mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-07-15 00:46:31 +02:00
Fix capitalize folder and file name ignored
This commit is contained in:
501
src/Main/BoardDef.cpp
Normal file
501
src/Main/BoardDef.cpp
Normal file
@ -0,0 +1,501 @@
|
||||
#include "BoardDef.h"
|
||||
#if defined(ESP32)
|
||||
#include "esp32-hal-log.h"
|
||||
#endif
|
||||
|
||||
const BoardDef bsps[_BOARD_MAX] = {
|
||||
/** DIY_BASIC */
|
||||
[DIY_BASIC] =
|
||||
{
|
||||
.SenseAirS8 =
|
||||
{
|
||||
.uart_tx_pin = 2,
|
||||
.uart_rx_pin = 0,
|
||||
#if defined(ESP8266)
|
||||
.supported = true,
|
||||
#else
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.Pms5003 =
|
||||
{
|
||||
.uart_tx_pin = 14,
|
||||
.uart_rx_pin = 12,
|
||||
#if defined(ESP8266)
|
||||
.supported = true,
|
||||
#else
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.I2C =
|
||||
{
|
||||
.sda_pin = 4,
|
||||
.scl_pin = 5,
|
||||
#if defined(ESP8266)
|
||||
.supported = true,
|
||||
#else
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.SW =
|
||||
{
|
||||
.pin = -1, /** Not supported */
|
||||
.activeLevel = 0, /** Don't care */
|
||||
.supported = false, /** Not supported */
|
||||
},
|
||||
.LED =
|
||||
{
|
||||
.pin = -1,
|
||||
.rgbNum = 0,
|
||||
.onState = 0,
|
||||
.supported = false,
|
||||
.rgbSupported = false,
|
||||
},
|
||||
.OLED =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.width = 64,
|
||||
.height = 48,
|
||||
.addr = 0x3C,
|
||||
.supported = true,
|
||||
#else
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.addr = 0,
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.WDG =
|
||||
{
|
||||
.resetPin = -1,
|
||||
.supported = false,
|
||||
},
|
||||
.name = "DIY_BASIC",
|
||||
},
|
||||
/** DIY_PRO_INDOOR_V4_2 */
|
||||
[DIY_PRO_INDOOR_V4_2] =
|
||||
{
|
||||
.SenseAirS8 =
|
||||
{
|
||||
.uart_tx_pin = 2,
|
||||
.uart_rx_pin = 0,
|
||||
#if defined(ESP8266)
|
||||
.supported = true,
|
||||
#else
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.Pms5003 =
|
||||
{
|
||||
.uart_tx_pin = 14,
|
||||
.uart_rx_pin = 12,
|
||||
#if defined(ESP8266)
|
||||
.supported = true,
|
||||
#else
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.I2C =
|
||||
{
|
||||
.sda_pin = 4,
|
||||
.scl_pin = 5,
|
||||
#if defined(ESP8266)
|
||||
.supported = true,
|
||||
#else
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.SW =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.pin = 13, /** D7 */
|
||||
.activeLevel = 0,
|
||||
.supported = true,
|
||||
#else
|
||||
.pin = -1,
|
||||
.activeLevel = 1,
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.LED =
|
||||
{
|
||||
.pin = -1,
|
||||
.rgbNum = 0,
|
||||
.onState = 0,
|
||||
.supported = false,
|
||||
.rgbSupported = false,
|
||||
},
|
||||
.OLED =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.width = 128,
|
||||
.height = 64,
|
||||
.addr = 0x3C,
|
||||
.supported = true,
|
||||
#else
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.addr = 0,
|
||||
.supported = false,
|
||||
#endif
|
||||
},
|
||||
.WDG =
|
||||
{
|
||||
.resetPin = -1,
|
||||
.supported = false,
|
||||
},
|
||||
.name = "DIY_PRO_INDOOR_V4_2",
|
||||
},
|
||||
/** ONE_INDOOR */
|
||||
[ONE_INDOOR] =
|
||||
{
|
||||
.SenseAirS8 =
|
||||
{
|
||||
.uart_tx_pin = 1,
|
||||
.uart_rx_pin = 0,
|
||||
#if defined(ESP8266)
|
||||
.supported = false,
|
||||
#else
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
/** Use UART0 don't use define pin number */
|
||||
.Pms5003 =
|
||||
{
|
||||
.uart_tx_pin = -1,
|
||||
.uart_rx_pin = -1,
|
||||
#if defined(ESP8266)
|
||||
.supported = false,
|
||||
#else
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.I2C =
|
||||
{
|
||||
.sda_pin = 7,
|
||||
.scl_pin = 6,
|
||||
#if defined(ESP8266)
|
||||
.supported = false,
|
||||
#else
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.SW =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.pin = -1,
|
||||
.activeLevel = 1,
|
||||
.supported = false,
|
||||
#else
|
||||
.pin = 9,
|
||||
.activeLevel = 0,
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.LED =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.pin = -1,
|
||||
.rgbNum = 0,
|
||||
.onState = 0,
|
||||
.supported = false,
|
||||
.rgbSupported = false,
|
||||
#else
|
||||
.pin = 10,
|
||||
.rgbNum = 11,
|
||||
.onState = 1,
|
||||
.supported = true,
|
||||
.rgbSupported = true,
|
||||
#endif
|
||||
},
|
||||
.OLED =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.addr = 0,
|
||||
.supported = false,
|
||||
#else
|
||||
.width = 128,
|
||||
.height = 64,
|
||||
.addr = 0x3C,
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.WDG =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.resetPin = -1,
|
||||
.supported = false,
|
||||
#else
|
||||
.resetPin = 2,
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.name = "ONE_INDOOR",
|
||||
},
|
||||
/** OPEN_AIR_OUTDOOR */
|
||||
[OPEN_AIR_OUTDOOR] = {
|
||||
.SenseAirS8 =
|
||||
{
|
||||
.uart_tx_pin = 1,
|
||||
.uart_rx_pin = 0,
|
||||
#if defined(ESP8266)
|
||||
.supported = false,
|
||||
#else
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
/** Use UART0 don't use define pin number */
|
||||
.Pms5003 =
|
||||
{
|
||||
.uart_tx_pin = -1,
|
||||
.uart_rx_pin = -1,
|
||||
#if defined(ESP8266)
|
||||
.supported = false,
|
||||
#else
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.I2C =
|
||||
{
|
||||
.sda_pin = 7,
|
||||
.scl_pin = 6,
|
||||
#if defined(ESP8266)
|
||||
.supported = false,
|
||||
#else
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.SW =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.pin = -1,
|
||||
.activeLevel = 1,
|
||||
.supported = false,
|
||||
#else
|
||||
.pin = 9,
|
||||
.activeLevel = 0,
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.LED =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.pin = -1,
|
||||
.rgbNum = 0,
|
||||
.onState = 0,
|
||||
.supported = false,
|
||||
.rgbSupported = false,
|
||||
#else
|
||||
.pin = 10,
|
||||
.rgbNum = 0,
|
||||
.onState = 1,
|
||||
.supported = true,
|
||||
.rgbSupported = false,
|
||||
#endif
|
||||
},
|
||||
.OLED =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.addr = 0,
|
||||
.supported = false,
|
||||
#else
|
||||
.width = 128,
|
||||
.height = 64,
|
||||
.addr = 0x3C,
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.WDG =
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
.resetPin = -1,
|
||||
.supported = false,
|
||||
#else
|
||||
.resetPin = 2,
|
||||
.supported = true,
|
||||
#endif
|
||||
},
|
||||
.name = "OPEN_AIR_OUTDOOR",
|
||||
}};
|
||||
|
||||
/**
|
||||
* @brief Get Board Support Package
|
||||
*
|
||||
* @param def Board define @ref BoardType
|
||||
* @return const BoardDef*
|
||||
*/
|
||||
const BoardDef *getBoardDef(BoardType def) {
|
||||
if (def >= _BOARD_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
return &bsps[def];
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define bspPrintf(c, ...) \
|
||||
if (_debug != nullptr) { \
|
||||
_debug->printf("[BSP] " c "\r\n", ##__VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
#define bspPrintf(c, ...) log_i(c, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Print list of support Board and sensor
|
||||
*
|
||||
* @param _debug Serial debug
|
||||
*/
|
||||
void printBoardDef(Stream *_debug) {
|
||||
#if defined(ESP8266)
|
||||
if (_debug == NULL) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < _BOARD_MAX; i++) {
|
||||
bspPrintf("Board name: %s", bsps[i].name);
|
||||
bspPrintf("\tSensor CO2 S8:");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].SenseAirS8.supported);
|
||||
if (bsps[i].SenseAirS8.supported) {
|
||||
bspPrintf("\t\tUART Tx: %d", bsps[i].SenseAirS8.uart_tx_pin);
|
||||
bspPrintf("\t\tUART Rx: %d", bsps[i].SenseAirS8.uart_rx_pin);
|
||||
}
|
||||
|
||||
bspPrintf("\tSensor PMS5003:");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].Pms5003.supported);
|
||||
if (bsps[i].Pms5003.supported) {
|
||||
bspPrintf("\t\tUART Tx: %d", bsps[i].Pms5003.uart_tx_pin);
|
||||
bspPrintf("\t\tUART Rx: %d", bsps[i].Pms5003.uart_rx_pin);
|
||||
}
|
||||
|
||||
bspPrintf("\tI2C");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].I2C.supported);
|
||||
if (bsps[i].I2C.supported) {
|
||||
bspPrintf("\t\tI2C SCL: %d", bsps[i].I2C.scl_pin);
|
||||
bspPrintf("\t\tI2C SDA: %d", bsps[i].I2C.sda_pin);
|
||||
}
|
||||
|
||||
bspPrintf("\tSwitch");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].SW.supported);
|
||||
if (bsps[i].SW.supported) {
|
||||
bspPrintf("\t\tPin : %d", bsps[i].SW.pin);
|
||||
bspPrintf("\t\tActive Level: %d", bsps[i].SW.activeLevel);
|
||||
}
|
||||
|
||||
bspPrintf("\tLED");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].LED.supported);
|
||||
if (bsps[i].LED.supported) {
|
||||
bspPrintf("\t\tPin : %d", bsps[i].LED.pin);
|
||||
bspPrintf("\t\tRGB : %d", bsps[i].LED.rgbSupported);
|
||||
if (bsps[i].LED.rgbSupported) {
|
||||
bspPrintf("\t\tNumber of RGB: %d", bsps[i].LED.rgbNum);
|
||||
} else {
|
||||
bspPrintf("\t\tLED state ON: %d (Single LED)", bsps[i].LED.onState);
|
||||
}
|
||||
}
|
||||
|
||||
bspPrintf("\tOLED");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].OLED.supported);
|
||||
if (bsps[i].OLED.supported) {
|
||||
bspPrintf("\t\tWidth : %d", bsps[i].OLED.width);
|
||||
bspPrintf("\t\tHeigth : %d", bsps[i].OLED.height);
|
||||
bspPrintf("\t\tI2C Addr: %d", bsps[i].OLED.addr);
|
||||
}
|
||||
|
||||
bspPrintf("\tWatchDog");
|
||||
bspPrintf("\t\tSupported: %d", bsps[i].WDG.supported);
|
||||
if (bsps[i].OLED.supported) {
|
||||
bspPrintf("\t\tReset Pin: %d", bsps[i].WDG.resetPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool getBoardDef_I2C_Supported(const BoardDef *bsp) {
|
||||
if (bsp == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return bsp->I2C.supported;
|
||||
}
|
||||
|
||||
int getBoardDef_I2C_SDA(const BoardDef *bsp) {
|
||||
if ((bsp == nullptr) || (bsp->I2C.supported == false)) {
|
||||
return -1;
|
||||
}
|
||||
return bsp->I2C.sda_pin;
|
||||
}
|
||||
|
||||
int getBoardDef_I2C_SCL(const BoardDef *bsp) {
|
||||
if ((bsp == nullptr) || (bsp->I2C.supported == false)) {
|
||||
return -1;
|
||||
}
|
||||
return bsp->I2C.scl_pin;
|
||||
}
|
||||
|
||||
bool getBoardDef_SW_Supported(const BoardDef *bsp) {
|
||||
if (bsp == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return bsp->SW.supported;
|
||||
}
|
||||
|
||||
int getBoardDef_SW_Pin(const BoardDef *bsp) {
|
||||
if ((bsp == nullptr) || (bsp->SW.supported == false)) {
|
||||
return -1;
|
||||
}
|
||||
return bsp->SW.supported;
|
||||
}
|
||||
|
||||
int getBoardDef_SW_ActiveLevel(const BoardDef *bsp) {
|
||||
if (bsp == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return bsp->SW.activeLevel;
|
||||
}
|
||||
|
||||
void AirGradientBspWdgInit(const BoardDef *bsp) {
|
||||
if (bsp == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (bsp->WDG.supported) {
|
||||
pinMode(bsp->WDG.resetPin, OUTPUT);
|
||||
digitalWrite(bsp->WDG.resetPin, LOW);
|
||||
delay(25); // Delay 25ms
|
||||
digitalWrite(bsp->WDG.resetPin, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin reset external watchdog. Must call @ref AirGradientBspWdgFeedEnd
|
||||
* after 20 ms
|
||||
*
|
||||
* @param bsp
|
||||
*/
|
||||
void AirGradientBspWdgFeedBegin(const BoardDef *bsp) {
|
||||
if (bsp == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bsp->WDG.supported) {
|
||||
digitalWrite(bsp->WDG.resetPin, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call this function to finish watchdog feed after call @ref
|
||||
* AirGradientBspWdgFeedBegin 25 ms
|
||||
*
|
||||
* @param bsp
|
||||
*/
|
||||
void AirGradientBspWdgFeedEnd(const BoardDef *bsp) {
|
||||
if (bsp == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bsp->WDG.supported) {
|
||||
digitalWrite(bsp->WDG.resetPin, LOW);
|
||||
}
|
||||
}
|
88
src/Main/BoardDef.h
Normal file
88
src/Main/BoardDef.h
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef _AIR_GRADIENT_BOARD_DEF_H_
|
||||
#define _AIR_GRADIENT_BOARD_DEF_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define AgLog(c, ...) \
|
||||
if (this->_debugStream != nullptr) { \
|
||||
this->_debugStream->printf("[%s] " c "\r\n", this->TAG, ##__VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
#include <esp32-hal-log.h>
|
||||
#define AgLog(c, ...) log_i(c, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Define Airgradient supported board type
|
||||
*/
|
||||
enum BoardType {
|
||||
DIY_BASIC = 0x00,
|
||||
DIY_PRO_INDOOR_V4_2 = 0x01,
|
||||
ONE_INDOOR = 0x02,
|
||||
OPEN_AIR_OUTDOOR = 0x03,
|
||||
_BOARD_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Board definitions
|
||||
*
|
||||
*/
|
||||
struct BoardDef {
|
||||
/** Board Support CO2 SenseS8 */
|
||||
struct {
|
||||
const int uart_tx_pin; /** UART tx pin */
|
||||
const int uart_rx_pin; /** UART rx pin */
|
||||
const bool supported; /** Is BSP supported for this sensor */
|
||||
} SenseAirS8;
|
||||
|
||||
/** Board Support Plantower PMS5003 */
|
||||
struct {
|
||||
const int uart_tx_pin; /** UART tx pin */
|
||||
const int uart_rx_pin; /** UART rx pin */
|
||||
const bool supported; /** Is BSP supported for this sensor */
|
||||
} Pms5003;
|
||||
|
||||
/** I2C Bus */
|
||||
struct {
|
||||
const int sda_pin; /** I2C SDA pin */
|
||||
const int scl_pin; /** I2C SCL pin */
|
||||
const bool supported; /** Is BSP supported I2C communication */
|
||||
} I2C;
|
||||
|
||||
/** Switch */
|
||||
struct {
|
||||
const int pin; /** Switch PIN */
|
||||
const int activeLevel; /** Switch pressed level */
|
||||
const bool supported;
|
||||
} SW;
|
||||
|
||||
/** LED */
|
||||
struct {
|
||||
const int pin; /** Pin control */
|
||||
const int rgbNum; /** Number of RGB LED */
|
||||
const int onState; /** Single LED turn on state */
|
||||
const bool supported; /** SUpported LED */
|
||||
const bool rgbSupported; /** LED is RGB */
|
||||
} LED;
|
||||
|
||||
/** OLED */
|
||||
struct {
|
||||
const uint8_t width; /** Display Width */
|
||||
const uint8_t height; /** Display height */
|
||||
const uint8_t addr; /** OLED I2C address */
|
||||
const bool supported;
|
||||
} OLED;
|
||||
|
||||
/** Watchdog */
|
||||
struct {
|
||||
const uint8_t resetPin;
|
||||
const bool supported;
|
||||
} WDG;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
const BoardDef *getBoardDef(BoardType def);
|
||||
void printBoardDef(Stream *_debug);
|
||||
|
||||
#endif /** _AIR_GRADIENT_BOARD_DEF_H_ */
|
74
src/Main/HardwareWatchdog.cpp
Normal file
74
src/Main/HardwareWatchdog.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "HardwareWatchdog.h"
|
||||
|
||||
HardwareWatchdog::HardwareWatchdog(BoardType type) : boardType(type) {}
|
||||
|
||||
#if defined(ESP8266)
|
||||
void HardwareWatchdog::begin(Stream &debugStream) {
|
||||
this->_debugStream = &debugStream;
|
||||
this->begin();
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize external watchdog
|
||||
*
|
||||
*/
|
||||
void HardwareWatchdog::begin(void) {
|
||||
if (this->_isInit) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** Get BSP */
|
||||
this->bsp = getBoardDef(this->boardType);
|
||||
if ((this->bsp == nullptr) || (this->bsp->WDG.supported == false)) {
|
||||
AgLog("Board not supported Watchdog");
|
||||
return;
|
||||
}
|
||||
|
||||
/** Init GPIO and first feed external watchdog */
|
||||
pinMode(this->bsp->WDG.resetPin, OUTPUT);
|
||||
this->_feed();
|
||||
|
||||
this->_isInit = true;
|
||||
AgLog("Inittialized");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset Watchdog
|
||||
*
|
||||
*/
|
||||
void HardwareWatchdog::reset(void) {
|
||||
if (this->isInitInvalid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->_feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wathdog timeout
|
||||
*
|
||||
* @return int Millisecionds
|
||||
*/
|
||||
int HardwareWatchdog::getTimeout(void) { return 5 * 1000 * 60; }
|
||||
|
||||
bool HardwareWatchdog::isInitInvalid(void) {
|
||||
if (this->_isInit == false) {
|
||||
AgLog("No-initialized");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset external watchdog
|
||||
*
|
||||
*/
|
||||
void HardwareWatchdog::_feed(void) {
|
||||
digitalWrite(this->bsp->WDG.resetPin, HIGH);
|
||||
delay(25);
|
||||
digitalWrite(this->bsp->WDG.resetPin, LOW);
|
||||
|
||||
AgLog("Reset");
|
||||
}
|
37
src/Main/HardwareWatchdog.h
Normal file
37
src/Main/HardwareWatchdog.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef _HARDWARE_WATCHDOG_H_
|
||||
#define _HARDWARE_WATCHDOG_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BoardDef.h"
|
||||
|
||||
/**
|
||||
* @brief The class define how to control external watchdog on ONE-V9 and
|
||||
* Outdoor
|
||||
*/
|
||||
class HardwareWatchdog {
|
||||
public:
|
||||
HardwareWatchdog(BoardType type);
|
||||
#if defined(ESP8266)
|
||||
void begin(Stream &debugStream);
|
||||
#else
|
||||
#endif
|
||||
void begin(void);
|
||||
void reset(void);
|
||||
int getTimeout(void);
|
||||
|
||||
private:
|
||||
bool _isInit = false;
|
||||
const BoardDef *bsp;
|
||||
BoardType boardType;
|
||||
#if defined(ESP8266)
|
||||
Stream *_debugStream;
|
||||
const char *TAG = "HardwareWatchdog";
|
||||
#else
|
||||
#endif
|
||||
|
||||
bool isInitInvalid(void);
|
||||
void _feed(void);
|
||||
};
|
||||
|
||||
#endif /** _HARDWARE_WATCHDOG_H_ */
|
126
src/Main/LedBar.cpp
Normal file
126
src/Main/LedBar.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "LedBar.h"
|
||||
|
||||
#include "../Libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.h"
|
||||
|
||||
#define pixel() ((Adafruit_NeoPixel *)this->pixels)
|
||||
|
||||
#if defined(ESP8266)
|
||||
void LedBar::begin(Stream &debugStream) {
|
||||
this->_debugStream = &debugStream;
|
||||
this->begin();
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
LedBar::LedBar(BoardType type) : _boardType(type) {}
|
||||
|
||||
/**
|
||||
* @brief LED bar initialize
|
||||
*
|
||||
*/
|
||||
void LedBar::begin(void) {
|
||||
if (this->_isBegin) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** Get board support package define */
|
||||
this->_bsp = getBoardDef(this->_boardType);
|
||||
if ((this->_bsp == nullptr) || (this->_bsp->LED.supported == false) ||
|
||||
(this->_bsp->LED.rgbNum == 0)) {
|
||||
AgLog("Board Not supported or LED not available on board");
|
||||
return;
|
||||
}
|
||||
|
||||
/** Init pixels */
|
||||
this->pixels = new Adafruit_NeoPixel(
|
||||
this->_bsp->LED.rgbNum, this->_bsp->LED.pin, NEO_GRB + NEO_KHZ800);
|
||||
pixel()->begin();
|
||||
pixel()->clear();
|
||||
|
||||
this->_isBegin = true;
|
||||
|
||||
AgLog("Initialize");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LED color, if LED is on the color update immedietly. Otherwise
|
||||
* must setOn to show LED color
|
||||
*
|
||||
* @param red Color Red (0 - 255)
|
||||
* @param green Color Green (0 - 255)
|
||||
* @param blue Color Blue (0 - 255)
|
||||
* @param ledNum Index of LED from 0 to getNumberOfLeds() - 1
|
||||
*/
|
||||
void LedBar::setColor(uint8_t red, uint8_t green, uint8_t blue, int ledNum) {
|
||||
if (this->ledNumInvalid(ledNum)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pixel()->setPixelColor(ledNum, red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LED brightness apply for all LED bar
|
||||
*
|
||||
* @param brightness Brightness (0 - 255)
|
||||
*/
|
||||
void LedBar::setBrighness(uint8_t brightness) {
|
||||
if (this->isBegin() == false) {
|
||||
return;
|
||||
}
|
||||
pixel()->setBrightness(brightness);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of LED on bar
|
||||
*
|
||||
* @return int Number of LED
|
||||
*/
|
||||
int LedBar::getNumberOfLeds(void) {
|
||||
if (this->isBegin() == false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this->_bsp->LED.rgbNum;
|
||||
}
|
||||
|
||||
bool LedBar::isBegin(void) {
|
||||
if (this->_isBegin) {
|
||||
return true;
|
||||
}
|
||||
AgLog("LED is not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LedBar::ledNumInvalid(int ledNum) {
|
||||
if (this->isBegin() == false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((ledNum < 0) || (ledNum >= this->_bsp->LED.rgbNum)) {
|
||||
AgLog("ledNum invalid: %d", ledNum);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LedBar::setColor(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
for (int ledNum = 0; ledNum < this->_bsp->LED.rgbNum; ledNum++) {
|
||||
this->setColor(red, green, blue, ledNum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call to turn LED on/off base on the setting color
|
||||
*
|
||||
*/
|
||||
void LedBar::show(void) {
|
||||
if (pixel()->canShow()) {
|
||||
pixel()->show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set all LED to off color (r,g,b) = (0,0,0)
|
||||
*
|
||||
*/
|
||||
void LedBar::clear(void) { pixel()->clear(); }
|
42
src/Main/LedBar.h
Normal file
42
src/Main/LedBar.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef _AIR_GRADIENT_LED_H_
|
||||
#define _AIR_GRADIENT_LED_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "BoardDef.h"
|
||||
|
||||
/**
|
||||
* @brief The class define how to handle the RGB LED bar
|
||||
*
|
||||
*/
|
||||
class LedBar {
|
||||
public:
|
||||
#if defined(ESP8266)
|
||||
void begin(Stream &debugStream);
|
||||
#else
|
||||
#endif
|
||||
LedBar(BoardType type);
|
||||
void begin(void);
|
||||
void setColor(uint8_t red, uint8_t green, uint8_t blue, int ledNum);
|
||||
void setColor(uint8_t red, uint8_t green, uint8_t blue);
|
||||
void setBrighness(uint8_t brightness);
|
||||
int getNumberOfLeds(void);
|
||||
void show(void);
|
||||
void clear(void);
|
||||
|
||||
private:
|
||||
const BoardDef *_bsp;
|
||||
bool _isBegin = false;
|
||||
uint8_t _ledState = 0;
|
||||
BoardType _boardType;
|
||||
void *pixels = nullptr;
|
||||
#if defined(ESP8266)
|
||||
Stream *_debugStream = NULL;
|
||||
const char *TAG = "LED";
|
||||
#else
|
||||
#endif
|
||||
bool isBegin(void);
|
||||
bool ledNumInvalid(int ledNum);
|
||||
};
|
||||
|
||||
#endif /** _AIR_GRADIENT_LED_H_ */
|
74
src/Main/PushButton.cpp
Normal file
74
src/Main/PushButton.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "PushButton.h"
|
||||
|
||||
PushButton::PushButton(BoardType type) : _boardType(type) {}
|
||||
|
||||
#if defined(ESP8266)
|
||||
void PushButton::begin(Stream &debugStream) {
|
||||
this->_debugStream = &debugStream;
|
||||
this->begin();
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize PushButton, If PushButton is not initialized the get state
|
||||
*
|
||||
*/
|
||||
void PushButton::begin(void) {
|
||||
if (this->_isBegin) {
|
||||
AgLog("Initialized, call end() then try again");
|
||||
return;
|
||||
}
|
||||
|
||||
this->_bsp = getBoardDef(this->_boardType);
|
||||
if ((this->_bsp == nullptr) || (this->_bsp->SW.supported == false)) {
|
||||
AgLog("Board not supported or switch not available");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->_boardType == DIY_PRO_INDOOR_V4_2) {
|
||||
pinMode(this->_bsp->SW.pin, INPUT_PULLUP);
|
||||
} else {
|
||||
pinMode(this->_bsp->SW.pin, INPUT);
|
||||
}
|
||||
|
||||
this->_isBegin = true;
|
||||
AgLog("Initialize");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get button state, Alway retrun State::BUTTON_RELEASED if no-initialize
|
||||
*
|
||||
* @return PushButton::State
|
||||
*/
|
||||
PushButton::State PushButton::getState(void) {
|
||||
if (this->isBegin() == false) {
|
||||
return State::BUTTON_RELEASED;
|
||||
}
|
||||
|
||||
if (digitalRead(this->_bsp->SW.pin) == this->_bsp->SW.activeLevel) {
|
||||
return State::BUTTON_PRESSED;
|
||||
}
|
||||
return State::BUTTON_RELEASED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PushButton::State as string
|
||||
*
|
||||
* @param state Buttons State
|
||||
* @return String
|
||||
*/
|
||||
String PushButton::toString(PushButton::State state) {
|
||||
if (state == BUTTON_PRESSED) {
|
||||
return "Presssed";
|
||||
}
|
||||
return "Released";
|
||||
}
|
||||
|
||||
bool PushButton::isBegin(void) {
|
||||
if (this->_isBegin) {
|
||||
return true;
|
||||
}
|
||||
AgLog("Switch not initialized");
|
||||
return false;
|
||||
}
|
47
src/Main/PushButton.h
Normal file
47
src/Main/PushButton.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef _AIR_GRADIENT_SW_H_
|
||||
#define _AIR_GRADIENT_SW_H_
|
||||
|
||||
#include "BoardDef.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* @brief The class define how to handle the Push button
|
||||
*
|
||||
*/
|
||||
class PushButton {
|
||||
public:
|
||||
/**
|
||||
* @brief Enum button state
|
||||
*/
|
||||
enum State { BUTTON_PRESSED, BUTTON_RELEASED };
|
||||
|
||||
#if defined(ESP8266)
|
||||
void begin(Stream &debugStream);
|
||||
#else
|
||||
#endif
|
||||
PushButton(BoardType type);
|
||||
void begin(void);
|
||||
State getState(void);
|
||||
String toString(State state);
|
||||
|
||||
private:
|
||||
/** BSP constant variable */
|
||||
const BoardDef *_bsp;
|
||||
/** Board type */
|
||||
BoardType _boardType;
|
||||
/** Is inititalize flag */
|
||||
bool _isBegin = false;
|
||||
|
||||
/** Special variable for ESP8266 */
|
||||
#if defined(ESP8266)
|
||||
Stream *_debugStream = nullptr;
|
||||
const char *TAG = "PushButton";
|
||||
#else
|
||||
#endif
|
||||
|
||||
/** Method */
|
||||
|
||||
bool isBegin(void);
|
||||
};
|
||||
|
||||
#endif /** _AIR_GRADIENT_SW_H_ */
|
115
src/Main/StatusLed.cpp
Normal file
115
src/Main/StatusLed.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include "StatusLed.h"
|
||||
|
||||
StatusLed::StatusLed(BoardType boardType) : boardType(boardType) {}
|
||||
|
||||
#if defined(ESP8266)
|
||||
void StatusLed::begin(Stream &debugStream) {
|
||||
this->_debugStream = &debugStream;
|
||||
this->begin();
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialized LED
|
||||
*
|
||||
*/
|
||||
void StatusLed::begin(void) {
|
||||
if (this->_isBegin) {
|
||||
AgLog("Initialized, call end() then try again");
|
||||
return;
|
||||
}
|
||||
bsp = getBoardDef(this->boardType);
|
||||
if ((bsp == nullptr) || (bsp->LED.supported == false)) {
|
||||
AgLog("Board not support StatusLed");
|
||||
return;
|
||||
}
|
||||
|
||||
pinMode(bsp->LED.pin, OUTPUT);
|
||||
digitalWrite(bsp->LED.pin, !bsp->LED.onState);
|
||||
|
||||
this->state = LED_OFF;
|
||||
this->_isBegin = true;
|
||||
|
||||
AgLog("Initialize");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn LED on
|
||||
*
|
||||
*/
|
||||
void StatusLed::setOn(void) {
|
||||
if (this->isBegin() == false) {
|
||||
return;
|
||||
}
|
||||
digitalWrite(bsp->LED.pin, bsp->LED.onState);
|
||||
this->state = LED_ON;
|
||||
AgLog("Turn ON");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn LED off
|
||||
*
|
||||
*/
|
||||
void StatusLed::setOff(void) {
|
||||
if (this->isBegin() == false) {
|
||||
return;
|
||||
}
|
||||
digitalWrite(bsp->LED.pin, !bsp->LED.onState);
|
||||
this->state = LED_OFF;
|
||||
AgLog("Turn OFF");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LED toggle
|
||||
*
|
||||
*/
|
||||
void StatusLed::setToggle(void) {
|
||||
if (this->state == LED_ON) {
|
||||
this->setOff();
|
||||
} else {
|
||||
this->setOn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current LED state
|
||||
*
|
||||
* @return StatusLed::State
|
||||
*/
|
||||
StatusLed::State StatusLed::getState(void) { return this->state; }
|
||||
|
||||
/**
|
||||
* @brief Convert LED state to string
|
||||
*
|
||||
* @param state LED state
|
||||
* @return String
|
||||
*/
|
||||
String StatusLed::toString(StatusLed::State state) {
|
||||
if (state == LED_ON) {
|
||||
return "On";
|
||||
}
|
||||
return "Off";
|
||||
}
|
||||
|
||||
bool StatusLed::isBegin(void) {
|
||||
if (this->_isBegin == false) {
|
||||
AgLog("Not-Initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StatusLed::end(void) {
|
||||
if (_isBegin == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
_debugStream = nullptr;
|
||||
#endif
|
||||
setOff();
|
||||
_isBegin = false;
|
||||
AgLog("De-initialize");
|
||||
}
|
45
src/Main/StatusLed.h
Normal file
45
src/Main/StatusLed.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef _STATUS_LED_H_
|
||||
#define _STATUS_LED_H_
|
||||
|
||||
#include "BoardDef.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* @brief The class define how to handle the LED
|
||||
*
|
||||
*/
|
||||
class StatusLed {
|
||||
public:
|
||||
enum State {
|
||||
LED_OFF,
|
||||
LED_ON,
|
||||
};
|
||||
|
||||
StatusLed(BoardType boardType);
|
||||
#if defined(ESP8266)
|
||||
void begin(Stream &debugStream);
|
||||
#else
|
||||
#endif
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void setOn(void);
|
||||
void setOff(void);
|
||||
void setToggle(void);
|
||||
State getState(void);
|
||||
String toString(StatusLed::State state);
|
||||
|
||||
private:
|
||||
const BoardDef *bsp = nullptr;
|
||||
BoardType boardType;
|
||||
bool _isBegin = false;
|
||||
State state;
|
||||
#if defined(ESP8266)
|
||||
Stream *_debugStream;
|
||||
const char *TAG = "StatusLed";
|
||||
#else
|
||||
#endif
|
||||
|
||||
bool isBegin(void);
|
||||
};
|
||||
|
||||
#endif /** _STATUS_LED_H_ */
|
164
src/PMS/PMS.cpp
Normal file
164
src/PMS/PMS.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include "PMS.h"
|
||||
|
||||
bool PMS::begin(Stream *stream) {
|
||||
_stream = stream;
|
||||
|
||||
DATA data;
|
||||
if (readUntil(data, 5000)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Standby mode. For low power consumption and prolong the life of the sensor.
|
||||
void PMS::sleep() {
|
||||
uint8_t command[] = {0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73};
|
||||
_stream->write(command, sizeof(command));
|
||||
}
|
||||
|
||||
// Operating mode. Stable data should be got at least 30 seconds after the
|
||||
// sensor wakeup from the sleep mode because of the fan's performance.
|
||||
void PMS::wakeUp() {
|
||||
uint8_t command[] = {0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74};
|
||||
_stream->write(command, sizeof(command));
|
||||
}
|
||||
|
||||
// Active mode. Default mode after power up. In this mode sensor would send
|
||||
// serial data to the host automatically.
|
||||
void PMS::activeMode() {
|
||||
uint8_t command[] = {0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71};
|
||||
_stream->write(command, sizeof(command));
|
||||
_mode = MODE_ACTIVE;
|
||||
}
|
||||
|
||||
// Passive mode. In this mode sensor would send serial data to the host only for
|
||||
// request.
|
||||
void PMS::passiveMode() {
|
||||
uint8_t command[] = {0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70};
|
||||
_stream->write(command, sizeof(command));
|
||||
_mode = MODE_PASSIVE;
|
||||
}
|
||||
|
||||
// Request read in Passive Mode.
|
||||
void PMS::requestRead() {
|
||||
if (_mode == MODE_PASSIVE) {
|
||||
uint8_t command[] = {0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71};
|
||||
_stream->write(command, sizeof(command));
|
||||
}
|
||||
}
|
||||
|
||||
// Non-blocking function for parse response.
|
||||
bool PMS::read(DATA &data) {
|
||||
_data = &data;
|
||||
loop();
|
||||
|
||||
return _status == STATUS_OK;
|
||||
}
|
||||
|
||||
// Blocking function for parse response. Default timeout is 1s.
|
||||
bool PMS::readUntil(DATA &data, uint16_t timeout) {
|
||||
_data = &data;
|
||||
uint32_t start = millis();
|
||||
do {
|
||||
loop();
|
||||
if (_status == STATUS_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
/** Relax task to avoid watchdog reset */
|
||||
delay(1);
|
||||
} while (millis() - start < timeout);
|
||||
|
||||
return _status == STATUS_OK;
|
||||
}
|
||||
|
||||
void PMS::loop() {
|
||||
_status = STATUS_WAITING;
|
||||
if (_stream->available()) {
|
||||
uint8_t ch = _stream->read();
|
||||
|
||||
switch (_index) {
|
||||
case 0:
|
||||
if (ch != 0x42) {
|
||||
return;
|
||||
}
|
||||
_calculatedChecksum = ch;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (ch != 0x4D) {
|
||||
_index = 0;
|
||||
return;
|
||||
}
|
||||
_calculatedChecksum += ch;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_calculatedChecksum += ch;
|
||||
_frameLen = ch << 8;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_frameLen |= ch;
|
||||
// Unsupported sensor, different frame length, transmission error e.t.c.
|
||||
if (_frameLen != 2 * 9 + 2 && _frameLen != 2 * 13 + 2) {
|
||||
_index = 0;
|
||||
return;
|
||||
}
|
||||
_calculatedChecksum += ch;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (_index == _frameLen + 2) {
|
||||
_checksum = ch << 8;
|
||||
} else if (_index == _frameLen + 2 + 1) {
|
||||
_checksum |= ch;
|
||||
|
||||
if (_calculatedChecksum == _checksum) {
|
||||
_status = STATUS_OK;
|
||||
|
||||
// Standard Particles, CF=1.
|
||||
_data->PM_SP_UG_1_0 = makeWord(_payload[0], _payload[1]);
|
||||
_data->PM_SP_UG_2_5 = makeWord(_payload[2], _payload[3]);
|
||||
_data->PM_SP_UG_10_0 = makeWord(_payload[4], _payload[5]);
|
||||
|
||||
// Atmospheric Environment.
|
||||
_data->PM_AE_UG_1_0 = makeWord(_payload[6], _payload[7]);
|
||||
_data->PM_AE_UG_2_5 = makeWord(_payload[8], _payload[9]);
|
||||
_data->PM_AE_UG_10_0 = makeWord(_payload[10], _payload[11]);
|
||||
|
||||
// Total particles count per 100ml air
|
||||
_data->PM_RAW_0_3 = makeWord(_payload[12], _payload[13]);
|
||||
_data->PM_RAW_0_5 = makeWord(_payload[14], _payload[15]);
|
||||
_data->PM_RAW_1_0 = makeWord(_payload[16], _payload[17]);
|
||||
_data->PM_RAW_2_5 = makeWord(_payload[18], _payload[19]);
|
||||
_data->PM_RAW_5_0 = makeWord(_payload[20], _payload[21]);
|
||||
_data->PM_RAW_10_0 = makeWord(_payload[22], _payload[23]);
|
||||
|
||||
// Formaldehyde concentration (PMSxxxxST units only)
|
||||
_data->AMB_HCHO = makeWord(_payload[24], _payload[25]) / 1000;
|
||||
|
||||
// Temperature & humidity (PMSxxxxST units only)
|
||||
_data->AMB_TMP = makeWord(_payload[20], _payload[21]);
|
||||
_data->AMB_HUM = makeWord(_payload[22], _payload[23]);
|
||||
}
|
||||
|
||||
_index = 0;
|
||||
return;
|
||||
} else {
|
||||
_calculatedChecksum += ch;
|
||||
uint8_t payloadIndex = _index - 4;
|
||||
|
||||
// Payload is common to all sensors (first 2x6 bytes).
|
||||
if (payloadIndex < sizeof(_payload)) {
|
||||
_payload[payloadIndex] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_index++;
|
||||
}
|
||||
}
|
75
src/PMS/PMS.h
Normal file
75
src/PMS/PMS.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef _PMS_BASE_H_
|
||||
#define _PMS_BASE_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* @brief Class define how to handle plantower PMS sensor it's upport for
|
||||
* PMS5003 and PMS5003T series. The data @ref AMB_TMP and @ref AMB_HUM only
|
||||
* valid on PMS5003T
|
||||
*/
|
||||
class PMS {
|
||||
public:
|
||||
static const uint16_t SINGLE_RESPONSE_TIME = 1000;
|
||||
static const uint16_t TOTAL_RESPONSE_TIME = 1000 * 10;
|
||||
static const uint16_t STEADY_RESPONSE_TIME = 1000 * 30;
|
||||
|
||||
// static const uint16_t BAUD_RATE = 9600;
|
||||
|
||||
struct DATA {
|
||||
// Standard Particles, CF=1
|
||||
uint16_t PM_SP_UG_1_0;
|
||||
uint16_t PM_SP_UG_2_5;
|
||||
uint16_t PM_SP_UG_10_0;
|
||||
|
||||
// Atmospheric environment
|
||||
uint16_t PM_AE_UG_1_0;
|
||||
uint16_t PM_AE_UG_2_5;
|
||||
uint16_t PM_AE_UG_10_0;
|
||||
|
||||
// Raw particles count (number of particles in 0.1l of air
|
||||
uint16_t PM_RAW_0_3;
|
||||
uint16_t PM_RAW_0_5;
|
||||
uint16_t PM_RAW_1_0;
|
||||
uint16_t PM_RAW_2_5;
|
||||
uint16_t PM_RAW_5_0;
|
||||
uint16_t PM_RAW_10_0;
|
||||
|
||||
// Formaldehyde (HCHO) concentration in mg/m^3 - PMSxxxxST units only
|
||||
uint16_t AMB_HCHO;
|
||||
|
||||
// Temperature & humidity - PMSxxxxST units only
|
||||
int16_t AMB_TMP;
|
||||
uint16_t AMB_HUM;
|
||||
};
|
||||
|
||||
bool begin(Stream *stream);
|
||||
void sleep();
|
||||
void wakeUp();
|
||||
void activeMode();
|
||||
void passiveMode();
|
||||
|
||||
void requestRead();
|
||||
bool read(DATA &data);
|
||||
bool readUntil(DATA &data, uint16_t timeout = SINGLE_RESPONSE_TIME);
|
||||
|
||||
private:
|
||||
enum STATUS { STATUS_WAITING, STATUS_OK };
|
||||
enum MODE { MODE_ACTIVE, MODE_PASSIVE };
|
||||
|
||||
uint8_t _payload[50];
|
||||
Stream *_stream;
|
||||
DATA *_data;
|
||||
STATUS _status;
|
||||
MODE _mode = MODE_ACTIVE;
|
||||
|
||||
uint8_t _index = 0;
|
||||
uint16_t _frameLen;
|
||||
uint16_t _checksum;
|
||||
uint16_t _calculatedChecksum;
|
||||
|
||||
void loop();
|
||||
char Char_PM2[10];
|
||||
};
|
||||
|
||||
#endif
|
73
src/S8/mb_crc.cpp
Normal file
73
src/S8/mb_crc.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "mb_crc.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* ModBus CRC routine extracted from
|
||||
* https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf */
|
||||
|
||||
/* Table of CRC values for high–order byte */
|
||||
static const uint8_t auchCRCHi[] = {
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40};
|
||||
|
||||
/* Table of CRC values for low–order byte */
|
||||
static const uint8_t auchCRCLo[] = {
|
||||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
||||
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
|
||||
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
|
||||
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
|
||||
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
||||
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
||||
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
|
||||
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
|
||||
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
|
||||
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
||||
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
||||
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
|
||||
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
|
||||
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
|
||||
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
||||
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
||||
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
|
||||
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
|
||||
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
|
||||
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
||||
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
||||
0x41, 0x81, 0x80, 0x40};
|
||||
|
||||
uint16_t AgMb16Crc(uint8_t *puchMsg, uint16_t usDataLen) {
|
||||
/*
|
||||
puchMsg -> message to calculate CRC upon
|
||||
usDataLen -> quantity of bytes in message
|
||||
*/
|
||||
uint8_t uchCRCHi = 0xFF; /* high byte of CRC initialized */
|
||||
uint8_t uchCRCLo = 0xFF; /* low byte of CRC initialized */
|
||||
uint16_t uIndex; /* will index into CRC lookup table */
|
||||
|
||||
while (usDataLen--) /* pass through message buffer */
|
||||
{
|
||||
uIndex = uchCRCLo ^ *puchMsg++; /* calculate the CRC */
|
||||
uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex];
|
||||
uchCRCHi = auchCRCLo[uIndex];
|
||||
}
|
||||
return (uchCRCHi << 8 | uchCRCLo);
|
||||
}
|
8
src/S8/mb_crc.h
Normal file
8
src/S8/mb_crc.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _AIR_GRADIENT_MODBUS_CRC_H_
|
||||
#define _AIR_GRADIENT_MODBUS_CRC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint16_t AgMb16Crc(uint8_t *buf, uint16_t len);
|
||||
|
||||
#endif /** _AIR_GRADIENT_MODBUS_CRC_H_ */
|
Reference in New Issue
Block a user