1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2026-02-11 07:03:07 +01:00

add code for SHT4X, ENV4

This commit is contained in:
wellenvogel
2025-09-29 12:43:21 +02:00
parent 8bf8ada30e
commit 9831f8da85
10 changed files with 443 additions and 169 deletions

View File

@@ -71,15 +71,15 @@
#endif #endif
#GROVE #GROVE
//#ifdef M5_ENV4$GS$ #ifdef M5_ENV4$GS$
// #ifndef M5_GROOVEIIC$GS$ #ifndef M5_GROOVEIIC$GS$
// #define M5_GROOVEIIC$GS$ #define M5_GROOVEIIC$GS$
// #endif #endif
// GROOVE_IIC(SHT3X,$Z$,1) GROOVE_IIC(SHT4X,$Z$,1)
// GROOVE_IIC(BMP280,$Z$,1) GROOVE_IIC(BMP280,$Z$,1)
// #define _GWSHT3X #define _GWSHT4X
// #define _GWBMP280 #define _GWBMP280
//#endif #endif
#GROVE #GROVE
//example: -DSHT3XG1_A : defines STH3Xn1 on grove A - x depends on the other devices //example: -DSHT3XG1_A : defines STH3Xn1 on grove A - x depends on the other devices
@@ -100,6 +100,25 @@
#define _GWSHT3X #define _GWSHT3X
#endif #endif
#GROVE
//example: -DSHT4XG1_A : defines STH4Xn1 on grove A - x depends on the other devices
#ifdef GWSHT4XG1$GS$
#ifndef M5_GROOVEIIC$GS$
#define M5_GROOVEIIC$GS$
#endif
GROOVE_IIC(SHT4X,$Z$,1)
#define _GWSHT4X
#endif
#GROVE
#ifdef GWSHT4XG2$GS$
#ifndef M5_GROOVEIIC$GS$
#define M5_GROOVEIIC$GS$
#endif
GROOVE_IIC(SHT4X,$Z$,2)
#define _GWSHT4X
#endif
#GROVE #GROVE
#ifdef GWQMP6988G1$GS$ #ifdef GWQMP6988G1$GS$
#ifndef M5_GROOVEIIC$GS$ #ifndef M5_GROOVEIIC$GS$

View File

@@ -23,7 +23,7 @@ static std::vector<IICGrove> iicGroveList;
#include "GwBME280.h" #include "GwBME280.h"
#include "GwBMP280.h" #include "GwBMP280.h"
#include "GwQMP6988.h" #include "GwQMP6988.h"
#include "GwSHT3X.h" #include "GwSHTXX.h"
#include <map> #include <map>
#include "GwTimer.h" #include "GwTimer.h"

View File

