Skip to content

Instantly share code, notes, and snippets.

@RoyBellingan
Last active June 24, 2022 12:48
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 RoyBellingan/036f288281d4c3f248ec427648197e5a to your computer and use it in GitHub Desktop.
Save RoyBellingan/036f288281d4c3f248ec427648197e5a to your computer and use it in GitHub Desktop.
Raspberry pi sensor hat temperature and pressure logger
/*
To autostart
crontab -e
* * * * * cd "/wherever you put the file/" && ./FILE_NAME
*/
#include "LPS22HB.h"
#include <bcm2835.h>
#include <math.h>
#include <stdio.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
char I2C_readByte(char reg) {
char buf[] = {reg};
bcm2835_i2c_read_register_rs(buf, buf, 1);
return buf[0];
}
unsigned short I2C_readU16(char reg) {
char buf[] = {reg, 0};
bcm2835_i2c_read_register_rs(buf, buf, 2);
int value = buf[1] * 0x100 + buf[0];
return value;
}
void I2C_writeByte(char reg, char val) {
char buf[] = {reg, val};
bcm2835_i2c_write(buf, 2);
}
void LPS22HB_RESET() {
uint8_t Buf;
Buf = I2C_readU16(LPS_CTRL_REG2);
Buf |= 0x04;
I2C_writeByte(LPS_CTRL_REG2, Buf); //SWRESET Set 1
while (Buf) {
Buf = I2C_readU16(LPS_CTRL_REG2);
Buf &= 0x04;
}
}
void LPS22HB_START_ONESHOT() {
uint8_t Buf;
Buf = I2C_readU16(LPS_CTRL_REG2);
Buf |= 0x01; //ONE_SHOT Set 1
I2C_writeByte(LPS_CTRL_REG2, Buf);
}
uint8_t LPS22HB_INIT() {
printf("Please run this as root, else the internal lib will crash NOW!\n");
bcm2835_i2c_begin();
bcm2835_i2c_setSlaveAddress(LPS22HB_I2C_ADDRESS); //切记不能把I2C关掉
bcm2835_i2c_set_baudrate(10000);
if (I2C_readByte(LPS_WHO_AM_I) != LPS_ID)
return 0; //Check device ID
LPS22HB_RESET(); //Wait for reset to complete
I2C_writeByte(LPS_CTRL_REG1, 0x02); //Low-pass filter disabled , output registers not updated until MSB and LSB have been read , Enable Block Data Update , Set Output Data Rate to 0
return 1;
}
struct _IO_FILE* makeFile() {
time_t curr_time;
struct tm* curr_tm;
char dateTime[100];
time(&curr_time);
curr_tm = localtime(&curr_time);
struct stat st = {0};
if (stat("logs", &st) == -1) {
mkdir("logs", 0700);
}
strftime(dateTime, 50, "logs/%Y-%m-%d_%H:%M:%S.csv", curr_tm);
printf("We will print into %s\n", dateTime);
struct _IO_FILE* file = fopen(dateTime, "w+");
if (file == 0) {
printf("sadNoise.wav Impossible to open file %s", dateTime);
exit(1);
}
return file;
}
/**
* Bla bla bla this will check the program is not already running using a classical technique
*/
void fLockCheck() {
// check if there is another instance running...
int fd = open("logger.lock", O_CREAT | O_RDWR, 0666);
if (fd == -1) {
printf("impossible to open logger.lock");
exit(1);
}
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
printf("logger.lock is already locked, I refuse to start.\n (The application is already running.)\n");
exit(1);
}
}
int main(int argc, char** argv) {
fLockCheck();
struct _IO_FILE* logFile = makeFile();
int delay = 30;
if (argc == 1) {
} else {
delay = atoi(argv[1]);
}
printf("this will run with a delay of %i s \n", delay);
float PRESS_DATA = 0;
float TEMP_DATA = 0;
uint8_t u8Buf[3];
if (!bcm2835_init())
return 1;
printf("\nPressure Sensor Test Program ...\n");
if (!LPS22HB_INIT()) {
printf("\nPressure Sensor Error\n");
return 0;
}
printf("\nPressure Sensor OK\n");
//because the first read is usually 0, we just skip it
LPS22HB_START_ONESHOT(); //Trigger one shot data acquisition
if ((I2C_readByte(LPS_STATUS) & 0x01) == 0x01) //a new pressure data is generated
{
u8Buf[0] = I2C_readByte(LPS_PRESS_OUT_XL);
u8Buf[1] = I2C_readByte(LPS_PRESS_OUT_L);
u8Buf[2] = I2C_readByte(LPS_PRESS_OUT_H);
PRESS_DATA = (float)((u8Buf[2] << 16) + (u8Buf[1] << 8) + u8Buf[0]) / 4096.0f;
}
if ((I2C_readByte(LPS_STATUS) & 0x02) == 0x02) // a new pressure data is generated
{
u8Buf[0] = I2C_readByte(LPS_TEMP_OUT_L);
u8Buf[1] = I2C_readByte(LPS_TEMP_OUT_H);
TEMP_DATA = (float)((u8Buf[1] << 8) + u8Buf[0]) / 100.0f;
}
//should be well enought for he sensor to start working
sleep(1);
printf("unixTs,DateTime,Pressure hPa,Temperature °c\n");
while (1) {
LPS22HB_START_ONESHOT(); //Trigger one shot data acquisition
if ((I2C_readByte(LPS_STATUS) & 0x01) == 0x01) //a new pressure data is generated
{
u8Buf[0] = I2C_readByte(LPS_PRESS_OUT_XL);
u8Buf[1] = I2C_readByte(LPS_PRESS_OUT_L);
u8Buf[2] = I2C_readByte(LPS_PRESS_OUT_H);
PRESS_DATA = (float)((u8Buf[2] << 16) + (u8Buf[1] << 8) + u8Buf[0]) / 4096.0f;
}
if ((I2C_readByte(LPS_STATUS) & 0x02) == 0x02) // a new pressure data is generated
{
u8Buf[0] = I2C_readByte(LPS_TEMP_OUT_L);
u8Buf[1] = I2C_readByte(LPS_TEMP_OUT_H);
TEMP_DATA = (float)((u8Buf[1] << 8) + u8Buf[0]) / 100.0f;
}
char buffer[256];
//this will give plain unix ts
time_t t = time(NULL);
//this will convert the unix ts in a struct with the human format
struct tm tm = *localtime(&t);
sprintf(buffer, "%u,%d-%02d-%02d %02d:%02d:%02d,%7.2f,%6.2f\n", (unsigned)time(NULL), tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, PRESS_DATA, TEMP_DATA);
printf("%s", buffer);
fputs(buffer, logFile);
fflush(logFile);
sleep(delay);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment