/*!
* @file
*
* @brief Library for the TC47A* I2C temperature sensors
*
* @author Blake Bourque
*
* @date Mar 5, 2014
*
* Provides readTempInC and readTempInF
*
*/
#include <stdio.h> //*printf, pclose/popen
#include <string.h> //strcpy
#include <stdlib.h> //strtol
#include "TC74.h"
// Private functions
int exec(char *command, char *out, int out_len);
float c2f(float f);
// Public function documented in header
int readTempInC(int bus, TC74_t addy)
{
#define C_LEN 20 //length of command
#define B_LEN 3 //length of bus
#define A_LEN 10 //length of addy
#define PADD 6 //leave some extra space
#define T_LEN 6 //Max length of temperature string
char i2c_command[A_LEN+B_LEN+C_LEN+PADD];
strncpy(i2c_command, "/usr/sbin/i2cget -y", 20);
if (bus == 1) {
strncat(i2c_command, " 1", B_LEN);
}
else if (bus == 0) {
strncat(i2c_command, " 0", B_LEN);
}
else {
fprintf(stderr, "Valid values for bus are [0,1] %d is invalid.\n", bus);
return -1;
}
char addystr[A_LEN];
int ret = snprintf(addystr, A_LEN, " 0x%x", addy);
if (ret < 0) {
fprintf(stderr, "Unable to generate command string.\n");
return -2;
}
else if (ret > A_LEN) {
fprintf(stderr, "%d characters were truncated.\n", ret-A_LEN);
}
strncat(i2c_command, addystr, A_LEN);
//printf("%s\n", i2c_command);
char temp[T_LEN];
ret = exec(i2c_command, temp, T_LEN);
if (ret < 0)
{
return -3;
}
//parse the temperature
return strtol(temp, NULL, 16); //@todo This might not handle negative tempertatures well
}
// Public function documented in header
float readTempInF(int bus, TC74_t addy)
{
int ret = readTempInC(bus, addy); //@todo what happens to negative return values
return c2f(ret);
}
/**
* Execute the command on the shell and give the first out_len characters from the
* first line of output to the caller by placing them in the caller allocated buffer.
* @param command command to run on the shell
* @param out a caller allocated buffer of out_len length
* @param out_len the max number of characters to return
* @return 0 on success, < 0 on error
*/
int exec(char *command, char *out, int out_len)
{
FILE *fp;
//Open the command for reading.
fp = popen(command, "r");
if (fp == NULL) {
fprintf(stderr, "Failed to run command %s\n", command);
return -1;
}
// Read the output a line at a time - output it.
// while (fgets(path, sizeof(path)-1, fp) != NULL) {
// printf("%s", path);
// }
//read the first line and send it back to the caller
char *ret = fgets(out, out_len-1, fp);
if (ret == NULL)
{
fprintf(stderr, "Unable to read output from command %s\n", command);
return -2;
}
//close
pclose(fp);
return 0;
}
/**
* Convert Celsius to Fahrenheit
* @param c Celsius temperature
* @return Fahrenheit temperature
*/
float c2f(float c)
{
float _temp = c*9.0;
_temp /= 5;
_temp += 32;
return _temp;
}
/*!
* @file
*
* @brief Library for the TC47A* I2C temperature sensors
*
* @author Blake Bourque
*
* @date Mar 5, 2014
*
* Provides readTempInC and readTempInF (header)
*
*/
#ifndef __TC74_h__
#define __TC74_h__
typedef enum {
TC74A0 = 0x48,
TC74A1 = 0x49,
TC74A2 = 0x4a,
TC74A3 = 0x4b,
TC74A4 = 0x4c,
TC74A5 = 0x4d,
TC74A6 = 0x4e,
TC74A7 = 0x4f
} TC74_t;
/**
* Reads the temperature from the sensor at address on the given bus.
* Accurate to plus or minus 2 deg C.
* @param bus 0 or 1: RPIv2 bus 1 is broken out on P1 header
* @param addy address of a TC74 sensor
* @return temperature in Celsius
*/
int readTempInC(int bus, TC74_t addy);
/**
* Reads the temperature from the sensor at address on the given bus and converts
* the temp to Fahrenheit.
* @param bus 0 or 1: RPIv2 bus 1 is broken out on P1 header
* @param addy address of a TC74 sensor
* @return temperature in Fahrenheit
*/
float readTempInF(int bus, TC74_t addy);
#endif //__TC74_h__