@@ -1,138 +0,0 @@
#include "GwSHT3X.h"
#ifdef _GWSHT3X
class SHT3XConfig;
static GwSensorConfigInitializerList<SHT3XConfig> configs;
class SHT3XConfig : public IICSensorBase{
public:
String tmNam;
String huNam;
bool tmAct=false;
bool huAct=false;
tN2kHumiditySource huSrc;
tN2kTempSource tmSrc;
SHT3X *device=nullptr;
using IICSensorBase::IICSensorBase;
virtual bool isActive(){
return tmAct || huAct;
}
virtual bool initDevice(GwApi * api,TwoWire *wire){
if (! isActive()) return false;
device=new SHT3X();
device->init(addr,wire);
GwLog *logger=api->getLogger();
LOG_DEBUG(GwLog::LOG,"initialized %s at address %d, intv %ld",prefix.c_str(),(int)addr,intv);
return true;
}
virtual bool preinit(GwApi * api){
GwLog *logger=api->getLogger();
LOG_DEBUG(GwLog::LOG,"%s configured",prefix.c_str());
addHumidXdr(api,*this);
addTempXdr(api,*this);
return isActive();
}
virtual void measure(GwApi * api,TwoWire *wire, int counterId)
{
if (!device)
return;
GwLog *logger=api->getLogger();
int rt = 0;
if ((rt = device->get()) == 0)
{
double temp = device->cTemp;
temp = CToKelvin(temp);
double humid = device->humidity;
LOG_DEBUG(GwLog::DEBUG, "%s measure temp=%2.1f, humid=%2.0f",prefix.c_str(), (float)temp, (float)humid);
if (huAct)
{
sendN2kHumidity(api, *this, humid, counterId);
}
if (tmAct)
{
sendN2kTemperature(api, *this, temp, counterId);
}
}
else
{
LOG_DEBUG(GwLog::DEBUG, "unable to query %s: %d",prefix.c_str(), rt);
}
}
virtual void readConfig(GwConfigHandler *cfg){
if (ok) return;
configs.readConfig(this,cfg);
return;
}
};
SensorBase::Creator creator=[](GwApi *api,const String &prfx)-> SensorBase*{
if (! configs.knowsPrefix(prfx)) return nullptr;
return new SHT3XConfig(api,prfx);
};
SensorBase::Creator registerSHT3X(GwApi *api){
GwLog *logger=api->getLogger();
#if defined(GWSHT3X) || defined (GWSHT3X11)
{
api->addSensor(creator(api,"SHT3X11"));
CHECK_IIC1();
#pragma message "GWSHT3X11 defined"
}
#endif
#if defined(GWSHT3X12)
{
api->addSensor(creator(api,"SHT3X12"));
CHECK_IIC1();
#pragma message "GWSHT3X12 defined"
}
#endif
#if defined(GWSHT3X21)
{
api->addSensor(creator(api,"SHT3X21"));
CHECK_IIC2();
#pragma message "GWSHT3X21 defined"
}
#endif
#if defined(GWSHT3X22)
{
api->addSensor(creator(api,"SHT3X22"));
CHECK_IIC2();
#pragma message "GWSHT3X22 defined"
}
#endif
return creator;
};
/**
* we do not dynamically compute the config names
* just to get compile time errors if something does not fit
* correctly
*/
#define CFGSHT3X(s, prefix, bus, baddr) \
CFG_SGET(s, tmNam, prefix); \
CFG_SGET(s, huNam, prefix); \
CFG_SGET(s, iid, prefix); \
CFG_SGET(s, tmAct, prefix); \
CFG_SGET(s, huAct, prefix); \
CFG_SGET(s, intv, prefix); \
CFG_SGET(s, huSrc, prefix); \
CFG_SGET(s, tmSrc, prefix); \
s->busId = bus; \
s->addr = baddr; \
s->ok = true; \
s->intv *= 1000;
#define SCSHT3X(prefix, bus, addr) \
GWSENSORDEF(configs, SHT3XConfig, CFGSHT3X, prefix, bus, addr)
SCSHT3X(SHT3X11, 1, 0x44);
SCSHT3X(SHT3X12, 1, 0x45);
SCSHT3X(SHT3X21, 2, 0x44);
SCSHT3X(SHT3X22, 2, 0x45);
#else
SensorBase::Creator registerSHT3X(GwApi *api){
return SensorBase::Creator();
}
#endif

View File

@@ -1,20 +0,0 @@
#ifndef _GWSHT3X_H
#define _GWSHT3X_H
#include "GwIicSensors.h"
#ifdef _GWIIC
#if defined(GWSHT3X) || defined(GWSHT3X11) || defined(GWSHT3X12) || defined(GWSHT3X21) || defined(GWSHT3X22)
#define _GWSHT3X
#endif
#else
#undef _GWSHT3X
#undef GWSHT3X
#undef GWSHT3X11
#undef GWSHT3X12
#undef GWSHT3X21
#undef GWSHT3X22
#endif
#ifdef _GWSHT3X
#include "SHT3X.h"
#endif
SensorBase::Creator registerSHT3X(GwApi *api);
#endif

View File

@@ -1,4 +1,4 @@
#include "GwSHT3X.h" #include "GwSHTXX.h"
#ifdef _GWSHT3X #ifdef _GWSHT3X
bool SHT3X::init(uint8_t slave_addr_in, TwoWire* wire_in) bool SHT3X::init(uint8_t slave_addr_in, TwoWire* wire_in)

128
lib/iictask/SHT4X.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include "SHT4X.h"
uint8_t crc8(const uint8_t *data, int len) {
/*
*
* CRC-8 formula from page 14 of SHT spec pdf
*
* Test data 0xBE, 0xEF should yield 0x92
*
* Initialization data 0xFF
* Polynomial 0x31 (x8 + x5 +x4 +1)
* Final XOR 0x00
*/
const uint8_t POLYNOMIAL(0x31);
uint8_t crc(0xFF);
for (int j = len; j; --j) {
crc ^= *data++;
for (int i = 8; i; --i) {
crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
}
}
return crc;
}
bool SHT4X::begin(TwoWire* wire, uint8_t addr) {
_addr = addr;
_wire = wire;
int error;
_wire->beginTransmission(addr);
error = _wire->endTransmission();
if (error == 0) {
return true;
}
return false;
}
bool SHT4X::update() {
uint8_t readbuffer[6];
uint8_t cmd = SHT4x_NOHEAT_HIGHPRECISION;
uint16_t duration = 10;
if (_heater == SHT4X_NO_HEATER) {
if (_precision == SHT4X_HIGH_PRECISION) {
cmd = SHT4x_NOHEAT_HIGHPRECISION;
duration = 10;
}
if (_precision == SHT4X_MED_PRECISION) {
cmd = SHT4x_NOHEAT_MEDPRECISION;
duration = 5;
}
if (_precision == SHT4X_LOW_PRECISION) {
cmd = SHT4x_NOHEAT_LOWPRECISION;
duration = 2;
}
}
if (_heater == SHT4X_HIGH_HEATER_1S) {
cmd = SHT4x_HIGHHEAT_1S;
duration = 1100;
}
if (_heater == SHT4X_HIGH_HEATER_100MS) {
cmd = SHT4x_HIGHHEAT_100MS;
duration = 110;
}
if (_heater == SHT4X_MED_HEATER_1S) {
cmd = SHT4x_MEDHEAT_1S;
duration = 1100;
}
if (_heater == SHT4X_MED_HEATER_100MS) {
cmd = SHT4x_MEDHEAT_100MS;
duration = 110;
}
if (_heater == SHT4X_LOW_HEATER_1S) {
cmd = SHT4x_LOWHEAT_1S;
duration = 1100;
}
if (_heater == SHT4X_LOW_HEATER_100MS) {
cmd = SHT4x_LOWHEAT_100MS;
duration = 110;
}
// _i2c.writeByte(_addr, cmd, 1);
_wire->beginTransmission(_addr);
_wire->write(cmd);
_wire->write(1);
_wire->endTransmission();
delay(duration);
_wire->requestFrom(_addr, (uint8_t)6);
for (uint16_t i = 0; i < 6; i++) {
readbuffer[i] = _wire->read();
}
if (readbuffer[2] != crc8(readbuffer, 2) ||
readbuffer[5] != crc8(readbuffer + 3, 2)) {
return false;
}
float t_ticks = (uint16_t)readbuffer[0] * 256 + (uint16_t)readbuffer[1];
float rh_ticks = (uint16_t)readbuffer[3] * 256 + (uint16_t)readbuffer[4];
cTemp = -45 + 175 * t_ticks / 65535;
humidity = -6 + 125 * rh_ticks / 65535;
humidity = min(max(humidity, (float)0.0), (float)100.0);
return true;
}
void SHT4X::setPrecision(sht4x_precision_t prec) {
_precision = prec;
}
sht4x_precision_t SHT4X::getPrecision(void) {
return _precision;
}
void SHT4X::setHeater(sht4x_heater_t heat) {
_heater = heat;
}
sht4x_heater_t SHT4X::getHeater(void) {
return _heater;
}

76
lib/iictask/SHT4X.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef __SHT4X_H_
#define __SHT4X_H_
#include "Arduino.h"
#include "Wire.h"
#define SHT40_I2C_ADDR_44 0x44
#define SHT40_I2C_ADDR_45 0x45
#define SHT41_I2C_ADDR_44 0x44
#define SHT41_I2C_ADDR_45 0x45
#define SHT45_I2C_ADDR_44 0x44
#define SHT45_I2C_ADDR_45 0x45
#define SHT4x_DEFAULT_ADDR 0x44 /**< SHT4x I2C Address */
#define SHT4x_NOHEAT_HIGHPRECISION \
0xFD /**< High precision measurement, no heater */
#define SHT4x_NOHEAT_MEDPRECISION \
0xF6 /**< Medium precision measurement, no heater */
#define SHT4x_NOHEAT_LOWPRECISION \
0xE0 /**< Low precision measurement, no heater */
#define SHT4x_HIGHHEAT_1S \
0x39 /**< High precision measurement, high heat for 1 sec */
#define SHT4x_HIGHHEAT_100MS \
0x32 /**< High precision measurement, high heat for 0.1 sec */
#define SHT4x_MEDHEAT_1S \
0x2F /**< High precision measurement, med heat for 1 sec */
#define SHT4x_MEDHEAT_100MS \
0x24 /**< High precision measurement, med heat for 0.1 sec */
#define SHT4x_LOWHEAT_1S \
0x1E /**< High precision measurement, low heat for 1 sec */
#define SHT4x_LOWHEAT_100MS \
0x15 /**< High precision measurement, low heat for 0.1 sec */
#define SHT4x_READSERIAL 0x89 /**< Read Out of Serial Register */
#define SHT4x_SOFTRESET 0x94 /**< Soft Reset */
typedef enum {
SHT4X_HIGH_PRECISION,
SHT4X_MED_PRECISION,
SHT4X_LOW_PRECISION,
} sht4x_precision_t;
/** Optional pre-heater configuration setting */
typedef enum {
SHT4X_NO_HEATER,
SHT4X_HIGH_HEATER_1S,
SHT4X_HIGH_HEATER_100MS,
SHT4X_MED_HEATER_1S,
SHT4X_MED_HEATER_100MS,
SHT4X_LOW_HEATER_1S,
SHT4X_LOW_HEATER_100MS,
} sht4x_heater_t;
class SHT4X {
public:
bool begin(TwoWire* wire = &Wire, uint8_t addr = SHT40_I2C_ADDR_44);
bool update(void);
float cTemp = 0;
float humidity = 0;
void setPrecision(sht4x_precision_t prec);
sht4x_precision_t getPrecision(void);
void setHeater(sht4x_heater_t heat);
sht4x_heater_t getHeater(void);
private:
TwoWire* _wire;
uint8_t _addr;
sht4x_precision_t _precision = SHT4X_HIGH_PRECISION;
sht4x_heater_t _heater = SHT4X_NO_HEATER;
};
#endif

View File

@@ -196,6 +196,203 @@
} }
] ]
}, },
{
"type": "array",
"name": "SHT4X",
"replace": [
{
"b": "1",
"i": "11",
"n": "119"
},
{
"b": "1",
"i": "12",
"n": "118"
},
{
"b": "2",
"i": "21",
"n": "129"
},
{
"b": "2",
"i": "22",
"n": "128"
}
],
"children": [
{
"name": "SHT4X$itmAct",
"label": "SHT4X$i Temp",
"type": "boolean",
"default": "true",
"description": "Enable the $i. I2C SHT4X temp sensor (bus $b)",
"category": "iicsensors$b",
"capabilities": {
"SHT4X$i": "true"
}
},
{
"name": "SHT4X$itmSrc",
"label": "SHT4X$i Temp Type",
"type": "list",
"default": "2",
"description": "the NMEA2000 source type for the temperature",
"list": [
{
"l": "SeaTemperature",
"v": "0"
},
{
"l": "OutsideTemperature",
"v": "1"
},
{
"l": "InsideTemperature",
"v": "2"
},
{
"l": "EngineRoomTemperature",
"v": "3"
},
{
"l": "MainCabinTemperature",
"v": "4"
},
{
"l": "LiveWellTemperature",
"v": "5"
},
{
"l": "BaitWellTemperature",
"v": "6"
},
{
"l": "RefridgerationTemperature",
"v": "7"
},
{
"l": "HeatingSystemTemperature",
"v": "8"
},
{
"l": "DewPointTemperature",
"v": "9"
},
{
"l": "ApparentWindChillTemperature",
"v": "10"
},
{
"l": "TheoreticalWindChillTemperature",
"v": "11"
},
{
"l": "HeatIndexTemperature",
"v": "12"
},
{
"l": "FreezerTemperature",
"v": "13"
},
{
"l": "ExhaustGasTemperature",
"v": "14"
},
{
"l": "ShaftSealTemperature",
"v": "15"
}
],
"category": "iicsensors$b",
"capabilities": {
"SHT4X$i": "true"
}
},
{
"name": "SHT4X$ihuAct",
"label": "SHT4X$i Humidity",
"type": "boolean",
"default": "true",
"description": "Enable the $i. I2C SHT4X humidity sensor (bus $b)",
"category": "iicsensors$b",
"capabilities": {
"SHT4X$i": "true"
}
},
{
"name": "SHT4X$ihuSrc",
"label": "SHT4X$i Humid Type",
"list": [
{
"l": "OutsideHumidity",
"v": "1"
},
{
"l": "Undef",
"v": "0xff"
}
],
"category": "iicsensors$b",
"capabilities": {
"SHT4X": "true"
}
},
{
"name": "SHT4X$iiid",
"label": "SHT4X$i N2K iid",
"type": "number",
"default": "$n",
"description": "the N2K instance id for the $i. SHT4X Temperature and Humidity ",
"category": "iicsensors$b",
"min": 0,
"max": 253,
"check": "checkMinMax",
"capabilities": {
"SHT4X$i": "true"
}
},
{
"name": "SHT4X$iintv",
"label": "SHT4X$i Interval",
"type": "number",
"default": 2,
"description": "Interval(s) to query SHT4X Temperature and Humidity (1...300)",
"category": "iicsensors$b",
"min": 1,
"max": 300,
"check": "checkMinMax",
"capabilities": {
"SHT4X$i": "true"
}
},
{
"name": "SHT4X$itmNam",
"label": "SHT4X$i Temp XDR",
"type": "String",
"default": "Temp$i",
"description": "set the XDR transducer name for the $i. SHT4X Temperature, leave empty to disable NMEA0183 XDR ",
"category": "iicsensors$b",
"capabilities": {
"SHT4X$i": "true"
}
},
{
"name": "SHT4X$ihuNam",
"label": "SHT4X$i Humid XDR",
"type": "String",
"default": "Humidity$i",
"description": "set the XDR transducer name for the $i. SHT4X Humidity, leave empty to disable NMEA0183 XDR",
"category": "iicsensors$b",
"capabilities": {
"SHT4X$i": "true"
}
}
]
},
{ {
"type": "array", "type": "array",
"name": "QMP6988", "name": "QMP6988",

View File

@@ -11,6 +11,17 @@ build_flags=
-D M5_CAN_KIT -D M5_CAN_KIT
${env.build_flags} ${env.build_flags}
[env:m5stack-atom-env4]
extends = sensors
board = m5stack-atom
lib_deps =
${env.lib_deps}
${sensors.lib_deps}
build_flags=
-D M5_ENV4
-D M5_CAN_KIT
${env.build_flags}
[env:m5stack-atom-bme280] [env:m5stack-atom-bme280]
extends = sensors extends = sensors

View File

@@ -93,6 +93,7 @@ class GwSensorConfig{
} }
bool readConfig(T* s,GwConfigHandler *cfg){ bool readConfig(T* s,GwConfigHandler *cfg){
if (s == nullptr) return false; if (s == nullptr) return false;
if (prefix != s->prefix) return false;
configReader(s,cfg); configReader(s,cfg);
return s->ok; return s->ok;
} }