Last active
October 24, 2017 16:43
-
-
Save unprolix/7298736 to your computer and use it in GitHub Desktop.
This code will allow a Rasperry Pi to read temperatures from the Freetronics infrared temperature sensor.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// irtemp.c | |
// Raspberry Pi code to read temperature from the Freetronics infrared temperature module. | |
// By Jeremy Bornstein <[email protected]> after the Arduino-specific code from Andy Gelme (@geekscape) | |
// See http://www.freetronics.com/irtemp for more information about the module. | |
// This code requires the wiringPi library to be installed. See http://wiringpi.com/ for more information. | |
// | |
// NOTE: On the author's system, isnan(FP_NAN) returns false. | |
// This is clearly an error which could impact this code; I haven't tracked it down yet. | |
// | |
// There is no makefile. This isn't polished up to be a library--just a demonstration. | |
// Compile with: | |
// gcc -o irtemp irtemp.c -lwiringPi | |
// and then run: | |
// ./irtemp | |
// ./irtemp ambient | |
// ./irtemp ir | |
// ./irtemp junk | |
#include <wiringPi.h> | |
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <math.h> | |
typedef unsigned char bool; | |
typedef unsigned char byte; | |
#define false 0 | |
#define true 1 | |
static const long IRTEMP_TIMEOUT = 2000; // milliseconds | |
static const long IRTEMP_DATA_AMBIENT = 0x66; | |
static const long IRTEMP_DATA_IR = 0x4C; | |
static const long IRTEMP_DATA_JUNK = 0x53; | |
// Customize these for your own pins. These are the wiringPi pin numbers. | |
const int ACQUIRE_PIN = 7; | |
const int DATA_PIN = 0; | |
const int CLOCK_PIN = 1; | |
#define DATA_SIZE 5 | |
bool capturing = false; | |
volatile unsigned char data_bit = 8; | |
volatile unsigned char data_byte = 0; | |
volatile byte data[DATA_SIZE]; | |
void clock_pin_falling (void) { | |
if (!capturing) return; | |
if (data_byte >= DATA_SIZE) return; | |
data_bit--; | |
byte value = digitalRead(DATA_PIN); | |
data[data_byte] |= value << data_bit; | |
if (data_bit == 0) { | |
data_bit = 8; | |
data_byte ++; | |
} | |
} | |
void reset_data() { | |
byte i; | |
for (i = 0; i < DATA_SIZE; i ++) data[i] = 0; | |
data_bit = 8; | |
data_byte = 0; | |
} | |
void sensor_enable(bool enabled) { | |
capturing = enabled; | |
digitalWrite(ACQUIRE_PIN, enabled ? LOW : HIGH); | |
} | |
float temperature_read() { | |
int msb = data[1] << 8; | |
int lsb = data[2]; | |
return((msb + lsb) / 16.0 - 273.15); | |
} | |
bool temperature_data_valid() { | |
byte checksum = (data[0] + data[1] + data[2]) & 0xFF; | |
return(data[3] == checksum && data[4] == 0x0d); | |
} | |
float temperature_retrieve(byte data_type) { | |
float temperature = FP_NAN; | |
bool temperature_valid = false; | |
long time_start = millis(); | |
bool done = false; | |
sensor_enable(true); | |
while (!done) { | |
reset_data(); | |
while (data_byte < DATA_SIZE) { | |
if ((millis() - time_start) > IRTEMP_TIMEOUT) { | |
printf("TIMEOUT\n"); | |
done = true; | |
break; | |
} | |
} | |
//printf("%x %x %x %x %x\n",data[0], data[1], data[2], data[3], data[4]); | |
if (!done && data[0] == data_type) { | |
if (temperature_data_valid()) { | |
temperature = temperature_read(); | |
done = true; | |
} | |
} | |
} | |
sensor_enable(false); | |
return(temperature); | |
} | |
void temperature_setup() { | |
wiringPiSetup(); // NOTE: uses "wiringPi" pin numbering scheme | |
pinMode(ACQUIRE_PIN, OUTPUT); | |
pinMode(DATA_PIN, INPUT); | |
pinMode(CLOCK_PIN, INPUT); | |
digitalWrite (ACQUIRE_PIN, HIGH); | |
digitalWrite (DATA_PIN, HIGH); | |
digitalWrite (CLOCK_PIN, HIGH); | |
wiringPiISR (CLOCK_PIN, INT_EDGE_FALLING, &clock_pin_falling); | |
} | |
void main(int argc, char *argv[]) { | |
temperature_setup(); | |
byte temperature_type = IRTEMP_DATA_IR; // default | |
if (argc > 2) { | |
printf("Specify no argument, or exactly one of: ir, ambient, junk\n"); | |
exit(-1); | |
} | |
if (argc == 2) { | |
if (!strcmp(argv[1], "ir")) | |
temperature_type = IRTEMP_DATA_IR; | |
else if (!strcmp(argv[1], "ambient")) | |
temperature_type = IRTEMP_DATA_AMBIENT; | |
else if (!strcmp(argv[1], "junk")) | |
temperature_type = IRTEMP_DATA_JUNK; | |
else { | |
printf("Invalid temperature type. Valid values are: ir, ambient, junk\n"); | |
exit(-1); | |
} | |
} | |
float temp = temperature_retrieve(temperature_type); | |
if (isnan(temp)) { | |
printf("N/A\n"); | |
} else { | |
printf("%f\n", temp); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment