Reputation: 45
So I was recruited to my school's Baja racing team where we design build and compete with offroad dune-buggy type cars. I am a CS major and have quite a bit experience with python, and therefore was asked to help out the electrical team to interface with all of the sensors which we wanted on the car. So far so good, but now I am using an IR temperature sensor which reads ambient and object temperatures. (We are going to put this somewhere on the engine to read it's temperature and output to our GUI)
The problem is that the only libraries that seem to have used this sensor are all written in C, and normally used with arduinos... Nonetheless I compiled and edited some C code that I found online and it works great! In C. :( Since our project is completely based in python; I'd really like some help reading this sensor via i2c and Python, although I really don't have a ton of experience in writing libraries, especially not for electronics. Any tips would be great to steer me in the correct direction. Here is the C code that we are currently using that I basically want the same thing in Python:
//fordit: gcc MLXi2c.c -o i2c -l bcm2835
#include <stdio.h>
#include <bcm2835.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include<time.h>
#define AVG 1 //averaging samples
#define LOGTIME 10 //loging period
int main(int argc, char **argv)
{
unsigned char buf[6];
unsigned char i,reg;
double temp=0,calc=0, skytemp,atemp;
FILE *flog;
flog=fopen("mlxlog.csv", "a");..
bcm2835_init();
bcm2835_i2c_begin();
bcm2835_i2c_set_baudrate(25000);.
// set address...........................................................................................
bcm2835_i2c_setSlaveAddress(0x5a);
....
printf("\nOk, your device is working!!\n");
....
....
while(1) {
time_t t = time(NULL);
<------>struct tm tm = *localtime(&t);
<------>calc=0;
<------>reg=7;
<------>for(i=0;i<AVG;i++){
<------> bcm2835_i2c_begin();
<------> bcm2835_i2c_write (®, 1);
<------> bcm2835_i2c_read_register_rs(®,&buf[0],3);
<------> temp = (double) (((buf[1]) << 8) + buf[0]);
<------> temp = (temp * 0.02)-0.01;
<--> temp = temp - 273.15;
<------> calc+=temp;
<------> sleep(1);
<------> }
<------>skytemp=calc/AVG;
<------>calc=0;
<------>reg=6;
<------>for(i=0;i<AVG;i++){
<------> bcm2835_i2c_begin();
<------> bcm2835_i2c_write (®, 1);
<------> bcm2835_i2c_read_register_rs(®,&buf[0],3);
<------> temp = (double) (((buf[1]) << 8) + buf[0]);
<------> temp = (temp * 0.02)-0.01;
<--> temp = temp - 273.15;
<------> calc+=temp;
<------> sleep(1);
<------> }
<------>atemp=calc/AVG;
<------>printf("%02d-%02d %02d:%02d:%02d\n Tambi=%04.2f C, Tobj=%04.2f C\n", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,atemp,skytemp);
<------>fprintf(flog,"%04d-%02d-%02d %02d:%02d:%02d,%04.2f,%04.02f\n",tm.tm_year+1900, tm.tm_mon +1, tm.tm_mday,tm.tm_hour, tm.tm_min, tm.tm_sec,atemp,skytemp);
<------>fflush(flog);
<------>sleep(LOGTIME-(2*AVG));
}
...
printf("[done]\n");
}
thanks in advance!
Upvotes: 1
Views: 5160
Reputation: 4010
Changes:
while(1)
- only one reading per execution. If the sensor requires repeated start, a for/while loop might be needed; just don't make it an infinite loop unless you plan on killing the process from python.printf
now outputs a JSON string delimited by a starting and ending pipe/|return 0;
to main()
so python's subprocess module knows
what's upSave this as mlx90614_query.c and compile:
//fordit: gcc mlx90614_query.c -o mlx90614_query -l bcm2835
#include <stdio.h>
#include <bcm2835.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#define AVG 1 //averaging samples
#define LOGTIME 10 //loging period
int main(int argc, char **argv)
{
unsigned char buf[6];
unsigned char i,reg;
double temp=0,calc=0, skytemp,atemp;
FILE *flog;
flog=fopen("mlxlog.csv", "a");
bcm2835_init();
bcm2835_i2c_begin();
bcm2835_i2c_set_baudrate(25000);
// set address
bcm2835_i2c_setSlaveAddress(0x5a);
printf("\nOk, your device is working!!\n");
time_t t = time(NULL);
struct tm tm = *localtime(&t);
calc=0;
reg=7;
for(i=0;i<AVG;i++){
bcm2835_i2c_begin();
bcm2835_i2c_write (®, 1);
bcm2835_i2c_read_register_rs(®,&buf[0],3);
temp = (double) (((buf[1]) << 8) + buf[0]);
temp = (temp * 0.02)-0.01;
temp = temp - 273.15;
calc+=temp;
sleep(1);
}
skytemp=calc/AVG;
calc=0;
reg=6;
for(i=0;i<AVG;i++){
bcm2835_i2c_begin();
bcm2835_i2c_write (®, 1);
bcm2835_i2c_read_register_rs(®,&buf[0],3);
temp = (double) (((buf[1]) << 8) + buf[0]);
temp = (temp * 0.02)-0.01;
temp = temp - 273.15;
calc+=temp;
sleep(1);
}
atemp=calc/AVG;
printf("|{\"time\":{\"month\":\"%02d\",\"day\":\"%02d\",\"hour\":\"%02d\",\"min\":\"%02d\",\"sec\":\"%02d\"},\"data\":{\"t_ambi\":\"%04.2f\",\"t_obj\":\"%04.2f\"}}|\n", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,atemp,skytemp);
fprintf(flog,"%04d-%02d-%02d %02d:%02d:%02d,%04.2f,%04.02f\n",tm.tm_year+1900, tm.tm_mon +1, tm.tm_mday,tm.tm_hour, tm.tm_min, tm.tm_sec,atemp,skytemp);
fflush(flog);
sleep(LOGTIME-(2*AVG));
printf("[done]\n");
return 0;
}
Your C program now outputs your existing debug messages plus this json ("|" used as delimiter):
{
"time": {
"month": "03",
"day": "09",
"hour": "20",
"min": "24",
"sec": "28"
},
"data": {
"t_ambi": "77.77",
"t_obj": "34.44"
}
}
Save this as a python script in the same folder as mlx90614_query (the extra spaces will cause trouble if you copy/paste to an interactive interpreter):
from __future__ import print_function
import json
import subprocess
import sys
sensor_dict = {}
py3 = False
# python version check determines string handling
try:
if (sys.version_info > (3, 0)):
py3 = True
except:
pass
try:
subp_ret = subprocess.check_output(["./mlx90614_query"])
# at this point, subprocess succeeded and subp_ret holds your output
if py3:
subp_ret = subp_ret.decode('utf8')
sensor_dict = json.loads(subp_ret.split("|")[1].strip())
# cast temperatures to float and print
for k in sensor_dict["data"]:
val = float(sensor_dict["data"][k])
sensor_dict["data"][k] = val
print (k, "\t", val)
# cast date/time segments to int and print
for k in sensor_dict["time"]:
val = int(sensor_dict["time"][k])
sensor_dict["time"][k] = val
print (k, "\t", val)
# Now go win that race! :P
except Exception as e:
print(str(e))
Output:
$ gcc mlx90614_query.c -o mlx90614_query -l bcm2835
$
$ ./mlx90614_query
Ok, your device is working!!
|{"time":{"month":"03","day":"09","hour":"21","min":"45","sec":"53"},"data":{"t_ambi":"0.00","t_obj":"0.00"}}|
[done]
$ python3.4 mlx_print.py
t_obj 34.44
t_ambi 77.77
hour 21
sec 33
min 58
month 3
day 9
$ python2 mlx_print.py
t_ambi 77.77
t_obj 34.44
min 58
sec 37
day 9
hour 21
month 3
Sorry for stealing your homework - Just <3 to code :D
Upvotes: 2