mirror of
https://github.com/eddyem/eddys_snippets.git
synced 2025-12-06 02:35:12 +03:00
Made refactoring for multi-sensor ability (N same sensors); check AHT21. I cry: I need this pointer in C!!!
This commit is contained in:
parent
7f85861d6c
commit
b0097d5ee6
@ -19,18 +19,18 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <usefull_macros.h>
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
#include "i2c.h"
|
|
||||||
#include "BMP180.h"
|
#include "BMP180.h"
|
||||||
|
#include "i2c.h"
|
||||||
|
#include "sensors_private.h"
|
||||||
|
|
||||||
static uint8_t addr = 0x77;
|
|
||||||
|
|
||||||
typedef enum{
|
enum{
|
||||||
BMP180_OVERS_1 = 0, // oversampling is off
|
BMP180_OVERS_1 = 0, // oversampling is off
|
||||||
BMP180_OVERS_2 = 1,
|
BMP180_OVERS_2 = 1,
|
||||||
BMP180_OVERS_4 = 2,
|
BMP180_OVERS_4 = 2,
|
||||||
BMP180_OVERS_8 = 3,
|
BMP180_OVERS_8 = 3,
|
||||||
BMP180_OVERSMAX = 4
|
BMP180_OVERSMAX = 3
|
||||||
} BMP180_oversampling;
|
};
|
||||||
|
|
||||||
#define BMP180_CHIP_ID 0x55
|
#define BMP180_CHIP_ID 0x55
|
||||||
|
|
||||||
@ -50,6 +50,8 @@ typedef enum{
|
|||||||
#define BMP180_CTRLM_OSS_SHIFT (6)
|
#define BMP180_CTRLM_OSS_SHIFT (6)
|
||||||
// start measurement
|
// start measurement
|
||||||
#define BMP180_CTRLM_SCO (1<<5)
|
#define BMP180_CTRLM_SCO (1<<5)
|
||||||
|
// measurements of P flag
|
||||||
|
#define BMP180_CTRLM_PRES (1<<4)
|
||||||
// write it to BMP180_REG_SOFTRESET for soft reset
|
// write it to BMP180_REG_SOFTRESET for soft reset
|
||||||
#define BMP180_SOFTRESET_VAL (0xB6)
|
#define BMP180_SOFTRESET_VAL (0xB6)
|
||||||
// start measurement of T/P
|
// start measurement of T/P
|
||||||
@ -64,9 +66,10 @@ typedef enum{
|
|||||||
|
|
||||||
static waitmsr_t wait4 = WAIT_NONE;
|
static waitmsr_t wait4 = WAIT_NONE;
|
||||||
|
|
||||||
static BMP180_oversampling bmp180_os = BMP180_OVERSMAX;
|
// mind that user can't change this
|
||||||
|
static const uint8_t bmp180_os = BMP180_OVERSMAX;
|
||||||
|
|
||||||
static struct {
|
typedef struct {
|
||||||
int16_t AC1;
|
int16_t AC1;
|
||||||
int16_t AC2;
|
int16_t AC2;
|
||||||
int16_t AC3;
|
int16_t AC3;
|
||||||
@ -80,45 +83,35 @@ static struct {
|
|||||||
int16_t MD;
|
int16_t MD;
|
||||||
int32_t MCfix;
|
int32_t MCfix;
|
||||||
int32_t AC1_fix;
|
int32_t AC1_fix;
|
||||||
} __attribute__ ((packed)) CaliData = {0};
|
int32_t Tuncomp; // uncompensated T value
|
||||||
|
} __attribute__ ((packed)) CaliData_t;
|
||||||
static sensor_status_t bmpstatus = SENS_NOTINIT;
|
|
||||||
static uint8_t calidata_rdy = 0;
|
|
||||||
//static uint32_t milliseconds_start = 0; // time of measurement start
|
|
||||||
//static uint32_t p_delay = 8; // delay for P measurement
|
|
||||||
static uint8_t uncomp_data[3]; // raw uncompensated data
|
|
||||||
static int32_t Tval; // uncompensated T value
|
|
||||||
// compensated values:
|
|
||||||
static uint32_t Pmeasured; // Pa
|
|
||||||
static float Tmeasured; // degC
|
|
||||||
static uint8_t devID = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static void BMP180_setOS(BMP180_oversampling os){
|
static void BMP180_setOS(BMP180_oversampling os){
|
||||||
bmp180_os = os & 0x03;
|
bmp180_os = os & 0x03;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
// get compensation data, return 1 if OK
|
// get compensation data, return 1 if OK
|
||||||
static int readcompdata(){
|
static int readcompdata(sensor_t *s){
|
||||||
FNAME();
|
FNAME();
|
||||||
if(!i2c_read_data8(BMP180_REG_CALIB, sizeof(CaliData), (uint8_t*)&CaliData)) return FALSE;
|
if(!s->privdata){
|
||||||
// convert big-endian into little-endian
|
s->privdata = malloc(sizeof(CaliData_t));
|
||||||
uint8_t *arr = (uint8_t*)&CaliData;
|
DBG("ALLOCA");
|
||||||
for(int i = 0; i < (int)sizeof(CaliData); i+=2){
|
|
||||||
register uint8_t val = arr[i];
|
|
||||||
arr[i] = arr[i+1];
|
|
||||||
arr[i+1] = val;
|
|
||||||
}
|
}
|
||||||
|
if(!i2c_read_data8(BMP180_REG_CALIB, sizeof(CaliData_t), (uint8_t*)s->privdata)) return FALSE;
|
||||||
|
CaliData_t *CaliData = (CaliData_t*)s->privdata;
|
||||||
|
// convert big-endian into little-endian
|
||||||
|
uint16_t *arr = (uint16_t*)(s->privdata);
|
||||||
|
for(int i = 0; i < 11; ++i) arr[i] = __builtin_bswap16(arr[i]);
|
||||||
// prepare for further calculations
|
// prepare for further calculations
|
||||||
CaliData.MCfix = CaliData.MC << 11;
|
CaliData->MCfix = CaliData->MC << 11;
|
||||||
CaliData.AC1_fix = CaliData.AC1 << 2;
|
CaliData->AC1_fix = CaliData->AC1 << 2;
|
||||||
calidata_rdy = 1;
|
s->private = 1; // use private for calibration ready flag
|
||||||
DBG("Calibration rdy");
|
DBG("Calibration rdy");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do a soft-reset procedure
|
// do a soft-reset procedure
|
||||||
static int BMP180_reset(){
|
static int BMP180_reset(sensor_t _U_ *s){
|
||||||
if(!i2c_write_reg8(BMP180_REG_SOFTRESET, BMP180_SOFTRESET_VAL)){
|
if(!i2c_write_reg8(BMP180_REG_SOFTRESET, BMP180_SOFTRESET_VAL)){
|
||||||
DBG("Can't reset\n");
|
DBG("Can't reset\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -127,9 +120,10 @@ static int BMP180_reset(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read compensation data & write registers
|
// read compensation data & write registers
|
||||||
static int BMP180_init(){
|
static int BMP180_init(sensor_t *s){
|
||||||
bmpstatus = SENS_NOTINIT ;
|
s->status = SENS_NOTINIT;
|
||||||
if(!BMP180_reset()) return FALSE;
|
if(!BMP180_reset(s)) return FALSE;
|
||||||
|
uint8_t devID;
|
||||||
if(!i2c_read_reg8(BMP180_REG_ID, &devID)){
|
if(!i2c_read_reg8(BMP180_REG_ID, &devID)){
|
||||||
DBG("Can't read BMP180_REG_ID");
|
DBG("Can't read BMP180_REG_ID");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -139,50 +133,54 @@ static int BMP180_init(){
|
|||||||
DBG("Not BMP180\n");
|
DBG("Not BMP180\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if(!readcompdata()){
|
if(!readcompdata(s)){
|
||||||
DBG("Can't read calibration data\n");
|
DBG("Can't read calibration data\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}else{
|
}else{
|
||||||
DBG("AC1=%d, AC2=%d, AC3=%d, AC4=%u, AC5=%u, AC6=%u", CaliData.AC1, CaliData.AC2, CaliData.AC3, CaliData.AC4, CaliData.AC5, CaliData.AC6);
|
#ifdef EBUG
|
||||||
DBG("B1=%d, B2=%d", CaliData.B1, CaliData.B2);
|
CaliData_t *CaliData = (CaliData_t*)s->privdata;
|
||||||
DBG("MB=%d, MC=%d, MD=%d", CaliData.MB, CaliData.MC, CaliData.MD);
|
#endif
|
||||||
|
DBG("AC1=%d, AC2=%d, AC3=%d, AC4=%u, AC5=%u, AC6=%u", CaliData->AC1, CaliData->AC2, CaliData->AC3, CaliData->AC4, CaliData->AC5, CaliData->AC6);
|
||||||
|
DBG("B1=%d, B2=%d", CaliData->B1, CaliData->B2);
|
||||||
|
DBG("MB=%d, MC=%d, MD=%d", CaliData->MB, CaliData->MC, CaliData->MD);
|
||||||
}
|
}
|
||||||
bmpstatus = SENS_RELAX;
|
s->status = SENS_RELAX;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start measurement, @return 1 if all OK
|
// start measurement, @return 1 if all OK
|
||||||
static int BMP180_start(){
|
static int BMP180_start(sensor_t *s){
|
||||||
if(!calidata_rdy || bmpstatus == SENS_BUSY) return FALSE;
|
if(!s->privdata || s->status == SENS_BUSY) return FALSE;
|
||||||
uint8_t reg = BMP180_READ_T | BMP180_CTRLM_SCO;
|
uint8_t reg = BMP180_READ_T | BMP180_CTRLM_SCO;
|
||||||
if(!i2c_write_reg8(BMP180_REG_CTRLMEAS, reg)){
|
if(!i2c_write_reg8(BMP180_REG_CTRLMEAS, reg)){
|
||||||
bmpstatus = SENS_ERR;
|
s->status = SENS_ERR;
|
||||||
DBG("Can't write CTRL reg\n");
|
DBG("Can't write CTRL reg\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
bmpstatus = SENS_BUSY;
|
s->status = SENS_BUSY;
|
||||||
wait4 = WAIT_T;
|
wait4 = WAIT_T;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// calculate T degC and P in Pa
|
// calculate T degC and P in Pa
|
||||||
static inline void compens(uint32_t Pval){
|
static inline void compens(sensor_t *s, uint32_t Pval){
|
||||||
|
CaliData_t *CaliData = (CaliData_t*)s->privdata;
|
||||||
// T:
|
// T:
|
||||||
int32_t X1 = ((Tval - CaliData.AC6)*CaliData.AC5) >> 15;
|
int32_t X1 = ((CaliData->Tuncomp - CaliData->AC6)*CaliData->AC5) >> 15;
|
||||||
int32_t X2 = CaliData.MCfix / (X1 + CaliData.MD);
|
int32_t X2 = CaliData->MCfix / (X1 + CaliData->MD);
|
||||||
int32_t B5 = X1 + X2;
|
int32_t B5 = X1 + X2;
|
||||||
Tmeasured = (B5 + 8.) / 160.;
|
s->data.T = (B5 + 8.) / 160.;
|
||||||
// P:
|
// P:
|
||||||
int32_t B6 = B5 - 4000;
|
int32_t B6 = B5 - 4000;
|
||||||
X1 = (CaliData.B2 * ((B6*B6) >> 12)) >> 11;
|
X1 = (CaliData->B2 * ((B6*B6) >> 12)) >> 11;
|
||||||
X2 = (CaliData.AC2 * B6) >> 11;
|
X2 = (CaliData->AC2 * B6) >> 11;
|
||||||
int32_t X3 = X1 + X2;
|
int32_t X3 = X1 + X2;
|
||||||
int32_t B3 = (((CaliData.AC1_fix + X3) << bmp180_os) + 2) >> 2;
|
int32_t B3 = (((CaliData->AC1_fix + X3) << bmp180_os) + 2) >> 2;
|
||||||
X1 = (CaliData.AC3 * B6) >> 13;
|
X1 = (CaliData->AC3 * B6) >> 13;
|
||||||
X2 = (CaliData.B1 * ((B6 * B6) >> 12)) >> 16;
|
X2 = (CaliData->B1 * ((B6 * B6) >> 12)) >> 16;
|
||||||
X3 = ((X1 + X2) + 2) >> 2;
|
X3 = ((X1 + X2) + 2) >> 2;
|
||||||
uint32_t B4 = (CaliData.AC4 * (uint32_t) (X3 + 32768)) >> 15;
|
uint32_t B4 = (CaliData->AC4 * (uint32_t) (X3 + 32768)) >> 15;
|
||||||
uint32_t B7 = (uint32_t)((int32_t)Pval - B3) * (50000 >> bmp180_os);
|
uint32_t B7 = (uint32_t)((int32_t)Pval - B3) * (50000 >> bmp180_os);
|
||||||
int32_t p = 0;
|
int32_t p = 0;
|
||||||
if(B7 < 0x80000000){
|
if(B7 < 0x80000000){
|
||||||
@ -194,86 +192,65 @@ static inline void compens(uint32_t Pval){
|
|||||||
X1 *= X1;
|
X1 *= X1;
|
||||||
X1 = (X1 * 3038) >> 16;
|
X1 = (X1 * 3038) >> 16;
|
||||||
X2 = (-7357 * p) / 65536;
|
X2 = (-7357 * p) / 65536;
|
||||||
Pmeasured = p + ((X1 + X2 + 3791) / 16);
|
s->data.P = (p + ((X1 + X2 + 3791) / 16)) / 100.; // convert to hPa
|
||||||
}
|
}
|
||||||
|
|
||||||
static int still_measuring(){
|
static sensor_status_t BMP180_process(sensor_t *s){
|
||||||
uint8_t reg;
|
uint8_t reg, stat;
|
||||||
if(!i2c_read_reg8(BMP180_REG_CTRLMEAS, ®)) return TRUE;
|
uint8_t uncomp_data[3];
|
||||||
if(reg & BMP180_CTRLM_SCO){
|
CaliData_t *CaliData = (CaliData_t*)s->privdata;
|
||||||
return TRUE;
|
if(s->status != SENS_BUSY) goto ret;
|
||||||
}
|
if(!i2c_read_reg8(BMP180_REG_CTRLMEAS, &stat)){ s->status = SENS_ERR; goto ret; }
|
||||||
return FALSE;
|
DBG("stat=0x%02X", stat);
|
||||||
}
|
if(stat & BMP180_CTRLM_SCO) goto ret; // still measure
|
||||||
|
if((stat & BMP180_CTRLM_PRES) == 0){ // wait for temperature
|
||||||
static sensor_status_t BMP180_process(){
|
|
||||||
uint8_t reg;
|
|
||||||
if(bmpstatus != SENS_BUSY) goto ret;
|
|
||||||
if(wait4 == WAIT_T){ // wait for temperature
|
|
||||||
if(still_measuring()) goto ret;
|
|
||||||
// get uncompensated data
|
// get uncompensated data
|
||||||
DBG("Read uncompensated T\n");
|
DBG("Read uncompensated T\n");
|
||||||
if(!i2c_read_data8(BMP180_REG_OUT, 2, uncomp_data)){
|
if(!i2c_read_data8(BMP180_REG_OUT, 2, uncomp_data)){
|
||||||
bmpstatus = SENS_ERR;
|
s->status = SENS_ERR;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
Tval = uncomp_data[0] << 8 | uncomp_data[1];
|
CaliData->Tuncomp = uncomp_data[0] << 8 | uncomp_data[1];
|
||||||
DBG("Start P measuring\n");
|
DBG("Tuncomp=%d, Start P measuring\n", CaliData->Tuncomp);
|
||||||
reg = BMP180_READ_P | BMP180_CTRLM_SCO | (bmp180_os << BMP180_CTRLM_OSS_SHIFT);
|
reg = BMP180_READ_P | BMP180_CTRLM_SCO | (bmp180_os << BMP180_CTRLM_OSS_SHIFT);
|
||||||
if(!i2c_write_reg8(BMP180_REG_CTRLMEAS, reg)){
|
if(!i2c_write_reg8(BMP180_REG_CTRLMEAS, reg)){
|
||||||
bmpstatus = SENS_ERR;
|
s->status = SENS_ERR;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
wait4 = WAIT_P;
|
|
||||||
}else{ // wait for pressure
|
}else{ // wait for pressure
|
||||||
if(still_measuring()) goto ret;
|
|
||||||
DBG("Read uncompensated P\n");
|
DBG("Read uncompensated P\n");
|
||||||
if(!i2c_read_data8(BMP180_REG_OUT, 3, uncomp_data)){
|
if(!i2c_read_data8(BMP180_REG_OUT, 3, uncomp_data)){
|
||||||
bmpstatus = SENS_ERR;
|
s->status = SENS_ERR;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
uint32_t Pval = uncomp_data[0] << 16 | uncomp_data[1] << 8 | uncomp_data[2];
|
uint32_t Pval = uncomp_data[0] << 16 | uncomp_data[1] << 8 | uncomp_data[2];
|
||||||
Pval >>= (8 - bmp180_os);
|
Pval >>= (8 - bmp180_os);
|
||||||
|
DBG("Puncomp=%d", Pval);
|
||||||
// calculate compensated values
|
// calculate compensated values
|
||||||
compens(Pval);
|
compens(s, Pval);
|
||||||
DBG("All data ready\n");
|
DBG("All data ready\n");
|
||||||
bmpstatus = SENS_RDY; // data ready
|
s->status = SENS_RDY; // data ready
|
||||||
wait4 = WAIT_NONE;
|
|
||||||
}
|
}
|
||||||
ret:
|
ret:
|
||||||
return bmpstatus;
|
return s->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read data & convert it
|
static sensor_props_t BMP180_props(sensor_t _U_ *s){
|
||||||
static int BMP180_getdata(sensor_data_t *d){
|
|
||||||
if(!d || bmpstatus != SENS_RDY) return FALSE;
|
|
||||||
d->T = Tmeasured;
|
|
||||||
d->P = Pmeasured / 100.; // convert Pa to hPa
|
|
||||||
bmpstatus = SENS_RELAX;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sensor_props_t BMP180_props(){
|
|
||||||
sensor_props_t p = {.T = 1, .P = 1};
|
sensor_props_t p = {.T = 1, .P = 1};
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t address(uint8_t new){
|
static int s_heater(sensor_t _U_ *s, int _U_ on){
|
||||||
if(new) addr = new;
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_heater(int _U_ on){
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor_t BMP180 = {
|
sensor_t BMP180 = {
|
||||||
.name = "BMP180",
|
.name = "BMP180",
|
||||||
.address = address,
|
.address = 0x77,
|
||||||
|
.status = SENS_NOTINIT,
|
||||||
.init = BMP180_init,
|
.init = BMP180_init,
|
||||||
.start = BMP180_start,
|
.start = BMP180_start,
|
||||||
.heater = s_heater,
|
.heater = s_heater,
|
||||||
.process = BMP180_process,
|
.process = BMP180_process,
|
||||||
.properties = BMP180_props,
|
.properties = BMP180_props,
|
||||||
.get_data = BMP180_getdata
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,12 +19,9 @@
|
|||||||
#include <usefull_macros.h>
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
#include "sensors_private.h"
|
||||||
#include "SI7005.h"
|
#include "SI7005.h"
|
||||||
|
|
||||||
static uint8_t addr = 0x40;
|
|
||||||
static double Tmeasured, Hmeasured;
|
|
||||||
static sensor_status_t status = SENS_NOTINIT;
|
|
||||||
|
|
||||||
#define SI7005_REGSTATUS 0
|
#define SI7005_REGSTATUS 0
|
||||||
#define SI7005_STATUSNRDY 1
|
#define SI7005_STATUSNRDY 1
|
||||||
#define SI7005_REGDATA 1
|
#define SI7005_REGDATA 1
|
||||||
@ -37,9 +34,9 @@ static sensor_status_t status = SENS_NOTINIT;
|
|||||||
|
|
||||||
#define SI7005_ID 0x50
|
#define SI7005_ID 0x50
|
||||||
|
|
||||||
static int s_init(){
|
static int s_init(sensor_t *s){
|
||||||
uint8_t ID;
|
uint8_t ID;
|
||||||
status = SENS_NOTINIT;
|
s->status = SENS_NOTINIT;
|
||||||
if(!i2c_read_reg8(SI7005_REGID, &ID)){
|
if(!i2c_read_reg8(SI7005_REGID, &ID)){
|
||||||
DBG("Can't read SI_REG_ID");
|
DBG("Can't read SI_REG_ID");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -49,16 +46,16 @@ static int s_init(){
|
|||||||
DBG("Not SI7005\n");
|
DBG("Not SI7005\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
status = SENS_RELAX;
|
s->status = SENS_RELAX;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_start(){
|
static int s_start(sensor_t *s){
|
||||||
if(status != SENS_RELAX) return FALSE;
|
if(s->status != SENS_RELAX) return FALSE;
|
||||||
status = SENS_BUSY;
|
s->status = SENS_BUSY;
|
||||||
if(!i2c_write_reg8(SI7005_REGCONFIG, SI7005_CONFTEMP | SI7005_CONFSTART)){
|
if(!i2c_write_reg8(SI7005_REGCONFIG, SI7005_CONFTEMP | SI7005_CONFSTART)){
|
||||||
DBG("Can't write start Tmeas");
|
DBG("Can't write start Tmeas");
|
||||||
status = SENS_ERR;
|
s->status = SENS_ERR;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
DBG("Wait for T\n");
|
DBG("Wait for T\n");
|
||||||
@ -66,64 +63,57 @@ static int s_start(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start humidity measurement
|
// start humidity measurement
|
||||||
static sensor_status_t si7005_cmdH(){
|
static sensor_status_t si7005_cmdH(sensor_t *s){
|
||||||
status = SENS_BUSY;
|
s->status = SENS_BUSY;
|
||||||
if(!i2c_write_reg8(SI7005_REGCONFIG, SI7005_CONFSTART)){
|
if(!i2c_write_reg8(SI7005_REGCONFIG, SI7005_CONFSTART)){
|
||||||
DBG("Can't write start Hmeas");
|
DBG("Can't write start Hmeas");
|
||||||
return (status = SENS_ERR);
|
return (s->status = SENS_ERR);
|
||||||
}
|
}
|
||||||
DBG("Wait for H");
|
DBG("Wait for H");
|
||||||
return status;
|
return s->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static sensor_status_t s_process(){
|
static sensor_status_t s_process(sensor_t *s){
|
||||||
uint8_t c, d[3];
|
uint8_t c, d[3];
|
||||||
if(status != SENS_BUSY) return status;
|
if(s->status != SENS_BUSY) return s->status;
|
||||||
if(!i2c_read_raw(d, 3)){
|
if(!i2c_read_raw(d, 3)){
|
||||||
DBG("Can't read status");
|
DBG("Can't read status");
|
||||||
return (status = SENS_ERR);
|
return (s->status = SENS_ERR);
|
||||||
}
|
}
|
||||||
//DBG("Status: 0x%02x, H: 0x%02x, L: 0x%02x", d[0], d[1], d[2]);
|
//DBG("Status: 0x%02x, H: 0x%02x, L: 0x%02x", d[0], d[1], d[2]);
|
||||||
if(!i2c_read_reg8(SI7005_REGCONFIG, &c)){
|
if(!i2c_read_reg8(SI7005_REGCONFIG, &c)){
|
||||||
DBG("Can't read config");
|
DBG("Can't read config");
|
||||||
return (status = SENS_ERR);
|
return (s->status = SENS_ERR);
|
||||||
}
|
}
|
||||||
//DBG("Config: 0x%02x", c);
|
//DBG("Config: 0x%02x", c);
|
||||||
if(d[0] & SI7005_STATUSNRDY){ // not ready yet
|
if(d[0] & SI7005_STATUSNRDY){ // not ready yet
|
||||||
return status;
|
return s->status;
|
||||||
}
|
}
|
||||||
uint16_t TH = (uint16_t)((d[1]<<8) | d[2]);
|
uint16_t TH = (uint16_t)((d[1]<<8) | d[2]);
|
||||||
if(c & SI7005_CONFTEMP){ // temperature measured
|
if(c & SI7005_CONFTEMP){ // temperature measured
|
||||||
TH >>= 2;
|
TH >>= 2;
|
||||||
Tmeasured = TH/32. - 50.;
|
double Tmeasured = TH/32. - 50.;
|
||||||
DBG("T=%.2f", Tmeasured);
|
DBG("T=%.2f", Tmeasured);
|
||||||
return si7005_cmdH();
|
s->data.T = Tmeasured;
|
||||||
|
return si7005_cmdH(s);
|
||||||
}else{ // humidity measured
|
}else{ // humidity measured
|
||||||
TH >>= 4;
|
// correct T/H
|
||||||
Hmeasured = TH/16.f - 24.f;
|
|
||||||
DBG("H=%.1f", Hmeasured);
|
|
||||||
status = SENS_RDY;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_getdata(sensor_data_t *d){
|
|
||||||
if(!d || status != SENS_RDY) return FALSE;
|
|
||||||
DBG("Measured T=%.1f, H=%.1f", Tmeasured, Hmeasured);
|
|
||||||
// correct T/H
|
|
||||||
#define A0 (-4.7844)
|
#define A0 (-4.7844)
|
||||||
#define A1 (0.4008)
|
#define A1 (0.4008)
|
||||||
#define A2 (-0.00393)
|
#define A2 (-0.00393)
|
||||||
d->H = Hmeasured - (A2*Hmeasured*Hmeasured + A1*Hmeasured + A0);
|
TH >>= 4;
|
||||||
d->T = Tmeasured;
|
double Hmeasured = TH/16.f - 24.f;
|
||||||
status = SENS_RELAX;
|
DBG("H=%.1f", Hmeasured);
|
||||||
return TRUE;
|
s->data.H = Hmeasured - (A2*Hmeasured*Hmeasured + A1*Hmeasured + A0);
|
||||||
|
s->status = SENS_RDY;
|
||||||
|
}
|
||||||
|
return s->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn heater on/off (1/0)
|
// turn heater on/off (1/0)
|
||||||
static int s_heater(int on){
|
static int s_heater(sensor_t *s, int on){
|
||||||
DBG("status=%d", status);
|
DBG("status=%d", s->status);
|
||||||
if(status != SENS_RELAX) return FALSE;
|
if(s->status != SENS_RELAX) return FALSE;
|
||||||
uint8_t reg = (on) ? SI7005_CONFHEAT : 0;
|
uint8_t reg = (on) ? SI7005_CONFHEAT : 0;
|
||||||
if(!i2c_write_reg8(SI7005_REGCONFIG, reg)){
|
if(!i2c_write_reg8(SI7005_REGCONFIG, reg)){
|
||||||
DBG("Can't write regconfig");
|
DBG("Can't write regconfig");
|
||||||
@ -132,23 +122,18 @@ static int s_heater(int on){
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static sensor_props_t s_props(){
|
static sensor_props_t s_props(sensor_t _U_ *s){
|
||||||
sensor_props_t p = {.T = 1, .H = 1, .htr = 1};
|
sensor_props_t p = {.T = 1, .H = 1, .htr = 1};
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t address(uint8_t new){
|
|
||||||
if(new) addr = new;
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
sensor_t SI7005 = {
|
sensor_t SI7005 = {
|
||||||
.name = "SI7005",
|
.name = "SI7005",
|
||||||
.address = address,
|
.address = 0x40,
|
||||||
|
.status = SENS_NOTINIT,
|
||||||
.init = s_init,
|
.init = s_init,
|
||||||
.start = s_start,
|
.start = s_start,
|
||||||
.heater = s_heater,
|
.heater = s_heater,
|
||||||
.process = s_process,
|
.process = s_process,
|
||||||
.properties = s_props,
|
.properties = s_props,
|
||||||
.get_data = s_getdata
|
|
||||||
};
|
};
|
||||||
|
|||||||
128
I2Csensors/aht.c
128
I2Csensors/aht.c
@ -20,42 +20,58 @@
|
|||||||
|
|
||||||
#include "aht.h"
|
#include "aht.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
#include "sensors_private.h"
|
||||||
static uint8_t addr = 0x38;
|
|
||||||
|
|
||||||
static sensor_status_t status = SENS_NOTINIT;
|
|
||||||
|
|
||||||
enum{
|
enum{
|
||||||
ISAHT10,
|
ISAHT1x,
|
||||||
ISAHT15,
|
ISAHT2x
|
||||||
ISAHT21b
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t rawH = 0, rawT = 0;
|
#define AHT_CMD_INITIALIZE 0xE1
|
||||||
|
#define AHT_CMD_MEASURE 0xAC
|
||||||
|
#define AHT_CMD_SOFT_RESET 0xBA
|
||||||
|
// status - for AHT21
|
||||||
|
#define AHT_CMD_STATUS 0x71
|
||||||
|
// init command bits:
|
||||||
|
// normal/cycle/command modes (bits 6:5) [non-documented!]:
|
||||||
|
#define AHT_INIT_NORMAL_MODE 0x00
|
||||||
|
#define AHT_INIT_CYCLE_MODE 0x20
|
||||||
|
#define AHT_INIT_CMD_MODE 0x40
|
||||||
|
// run calibration
|
||||||
|
#define AHT_INIT_CAL_ON 0x08
|
||||||
|
// zero byte for INIT/START cmd
|
||||||
|
#define AHT_NOP 0
|
||||||
|
// measurement control [non-documented!]
|
||||||
|
#define AHT_MEAS_CTRL 0x33
|
||||||
|
// status bits
|
||||||
|
#define AHT_STATUS_BUSY 0x80
|
||||||
|
#define AHT_STATUS_NORMAL_MODE 0x00
|
||||||
|
#define AHT_STATUS_CYCLE_MODE 0x20
|
||||||
|
#define AHT_STATUS_CMD_MODE 0x40
|
||||||
|
#define AHT_STATUS_CAL_ON 0x08
|
||||||
|
// status bits for AHT2x (both should be ones, or init again)
|
||||||
|
#define AHT_STATUS_CHK 0x18
|
||||||
|
|
||||||
#define AHT_CMD_INITIALIZE 0xE1
|
|
||||||
#define AHT_CMD_MEASURE 0xAC
|
|
||||||
#define AHT_CMD_SOFT_RESET 0xBA
|
|
||||||
// max reset time
|
// max reset time
|
||||||
#define RST_TIME (20e-3)
|
#define RST_TIME (20e-3)
|
||||||
// max data waiting time
|
// max data waiting time
|
||||||
#define DATA_TIME (75e-3)
|
#define DATA_TIME (75e-3)
|
||||||
|
|
||||||
static sensor_status_t s_poll(){
|
static sensor_status_t s_poll(){
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
if(!i2c_read_raw(&b, 1)) return SENS_ERR;
|
if(!i2c_read_raw(&b, 1)) return SENS_ERR;
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
if(b & 0x80) printf("BUSY ");
|
if(b & AHT_STATUS_BUSY) printf("BUSY ");
|
||||||
static const char *modes[] = {"NOR", "CYC", "CMD", "CMD"};
|
static const char *modes[] = {"NOR", "CYC", "CMD", "CMD"};
|
||||||
printf("MODE=%s ", modes[(b >> 6)&3]);
|
printf("MODE=%s ", modes[(b >> 6)&3]);
|
||||||
printf("%sCALIBRATED\n", b & 8 ? "" : "NOT ");
|
printf("%sCALIBRATED\n", b & AHT_STATUS_CAL_ON ? "" : "NOT ");
|
||||||
#endif
|
#endif
|
||||||
if(b & 0x80) return SENS_BUSY;
|
if(b & AHT_STATUS_BUSY) return SENS_BUSY;
|
||||||
return SENS_RELAX;
|
return SENS_RELAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_init(){
|
static int s_init(sensor_t *s){
|
||||||
status = SENS_NOTINIT;
|
s->status = SENS_NOTINIT;
|
||||||
if(!i2c_write_reg8(AHT_CMD_SOFT_RESET, 0)){
|
if(!i2c_write_reg8(AHT_CMD_SOFT_RESET, 0)){
|
||||||
DBG("Can't reset");
|
DBG("Can't reset");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -67,7 +83,7 @@ static int s_init(){
|
|||||||
}
|
}
|
||||||
if(t - t0 > RST_TIME) return SENS_ERR;
|
if(t - t0 > RST_TIME) return SENS_ERR;
|
||||||
DBG("Reseted");
|
DBG("Reseted");
|
||||||
uint8_t data[3] = {AHT_CMD_INITIALIZE, 0x08, 0};
|
uint8_t data[3] = {AHT_CMD_INITIALIZE, AHT_INIT_CAL_ON, AHT_NOP};
|
||||||
if(!i2c_write_raw(data, 3)){
|
if(!i2c_write_raw(data, 3)){
|
||||||
DBG("Can't init");
|
DBG("Can't init");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -79,13 +95,22 @@ static int s_init(){
|
|||||||
}
|
}
|
||||||
if(t - t0 > RST_TIME) return SENS_ERR;
|
if(t - t0 > RST_TIME) return SENS_ERR;
|
||||||
DBG("Inited");
|
DBG("Inited");
|
||||||
status = SENS_RELAX;
|
s->status = SENS_RELAX;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_start(){
|
static int s_start(sensor_t *s){
|
||||||
if(status != SENS_RELAX) return FALSE;
|
if(s->status != SENS_RELAX) return FALSE;
|
||||||
uint8_t data[3] = {AHT_CMD_MEASURE, 0x33, 0};
|
uint8_t data[3] = {AHT_CMD_MEASURE, AHT_MEAS_CTRL, AHT_NOP};
|
||||||
|
// the only difference between AHT1x and AHT2x
|
||||||
|
if(s->private == ISAHT2x){ // check status
|
||||||
|
uint8_t b;
|
||||||
|
if(!i2c_read_reg8(AHT_CMD_STATUS, &b)) return FALSE;
|
||||||
|
if((b & AHT_STATUS_CHK) != AHT_STATUS_CHK){
|
||||||
|
DBG("need init");
|
||||||
|
if(!s->init(s)) return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!i2c_write_raw(data, 3)){
|
if(!i2c_write_raw(data, 3)){
|
||||||
DBG("Can't start measuring");
|
DBG("Can't start measuring");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -94,60 +119,61 @@ static int s_start(){
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static sensor_status_t s_process(){
|
static sensor_status_t s_process(sensor_t *s){
|
||||||
sensor_status_t s = s_poll();
|
sensor_status_t st = s_poll();
|
||||||
if(s != SENS_RELAX) return (status = s);
|
if(st != SENS_RELAX) return (s->status = st);
|
||||||
uint8_t data[6];
|
uint8_t data[6];
|
||||||
if(!i2c_read_raw(data, 6)) return (status = SENS_ERR);
|
if(!i2c_read_raw(data, 6)) return (s->status = SENS_ERR);
|
||||||
DBG("Got @ %.3f", sl_dtime());
|
DBG("Got @ %.3f", sl_dtime());
|
||||||
rawH = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | (data[3] >> 4);
|
uint32_t rawH = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | (data[3] >> 4);
|
||||||
rawT = ((uint32_t)(data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | data[5];
|
uint32_t rawT = ((uint32_t)(data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | data[5];
|
||||||
DBG("rawH=%d, rawT=%d", rawH, rawT);
|
DBG("rawH=%d, rawT=%d", rawH, rawT);
|
||||||
return (status = SENS_RDY);
|
s->data.T = rawT * 200.0 / 1048576.0 - 50.0;
|
||||||
|
s->data.H = rawH * 100.0 / 1048576.0;
|
||||||
|
return (s->status = SENS_RDY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_getdata(sensor_data_t *d){
|
static sensor_props_t s_props(sensor_t _U_ *s){
|
||||||
if(!d || status != SENS_RDY) return FALSE;
|
|
||||||
d->T = rawT * 200.0 / 1048576.0 - 50.0;
|
|
||||||
d->H = rawH * 100.0 / 1048576.0;
|
|
||||||
status = SENS_RELAX;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sensor_props_t s_props(){
|
|
||||||
sensor_props_t p = {.T = 1, .H = 1};
|
sensor_props_t p = {.T = 1, .H = 1};
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t address(uint8_t new){
|
static int s_heater(sensor_t _U_ *s, int _U_ on){
|
||||||
if(new) addr = new;
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_heater(int _U_ on){
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor_t AHT10 = {
|
sensor_t AHT10 = {
|
||||||
.name = "AHT10",
|
.name = "AHT10",
|
||||||
.private = ISAHT10,
|
.private = ISAHT1x,
|
||||||
.address = address,
|
.address = 0x38,
|
||||||
|
.status = SENS_NOTINIT,
|
||||||
.init = s_init,
|
.init = s_init,
|
||||||
.start = s_start,
|
.start = s_start,
|
||||||
.heater = s_heater,
|
.heater = s_heater,
|
||||||
.process = s_process,
|
.process = s_process,
|
||||||
.properties = s_props,
|
.properties = s_props,
|
||||||
.get_data = s_getdata
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sensor_t AHT15 = {
|
sensor_t AHT15 = {
|
||||||
.name = "AHT15",
|
.name = "AHT15",
|
||||||
.private = ISAHT15,
|
.private = ISAHT1x,
|
||||||
.address = address,
|
.address = 0x38,
|
||||||
|
.status = SENS_NOTINIT,
|
||||||
|
.init = s_init,
|
||||||
|
.start = s_start,
|
||||||
|
.heater = s_heater,
|
||||||
|
.process = s_process,
|
||||||
|
.properties = s_props,
|
||||||
|
};
|
||||||
|
|
||||||
|
sensor_t AHT21 = {
|
||||||
|
.name = "AHT21",
|
||||||
|
.private = ISAHT2x,
|
||||||
|
.address = 0x38,
|
||||||
|
.status = SENS_NOTINIT,
|
||||||
.init = s_init,
|
.init = s_init,
|
||||||
.start = s_start,
|
.start = s_start,
|
||||||
.heater = s_heater,
|
.heater = s_heater,
|
||||||
.process = s_process,
|
.process = s_process,
|
||||||
.properties = s_props,
|
.properties = s_props,
|
||||||
.get_data = s_getdata
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,3 +21,4 @@
|
|||||||
|
|
||||||
extern sensor_t AHT10;
|
extern sensor_t AHT10;
|
||||||
extern sensor_t AHT15;
|
extern sensor_t AHT15;
|
||||||
|
extern sensor_t AHT21;
|
||||||
|
|||||||
@ -47,7 +47,7 @@ static sl_option_t cmdlnopts[] = {
|
|||||||
end_option
|
end_option
|
||||||
};
|
};
|
||||||
|
|
||||||
static int start(const sensor_t *s, uint8_t addr){
|
static int start(sensor_t *s, uint8_t addr){
|
||||||
if(!sensor_init(s, addr)){
|
if(!sensor_init(s, addr)){
|
||||||
WARNX("Can't init sensor");
|
WARNX("Can't init sensor");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -59,14 +59,14 @@ static int start(const sensor_t *s, uint8_t addr){
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int printdata(const sensor_t *s){
|
static int printdata(sensor_t *s){
|
||||||
sensor_data_t D;
|
sensor_data_t D;
|
||||||
if(!s->get_data(&D)){
|
if(!sensor_getdata(s, &D)){
|
||||||
WARNX("Can't read data, try again");
|
WARNX("Can't read data, try again");
|
||||||
if(!sensor_start(s)) WARNX("Oops: can't start");
|
if(!sensor_start(s)) WARNX("Oops: can't start");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
sensor_props_t props = s->properties();
|
sensor_props_t props = sensor_properties(s);
|
||||||
if(props.T) printf("T=%.2f\n", D.T);
|
if(props.T) printf("T=%.2f\n", D.T);
|
||||||
if(props.H) printf("H=%.2f\n", D.H);
|
if(props.H) printf("H=%.2f\n", D.H);
|
||||||
if(props.P){
|
if(props.P){
|
||||||
@ -87,19 +87,20 @@ int main(int argc, char **argv){
|
|||||||
if(!G.sensor) ERRX("Point sensor's name");
|
if(!G.sensor) ERRX("Point sensor's name");
|
||||||
if(G.slaveaddr && (G.slaveaddr < 8 || G.slaveaddr > 0x77)) ERRX("I2C address should be 7-bit and not forbidden");
|
if(G.slaveaddr && (G.slaveaddr < 8 || G.slaveaddr > 0x77)) ERRX("I2C address should be 7-bit and not forbidden");
|
||||||
if(!sensors_open(G.device)) ERR("Can't open %s", G.device);
|
if(!sensors_open(G.device)) ERR("Can't open %s", G.device);
|
||||||
const sensor_t* s = sensor_find(G.sensor);
|
sensor_t* s = sensor_new(G.sensor);
|
||||||
if(!s){ WARNX("Can't find sensor `%s` in supported list", G.sensor); goto clo; }
|
if(!s){ WARNX("Can't find sensor `%s` in supported list", G.sensor); goto clo; }
|
||||||
if(G.heater > -1){
|
if(G.heater > -1){
|
||||||
if(s->properties().htr && s->heater){
|
sensor_props_t props = sensor_properties(s);
|
||||||
|
if(props.htr){
|
||||||
if(!sensor_init(s, G.slaveaddr)) ERRX("Can't init device");
|
if(!sensor_init(s, G.slaveaddr)) ERRX("Can't init device");
|
||||||
if(!s->heater(G.heater)) WARNX("Cant run heater command");
|
if(!sensor_heater(s, G.heater)) WARNX("Cant run heater command");
|
||||||
else green("Heater is %s\n", G.heater ? "on" : "off");
|
else green("Heater is %s\n", G.heater ? "on" : "off");
|
||||||
}else ERRX("The sensor have no heater");
|
}else ERRX("The sensor have no heater");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!start(s, G.slaveaddr)) goto clo;
|
if(!start(s, G.slaveaddr)) goto clo;
|
||||||
while(1){
|
while(1){
|
||||||
sensor_status_t status = s->process();
|
sensor_status_t status = sensor_process(s);
|
||||||
if(status == SENS_RDY){ // data ready - get it
|
if(status == SENS_RDY){ // data ready - get it
|
||||||
if(!printdata(s)) continue;
|
if(!printdata(s)) continue;
|
||||||
break;
|
break;
|
||||||
@ -109,6 +110,7 @@ int main(int argc, char **argv){
|
|||||||
}
|
}
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
}
|
}
|
||||||
|
sensor_delete(&s);
|
||||||
|
|
||||||
clo:
|
clo:
|
||||||
sensors_close();
|
sensors_close();
|
||||||
|
|||||||
@ -22,11 +22,11 @@
|
|||||||
#include "aht.h"
|
#include "aht.h"
|
||||||
#include "BMP180.h"
|
#include "BMP180.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "sensor.h"
|
#include "sensors_private.h"
|
||||||
#include "SI7005.h"
|
#include "SI7005.h"
|
||||||
|
|
||||||
// NULL-terminated list of all supported sensors
|
// NULL-terminated list of all supported sensors
|
||||||
static const sensor_t* supported_sensors[] = {&AHT10, &AHT15, &BMP180, &SI7005, NULL};
|
static const sensor_t* supported_sensors[] = {&AHT10, &AHT15, &AHT21, &BMP180, &SI7005, NULL};
|
||||||
|
|
||||||
// just two stupid wrappers
|
// just two stupid wrappers
|
||||||
int sensors_open(const char *dev){
|
int sensors_open(const char *dev){
|
||||||
@ -37,9 +37,10 @@ void sensors_close(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init sensor with optional new address
|
// init sensor with optional new address
|
||||||
int sensor_init(const sensor_t *s, uint8_t address){
|
int sensor_init(sensor_t *s, uint8_t address){
|
||||||
if(!s) return FALSE;
|
if(!s) return FALSE;
|
||||||
address = s->address(address);
|
if(address) s->address = address;
|
||||||
|
else address = s->address; // default
|
||||||
if(!i2c_set_slave_address(address)){
|
if(!i2c_set_slave_address(address)){
|
||||||
DBG("Can't set slave address 0x%02x", address);
|
DBG("Can't set slave address 0x%02x", address);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -50,21 +51,32 @@ int sensor_init(const sensor_t *s, uint8_t address){
|
|||||||
}
|
}
|
||||||
double t0 = sl_dtime();
|
double t0 = sl_dtime();
|
||||||
int result = FALSE;
|
int result = FALSE;
|
||||||
while(sl_dtime() - t0 < I2C_TIMEOUT && !(result = s->init())) usleep(10000);
|
while(sl_dtime() - t0 < I2C_TIMEOUT && !(result = s->init(s))) usleep(10000);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find supported sensor by name
|
// find supported sensor by name and return allocated struct
|
||||||
const sensor_t* sensor_find(const char *name){
|
sensor_t *sensor_new(const char *name){
|
||||||
if(!name || !*name) return NULL;
|
if(!name || !*name) return NULL;
|
||||||
const sensor_t **p = supported_sensors;
|
const sensor_t **p = supported_sensors;
|
||||||
while(*p){
|
while(*p){
|
||||||
if(0 == strcmp((*p)->name, name)) return *p;
|
if(0 == strcmp((*p)->name, name)){
|
||||||
|
sensor_t *n = MALLOC(sensor_t, 1);
|
||||||
|
memcpy(n, *p, sizeof(sensor_t));
|
||||||
|
return n;
|
||||||
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sensor_delete(sensor_t **s){
|
||||||
|
if(!s || !*s) return;
|
||||||
|
if((*s)->privdata) FREE((*s)->privdata);
|
||||||
|
// here could be additional free's
|
||||||
|
FREE((*s));
|
||||||
|
}
|
||||||
|
|
||||||
// list all supported sensors
|
// list all supported sensors
|
||||||
void sensors_list(){
|
void sensors_list(){
|
||||||
const sensor_t **p = supported_sensors;
|
const sensor_t **p = supported_sensors;
|
||||||
@ -77,10 +89,34 @@ void sensors_list(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wrapper with timeout
|
// wrapper with timeout
|
||||||
int sensor_start(const sensor_t *s){
|
int sensor_start(sensor_t *s){
|
||||||
if(!s) return FALSE;
|
if(!s) return FALSE;
|
||||||
double t0 = sl_dtime();
|
double t0 = sl_dtime();
|
||||||
int result = FALSE;
|
int result = FALSE;
|
||||||
while(sl_dtime() - t0 < I2C_TIMEOUT && !(result = s->start())) usleep(10000);
|
while(sl_dtime() - t0 < I2C_TIMEOUT && !(result = s->start(s))) usleep(10000);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sensor_getdata(sensor_t *s, sensor_data_t *d){
|
||||||
|
if(!s || !d) return FALSE;
|
||||||
|
if(s->status != SENS_RDY) return FALSE;
|
||||||
|
*d = s->data;
|
||||||
|
s->status = SENS_RELAX;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor_status_t sensor_process(sensor_t *s){
|
||||||
|
if(!s) return FALSE;
|
||||||
|
return s->process(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor_props_t sensor_properties(sensor_t *s){
|
||||||
|
sensor_props_t def = {0};
|
||||||
|
if(!s) return def;
|
||||||
|
return s->properties(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sensor_heater(sensor_t *s, int on){
|
||||||
|
if(!s || !s->properties(s).htr || !s->heater) return FALSE;
|
||||||
|
return s->heater(s, on);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 17.0.2, 2025-10-11T01:16:49. -->
|
<!-- Written by QtCreator 17.0.2, 2025-10-12T01:47:56. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
@ -9,3 +9,4 @@ i2c.h
|
|||||||
main.c
|
main.c
|
||||||
sensor.c
|
sensor.c
|
||||||
sensor.h
|
sensor.h
|
||||||
|
sensors_private.h
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 85 B After Width: | Height: | Size: 103 B |
@ -43,21 +43,17 @@ typedef struct{
|
|||||||
double P;
|
double P;
|
||||||
} sensor_data_t;
|
} sensor_data_t;
|
||||||
|
|
||||||
typedef struct{
|
//struct sensor_struct;
|
||||||
const char *name; // name
|
typedef struct sensor_struct sensor_t;
|
||||||
uint32_t private; // private information (e.g. for almost similar sensors with some slight differences)
|
|
||||||
uint8_t (*address)(uint8_t new);// set/get sensor's address (get - if `new`==0)
|
|
||||||
int (*init)(); // init device - only @ start after POR
|
|
||||||
int (*start)(); // start measuring
|
|
||||||
int (*heater)(int); // turn heater on/off (1/0)
|
|
||||||
sensor_status_t (*process)(); // main polling process
|
|
||||||
sensor_props_t (*properties)(); // get properties
|
|
||||||
int (*get_data)(sensor_data_t*);// read data
|
|
||||||
} sensor_t;
|
|
||||||
|
|
||||||
int sensors_open(const char *dev);
|
int sensors_open(const char *dev);
|
||||||
void sensors_close();
|
void sensors_close();
|
||||||
int sensor_init(const sensor_t *s, uint8_t address);
|
|
||||||
void sensors_list();
|
void sensors_list();
|
||||||
const sensor_t* sensor_find(const char *name);
|
sensor_t* sensor_new(const char *name);
|
||||||
int sensor_start(const sensor_t *s);
|
void sensor_delete(sensor_t **s);
|
||||||
|
sensor_props_t sensor_properties(sensor_t *s);
|
||||||
|
int sensor_init(sensor_t *s, uint8_t address);
|
||||||
|
int sensor_heater(sensor_t *s, int on);
|
||||||
|
int sensor_start(sensor_t *s);
|
||||||
|
sensor_status_t sensor_process(sensor_t *s);
|
||||||
|
int sensor_getdata(sensor_t *s, sensor_data_t *d);
|
||||||
|
|||||||
36
I2Csensors/sensors_private.h
Normal file
36
I2Csensors/sensors_private.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "sensor.h"
|
||||||
|
|
||||||
|
// unfortunately, we have no "self" pointer in C, so we should add this struct calling to each function for further purposes
|
||||||
|
struct sensor_struct{
|
||||||
|
const char *name; // name
|
||||||
|
uint8_t address; // sensor's address
|
||||||
|
uint32_t private; // private information (e.g. for almost similar sensors with some slight differences)
|
||||||
|
void *privdata; // some private data for calibration etc
|
||||||
|
sensor_status_t status; // status of sensor
|
||||||
|
sensor_data_t data; // measured data
|
||||||
|
int (*init)(struct sensor_struct*); // init device - @ start after POR or in case of errors
|
||||||
|
int (*start)(struct sensor_struct*); // start measuring
|
||||||
|
int (*heater)(struct sensor_struct *, int); // turn heater on/off (1/0)
|
||||||
|
sensor_status_t (*process)(struct sensor_struct*); // main polling process
|
||||||
|
sensor_props_t (*properties)(struct sensor_struct*); // get properties
|
||||||
|
};
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user