Skip to content

Instantly share code, notes, and snippets.

@unprolix
Last active Oct 24, 2017
Embed
What would you like to do?
This code will allow a Rasperry Pi to read temperatures from the Freetronics infrared temperature sensor.
// irtemp.c
// Raspberry Pi code to read temperature from the Freetronics infrared temperature module.
// By Jeremy Bornstein <jeremy@jeremy.org> 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