Created
November 12, 2013 01:53
-
-
Save dansimpson/7424069 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#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