Skip to content

Instantly share code, notes, and snippets.

@dansimpson
Created November 12, 2013 01:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dansimpson/7424069 to your computer and use it in GitHub Desktop.
Save dansimpson/7424069 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(array) sizeof(array) / sizeof(array[0])
static const char *device = "/dev/spidev1.0";
static uint8_t mode = SPI_MODE_0;
static uint8_t bits = 8;
static uint32_t clock = 500000;
static uint16_t delay = 1;
/*
* Arg parsing only for device now
*/
static void parse_opts(int argc, char *argv[]) {
while (1) {
static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ NULL, 0, 0, 0 }
};
int c = getopt_long(argc, argv, "D", lopts, NULL);
if (c == -1) {
break;
}
switch (c) {
case 'D':
device = optarg;
break;
default:
printf("Usage: %s [-Dj]\n", argv[0]);
puts(" -D --device device to use (default /dev/spidev1.0)\n");
exit(1);
break;
}
}
}
/*
* prepare the SPI bus
*/
static int prepare(int fd) {
if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) {
perror("Can't set mode");
return -1;
}
if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) {
perror("Can't set number of bits");
return -1;
}
if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &clock) == -1) {
perror("Can't set write clock");
return -1;
}
return 0;
}
/*
* Get the compensated probe temperature for the raw value
*/
double probe_temp(uint32_t raw) {
uint32_t masked = (raw >> 18) & 0x3FFF;
if((masked & 0x2000) == 0x2000) {
return ((~masked & 0x1FFF) + 1) * -1 * 0.25;
}
return (masked & 0x1FFF) * 0.25;
}
/*
* Get the reference temperature for the raw value
*/
double ref_temp(uint32_t raw) {
uint32_t masked = (raw >> 4) & 0xFFF;
if((masked & 0x800) == 0x800) {
return ((~masked & 0x7FF) + 1) * -1 * 0.0625;
}
return (masked & 0x7FF) * 0.0625;
}
/*
* Read the temperature data from the MAX31855
*/
uint32_t readmax38155(int fd) {
uint8_t tx[] = { 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = clock,
.bits_per_word = bits,
};
if (ioctl(fd, SPI_IOC_MESSAGE(1), &tr) == 1) {
perror("IO Error");
abort();
}
return (rx[0] << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3];
}
int main(int argc, char **argv) {
parse_opts(argc, argv);
int fd = open(device, O_RDWR);
if (fd <= 0) {
printf("Device %s not found\n", device);
return -1;
}
if (prepare(fd) == -1) {
return -1;
}
uint32_t raw = readmax38155(fd);
// no longer needed
close(fd);
// check flags for errors
char errors[128] = "";
if((raw & 0x10000) != 0) {
if((raw & 0x1) != 0) {
strcat(errors, "No connection. ");
}
if((raw & 0x2) != 0) {
strcat(errors, "Thermocouple short to ground. ");
}
if((raw & 0x4) != 0) {
strcat(errors, "Thermocouple short to VCC. ");
}
if(strlen(errors) == 0) {
strcat(errors, "Unknown error.");
}
}
// dump json
printf("{\"probe_temp\":%.2f,\"ref_temp\":%.2f,\"errors\":\"%s\"}",
probe_temp(raw),
ref_temp(raw),
errors);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment