CCS811+SHT20 (eCO2+TVOC+TEMP+HUM) - тестовая программа
Добавлено: 08 июн 2019, 16:50
Приветствую всех форумчан. Предлагаю на тесты скетч для датчика CCS811, добавлен датчик температуры и влажности для компенсации значений eCO2 и TVOC. Датчик работает в импульсном режиме, делая замеры раз в минуту. Микроконтролер всегда спит, просыпаясь по прерыванию от датчика ССS811, проснувшийсь будит сам датчик CCS811:), забирает значения и переводит датчик в сон. Если значения именились то отправляет их на контролер. Так же считываются значения с датчика SHT20, отправляются на контролер если они изменились и записываются в датчик CCS811. Раз в сутки сохраняется в память МК значения бэйзлайн датчика CCS811, которые могут понадобится позже при перезагрузке всего устройства. Ну и отправка заряда батареи на контролер. Даташит датчика - https://docviewer.yandex.ru/view/107589 ... 3D&lang=en.
Потребление усего устройства в пиках - 24мА, во сне 14мкА (вышло не сразу, но что интересно это явно ниже указанных значений в даташите, а 14 это же и на МК и на SHT20 ), это замеры на 2.8-2.9в. Вроде бы получается впринципе батарейная тема...
...Давайте это пообсуждаем...
библиотечки:
DFRobot_SHT20.h
SparkFunCCS811.h
фотка:
Потребление усего устройства в пиках - 24мА, во сне 14мкА (вышло не сразу, но что интересно это явно ниже указанных значений в даташите, а 14 это же и на МК и на SHT20 ), это замеры на 2.8-2.9в. Вроде бы получается впринципе батарейная тема...
...Давайте это пообсуждаем...
Код: Выделить всё
int8_t timer_status = 0;
String error_mes;
uint16_t old_aa = 99999;
uint16_t old_bb = 99999;
uint16_t aa;
uint16_t bb;
uint16_t aaThreshold = 10;
uint16_t bbThreshold = 2;
float tempThreshold = 0.5;
float humThreshold = 10;
float humid;
float temper;
float oldhumd;
float oldtemp;
bool simafor;
unsigned long SLEEP_TIME = 90000000; //25 hours
//unsigned long SLEEP_TIME = 60000; //test
unsigned long oldmillis;
unsigned long newmillis;
unsigned long interrupt_time;
unsigned long SLEEP_TIME_W;
unsigned int result;
unsigned int baselineToApply;
unsigned long newmillisforbatt;
unsigned long battsendinterval = 3600000;
uint16_t currentBatteryPercent;
uint16_t batteryVoltage = 0;
#include "DFRobot_SHT20.h"
DFRobot_SHT20 sht20;
//#define MY_DEBUG
#define MY_DISABLED_SERIAL
#define MY_RADIO_NRF5_ESB
//#define MY_PASSIVE_NODE
#define MY_NODE_ID 129
#define MY_PARENT_NODE_ID 0
#define MY_PARENT_NODE_IS_STATIC
#define MY_TRANSPORT_UPLINK_CHECK_DISABLED
#include <Wire.h>
#include <SparkFunCCS811.h>
#define CCS811_ADDR 0x5B
//#define CCS811_ADDR 0x5A
#define PIN_NOT_WAKE 5
#define PIN_NOT_INT 6
CCS811 myCCS811(CCS811_ADDR);
CCS811Core::status returnCode;
CCS811Core::status errorStatus;
#define C02_CHILD_ID 1
#define TVOC_CHILD_ID 3
#define TEMP_SENS_ID 5
#define HUM_SENS_ID 7
#define CHILD_ID_VOLT 254
#define BATTARY_DATA_SENS_ID 253
#define BATTERY_VCC_MIN 2100
#define BATTERY_VCC_MAX 3000
uint16_t battery_vcc_min = 2000;
uint16_t battery_vcc_max = 2950;
#include <MySensors.h>
MyMessage C02_Msg(C02_CHILD_ID, V_LEVEL);
MyMessage TVOC_Msg(TVOC_CHILD_ID, V_LEVEL);
MyMessage voltMsg(CHILD_ID_VOLT, V_VOLTAGE);
MyMessage powerMsg(BATTARY_DATA_SENS_ID, V_VAR1);
MyMessage msg_temp(TEMP_SENS_ID, V_TEMP);
MyMessage msg_hum(HUM_SENS_ID, V_HUM);
void before()
{
NRF_POWER->DCDCEN = 1;
NRF_UART0->ENABLE = 0;
disableNfc();
pinMode(PIN_NOT_WAKE, OUTPUT);
digitalWrite(PIN_NOT_WAKE, 1);
wait(4000);
//########################### for test ########################
//saveState(0, 0x00);
//saveState(1, 0x00);
//saveState(2, 0x00);
//saveState(3, 0x00);
//########################### for test ########################
}
void presentation()
{
sendSketchInfo("EFEKTA CCS811 AIR Q", "1.1");
present(C02_CHILD_ID, S_AIR_QUALITY, "C02 | PPM");
wait(300);
present(TVOC_CHILD_ID, S_AIR_QUALITY, "TVOC | PPB/T");
wait(300);
present(BATTARY_DATA_SENS_ID, S_CUSTOM, "BATT");
wait(300);
present(TEMP_SENS_ID, S_TEMP, "TEMPERATURE DATA");
wait(300);
present(HUM_SENS_ID, S_HUM, "HUMIDITY DATA");
wait(300);
}
void setup()
{
digitalWrite(PIN_NOT_WAKE, 0); //Start asleep
sht20.initSHT20();
wait(20);
myCCS811.begin();
wait(20);
myCCS811.setDriveMode(3);
wait(20);
if ((loadState(0) == 0xA5) && (loadState(1) == 0xB2))
{
baselineToApply = ((unsigned int)loadState(2) << 8) | loadState(3);
myCCS811.setBaseline( baselineToApply );
wait(20);
}
pinMode(PIN_NOT_INT, INPUT_PULLUP);
myCCS811.enableInterrupts();
digitalWrite(PIN_NOT_WAKE, 1); //Start asleep
wait(100);
SLEEP_TIME_W = SLEEP_TIME;
sendBatteryStatus();
}
void loop()
{
if (timer_status == 6)
{
newmillis = millis();
interrupt_time = newmillis - oldmillis;
SLEEP_TIME_W = SLEEP_TIME_W - interrupt_time;
sht20.initSHT20();
wait(20);
myCCS811.begin();
digitalWrite(PIN_NOT_WAKE, 0);
wait(20);
myCCS811.readAlgorithmResults();
aa = myCCS811.getCO2();
wait(20);
bb = myCCS811.getTVOC();
wait(20);
if (SLEEP_TIME_W < SLEEP_TIME / 1000) {
SLEEP_TIME_W = SLEEP_TIME;
result = myCCS811.getBaseline();
saveState(0, 0xA5);
saveState(1, 0xB2);
saveState(2, (result >> 8) & 0x00FF);
saveState(3, result & 0x00FF);
}
digitalWrite(PIN_NOT_WAKE, 1);
wait(200);
if (abs(aa - old_aa) >= aaThreshold) {
send(C02_Msg.set(aa), 1);
wait(2000, 1, V_LEVEL);
wait(100);
old_aa = aa;
}
if (abs(bb - old_bb) >= bbThreshold) {
send(TVOC_Msg.set(bb), 1);
wait(2000, 1, V_LEVEL);
wait(100);
old_bb = bb;
}
if (millis() - newmillisforbatt >= battsendinterval) {
sendBatteryStatus();
}
if (simafor == 0) {
humid = sht20.readHumidity();
wait(100);
temper = sht20.readTemperature();
wait(100);
int t_humd = humid;
int t_temp = temper;
if (abs(temper - oldtemp) >= tempThreshold) {
send(msg_temp.set(temper, 1));
wait(2000, 1, V_TEMP);
wait(100);
oldtemp = temper;
}
if (abs(humid - oldhumd) >= humThreshold) {
send(msg_hum.set(humid, 1));
wait(2000, 1, V_HUM);
wait(100);
oldhumd = humid;
}
TRANSPORT_DEBUG(PSTR("MyS: DATA - TEMPERATURE: %d, HUMIDITY %d\n"), t_temp, t_humd);
digitalWrite(PIN_NOT_WAKE, 0);
wait(20);
myCCS811.setEnvironmentalData(humid, temper);
wait(20);
digitalWrite(PIN_NOT_WAKE, 1);
wait(20);
simafor = 1;
} else {
simafor = 0;
}
}
if (timer_status == -1) {
newmillis = millis();
SLEEP_TIME_W = SLEEP_TIME;
digitalWrite(PIN_NOT_WAKE, 0);
wait(20);
result = myCCS811.getBaseline();
saveState(0, 0xA5);
saveState(1, 0xB2);
saveState(2, (result >> 8) & 0x00FF);
saveState(3, result & 0x00FF);
digitalWrite(PIN_NOT_WAKE, 1);
wait(20);
}
i2c_off();
oldmillis = millis();
timer_status = sleep(digitalPinToInterrupt(6), FALLING, SLEEP_TIME_W, false);
}
void disableNfc() {
NRF_NFCT->TASKS_DISABLE = 1;
NRF_NVMC->CONFIG = 1;
NRF_UICR->NFCPINS = 0;
NRF_NVMC->CONFIG = 0;
}
void turnOffAdc() {
if (NRF_SAADC->ENABLE) {
NRF_SAADC->TASKS_STOP = 1;
while (NRF_SAADC->EVENTS_STOPPED) {}
NRF_SAADC->ENABLE = 0;
while (NRF_SAADC->ENABLE) {}
}
}
void i2c_off()
{
NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
*(volatile uint32_t *)0x40004FFC = 0;
*(volatile uint32_t *)0x40004FFC;
*(volatile uint32_t *)0x40004FFC = 1;
wait(300);
}
void sendBatteryStatus() {
newmillisforbatt = millis();
batteryVoltage = hwCPUVoltage();
wait(10);
if (batteryVoltage > battery_vcc_max) {
currentBatteryPercent = 100;
}
else if (batteryVoltage < battery_vcc_min) {
currentBatteryPercent = 0;
} else {
currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min);
}
sendBatteryLevel(currentBatteryPercent, 1);
wait(2000, C_INTERNAL, I_BATTERY_LEVEL);
send(powerMsg.set(batteryVoltage), 1);
wait(2000, 1, V_VAR1);
}
//printDriverError decodes the CCS811Core::status type and prints the
//type of error to the serial terminal.
//
//Save the return value of any function of type CCS811Core::status, then pass
//to this function to see what the output was.
/*
void printDriverError( CCS811Core::status errorCode )
{
switch ( errorCode )
{
case CCS811Core::SENSOR_SUCCESS:
TRANSPORT_DEBUG(PSTR("SUCCESS\n"));
break;
case CCS811Core::SENSOR_ID_ERROR:
TRANSPORT_DEBUG(PSTR("ID_ERROR\n"));
break;
case CCS811Core::SENSOR_I2C_ERROR:
TRANSPORT_DEBUG(PSTR("I2C_ERROR\n"));
break;
case CCS811Core::SENSOR_INTERNAL_ERROR:
TRANSPORT_DEBUG(PSTR("INTERNAL_ERROR\n"));
break;
case CCS811Core::SENSOR_GENERIC_ERROR:
TRANSPORT_DEBUG(PSTR("GENERIC_ERROR\n"));
break;
default:
TRANSPORT_DEBUG(PSTR("Unspecified error.\n"));
}
}
*/
DFRobot_SHT20.h
SparkFunCCS811.h
фотка: