Browse Source

Merge branch 'dev' into sensor/veml6075

alexa
Xose Pérez 6 years ago
committed by GitHub
parent
commit
8b863c48eb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 763 additions and 86 deletions
  1. +1
    -1
      .travis.yml
  2. +6
    -5
      README.md
  3. +1
    -0
      code/espurna/api.ino
  4. +2
    -0
      code/espurna/config/arduino.h
  5. +12
    -0
      code/espurna/config/general.h
  6. +88
    -0
      code/espurna/config/hardware.h
  7. +3
    -0
      code/espurna/config/progmem.h
  8. +2
    -0
      code/espurna/config/prototypes.h
  9. +52
    -2
      code/espurna/config/sensors.h
  10. +1
    -0
      code/espurna/config/types.h
  11. +18
    -2
      code/espurna/debug.ino
  12. +43
    -0
      code/espurna/eeprom.ino
  13. +11
    -24
      code/espurna/ir.ino
  14. +10
    -0
      code/espurna/migrate.ino
  15. +1
    -1
      code/espurna/mqtt.ino
  16. +2
    -2
      code/espurna/relay.ino
  17. +94
    -1
      code/espurna/sensor.ino
  18. +6
    -6
      code/espurna/sensors/PMSX003Sensor.h
  19. +188
    -24
      code/espurna/sensors/PZEM004TSensor.h
  20. +119
    -0
      code/espurna/sensors/VL53L1XSensor.h
  21. +4
    -11
      code/espurna/settings.ino
  22. +9
    -1
      code/espurna/system.ino
  23. +13
    -5
      code/espurna/utils.ino
  24. +1
    -1
      code/html/custom.js
  25. +76
    -0
      code/platformio.ini
  26. BIN
      images/devices/tonbux-xs-ssa01.jpg

+ 1
- 1
.travis.yml View File

@ -11,7 +11,7 @@ cache:
install: install:
- pip install -U platformio - pip install -U platformio
- npm install -g npm@latest - npm install -g npm@latest
- cd code ; npm ci ; cd ..
- cd code && npm ci && cd ..
env: env:
global: global:
- BUILDER_TOTAL_THREADS=4 - BUILDER_TOTAL_THREADS=4


+ 6
- 5
README.md View File

@ -4,10 +4,11 @@ ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smar
It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries. It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries.
[![version](https://img.shields.io/badge/version-1.13.3-brightgreen.svg)](CHANGELOG.md) [![version](https://img.shields.io/badge/version-1.13.3-brightgreen.svg)](CHANGELOG.md)
[![branch](https://img.shields.io/badge/branch-master-orange.svg)](https://github.com/xoseperez/espurna/tree/master/)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=master)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard)
[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/xoseperez/espurna/tree/dev/)
[![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE) [![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=dev)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard)
[![downloads](https://img.shields.io/github/downloads/xoseperez/espurna/total.svg)](https://github.com/xoseperez/espurna/releases)
<br /> <br />
[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest)
[![gitter](https://img.shields.io/gitter/room/tinkermant-cat/espurna.svg)](https://gitter.im/tinkerman-cat/espurna) [![gitter](https://img.shields.io/gitter/room/tinkermant-cat/espurna.svg)](https://gitter.im/tinkerman-cat/espurna)
@ -239,8 +240,8 @@ Here is the list of supported hardware. For more information please refer to the
|**Maxcio W-US002S**|**HEYGO HY02**|**YiDian XS-SSA05**| |**Maxcio W-US002S**|**HEYGO HY02**|**YiDian XS-SSA05**|
|![WiOn 50055](images/devices/wion-50055.jpg)|![LINGAN SWA1](images/devices/lingan-swa1.jpg)|![HomeCube 16A](images/devices/homecube-16a.jpg)| |![WiOn 50055](images/devices/wion-50055.jpg)|![LINGAN SWA1](images/devices/lingan-swa1.jpg)|![HomeCube 16A](images/devices/homecube-16a.jpg)|
|**WiOn 50055**|**LINGAN SWA1**|**HomeCube 16A**| |**WiOn 50055**|**LINGAN SWA1**|**HomeCube 16A**|
|![WorkChoice EcoPlug](images/devices/workchoice-ecoplug.jpg)|![Bestek MRJ1011](images/devices/bestek-mrj1011.jpg)||
|**WorkChoice EcoPlug**|**Bestek MRJ1011**||
|![WorkChoice EcoPlug](images/devices/workchoice-ecoplug.jpg)|![Bestek MRJ1011](images/devices/bestek-mrj1011.jpg)|![Tonbux XS-SSA01](images/devices/tonbux-xs-ssa01.jpg)|
|**WorkChoice EcoPlug**|**Bestek MRJ1011**|**Tonbux XS-SSA01**|
|![Tonbux PowerStrip02](images/devices/tonbux-powerstrip02.jpg)|![ForNorm Power Strip](images/devices/fornorm-power-strip.jpg)|![Zhilde ZLD-EU55-W](images/devices/zhilde-zld-eu55-w.jpg)| |![Tonbux PowerStrip02](images/devices/tonbux-powerstrip02.jpg)|![ForNorm Power Strip](images/devices/fornorm-power-strip.jpg)|![Zhilde ZLD-EU55-W](images/devices/zhilde-zld-eu55-w.jpg)|
|**Tonbux PowerStrip02**|**Fornorm Power Strip**|**Zhilde ZLD-EU55-W**| |**Tonbux PowerStrip02**|**Fornorm Power Strip**|**Zhilde ZLD-EU55-W**|
|![Itead Sonoff Touch](images/devices/itead-sonoff-touch.jpg)|![Itead Sonoff T1](images/devices/itead-sonoff-t1.jpg)|![YJZK switch](images/devices/yjzk-2gang-switch.jpg)| |![Itead Sonoff Touch](images/devices/itead-sonoff-touch.jpg)|![Itead Sonoff T1](images/devices/itead-sonoff-t1.jpg)|![YJZK switch](images/devices/yjzk-2gang-switch.jpg)|


+ 1
- 0
code/espurna/api.ino View File

@ -221,6 +221,7 @@ void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f
} }
void apiSetup() { void apiSetup() {
_apiConfigure();
wsOnSendRegister(_apiWebSocketOnSend); wsOnSendRegister(_apiWebSocketOnSend);
wsOnReceiveRegister(_apiWebSocketOnReceive); wsOnReceiveRegister(_apiWebSocketOnReceive);
webRequestRegister(_apiRequestCallback); webRequestRegister(_apiRequestCallback);


+ 2
- 0
code/espurna/config/arduino.h View File

@ -72,6 +72,7 @@
//#define MAXCIO_WUS002S //#define MAXCIO_WUS002S
//#define YIDIAN_XSSSA05 //#define YIDIAN_XSSSA05
//#define TONBUX_XSSSA06 //#define TONBUX_XSSSA06
//#define TONBUX_XSSSA01
//#define GREEN_ESP8266RELAY //#define GREEN_ESP8266RELAY
//#define IKE_ESPIKE //#define IKE_ESPIKE
//#define ARNIEX_SWIFITCH //#define ARNIEX_SWIFITCH
@ -172,3 +173,4 @@
//#define SONAR_SUPPORT 1 //#define SONAR_SUPPORT 1
//#define TMP3X_SUPPORT 1 //#define TMP3X_SUPPORT 1
//#define V9261F_SUPPORT 1 //#define V9261F_SUPPORT 1
//#define VL53L1X_SUPPORT 1

+ 12
- 0
code/espurna/config/general.h View File

@ -187,6 +187,7 @@
// Topics that will be reported in heartbeat // Topics that will be reported in heartbeat
#define HEARTBEAT_REPORT_STATUS 1 #define HEARTBEAT_REPORT_STATUS 1
#define HEARTBEAT_REPORT_SSID 1
#define HEARTBEAT_REPORT_IP 1 #define HEARTBEAT_REPORT_IP 1
#define HEARTBEAT_REPORT_MAC 1 #define HEARTBEAT_REPORT_MAC 1
#define HEARTBEAT_REPORT_RSSI 1 #define HEARTBEAT_REPORT_RSSI 1
@ -236,6 +237,9 @@
#ifndef BUTTON_LNGLNGCLICK_DELAY #ifndef BUTTON_LNGLNGCLICK_DELAY
#define BUTTON_LNGLNGCLICK_DELAY 10000 // Time in ms holding the button down to get a long-long click #define BUTTON_LNGLNGCLICK_DELAY 10000 // Time in ms holding the button down to get a long-long click
#endif
#ifndef BUTTON_MQTT_SEND_ALL_EVENTS
#define BUTTON_MQTT_SEND_ALL_EVENTS 0 // 0 - to send only events the are bound to actions #define BUTTON_MQTT_SEND_ALL_EVENTS 0 // 0 - to send only events the are bound to actions
// 1 - to send all button events to MQTT // 1 - to send all button events to MQTT
#endif #endif
@ -434,7 +438,9 @@
// or in the Internet. Since the WebUI is just one compressed file with HTML, CSS and JS // or in the Internet. Since the WebUI is just one compressed file with HTML, CSS and JS
// there are no special requirements. Any static web server will do (NGinx, Apache, Lighttpd,...). // there are no special requirements. Any static web server will do (NGinx, Apache, Lighttpd,...).
// The only requirement is that the resource must be available under this domain. // The only requirement is that the resource must be available under this domain.
#ifndef WEB_REMOTE_DOMAIN
#define WEB_REMOTE_DOMAIN "http://tinkerman.cat" #define WEB_REMOTE_DOMAIN "http://tinkerman.cat"
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// WEBSOCKETS // WEBSOCKETS
@ -731,6 +737,7 @@
#define MQTT_TOPIC_LED "led" #define MQTT_TOPIC_LED "led"
#define MQTT_TOPIC_BUTTON "button" #define MQTT_TOPIC_BUTTON "button"
#define MQTT_TOPIC_IP "ip" #define MQTT_TOPIC_IP "ip"
#define MQTT_TOPIC_SSID "ssid"
#define MQTT_TOPIC_VERSION "version" #define MQTT_TOPIC_VERSION "version"
#define MQTT_TOPIC_UPTIME "uptime" #define MQTT_TOPIC_UPTIME "uptime"
#define MQTT_TOPIC_DATETIME "datetime" #define MQTT_TOPIC_DATETIME "datetime"
@ -925,8 +932,13 @@
#define HOMEASSISTANT_SUPPORT MQTT_SUPPORT // Build with home assistant support (if MQTT, 1.64Kb) #define HOMEASSISTANT_SUPPORT MQTT_SUPPORT // Build with home assistant support (if MQTT, 1.64Kb)
#endif #endif
#ifndef HOMEASSISTANT_ENABLED
#define HOMEASSISTANT_ENABLED 0 // Integration not enabled by default #define HOMEASSISTANT_ENABLED 0 // Integration not enabled by default
#endif
#ifndef HOMEASSISTANT_PREFIX
#define HOMEASSISTANT_PREFIX "homeassistant" // Default MQTT prefix #define HOMEASSISTANT_PREFIX "homeassistant" // Default MQTT prefix
#endif
#ifndef HOMEASSISTANT_PAYLOAD_ON #ifndef HOMEASSISTANT_PAYLOAD_ON
#define HOMEASSISTANT_PAYLOAD_ON "1" // Payload for ON and available messages #define HOMEASSISTANT_PAYLOAD_ON "1" // Payload for ON and available messages


+ 88
- 0
code/espurna/config/hardware.h View File

@ -1920,6 +1920,29 @@
#define HLW8012_CURRENT_R 0.002 // Current resistor #define HLW8012_CURRENT_R 0.002 // Current resistor
#define HLW8012_VOLTAGE_R_UP ( 2 * 1000000 ) // Upstream voltage resistor #define HLW8012_VOLTAGE_R_UP ( 2 * 1000000 ) // Upstream voltage resistor
// -----------------------------------------------------------------------------
// Maxcio W-DE004
// -----------------------------------------------------------------------------
#elif defined(MAXCIO_WDE004)
// Info
#define MANUFACTURER "MAXCIO"
#define DEVICE "WDE004"
// Buttons
#define BUTTON1_PIN 1
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// Relays
#define RELAY1_PIN 14
#define RELAY1_TYPE RELAY_TYPE_NORMAL
// LEDs
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// YiDian XS-SSA05 // YiDian XS-SSA05
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1962,6 +1985,29 @@
#define HLW8012_POWER_RATIO 3414290 #define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING #define HLW8012_INTERRUPT_ON FALLING
// -----------------------------------------------------------------------------
// TONBUX XS-SSA01
// -----------------------------------------------------------------------------
#elif defined(TONBUX_XSSSA01)
// Info
#define MANUFACTURER "TONBUX"
#define DEVICE "XSSSA01"
// Buttons
#define BUTTON1_PIN 4
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// Relays
#define RELAY1_PIN 14
#define RELAY1_TYPE RELAY_TYPE_NORMAL
// LEDs
#define LED1_PIN 13
#define LED1_PIN_INVERSE 0
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// TONBUX XS-SSA06 // TONBUX XS-SSA06
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -2530,6 +2576,47 @@
#define HLW8012_POWER_RATIO 3414290 #define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING #define HLW8012_INTERRUPT_ON FALLING
// -----------------------------------------------------------------------------
// Same as the above but new board version marked V2.3
// -----------------------------------------------------------------------------
#elif defined(BLITZWOLF_BWSHP2_V23)
// Info
#define MANUFACTURER "BLITZWOLF"
#define DEVICE "BWSHP2V2.3"
// Buttons
#define BUTTON1_PIN 3
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// Relays
#define RELAY1_PIN 14
#define RELAY1_TYPE RELAY_TYPE_NORMAL
// LEDs
#define LED1_PIN 1
#define LED1_PIN_INVERSE 1
#define LED2_PIN 13
#define LED2_PIN_INVERSE 1
#define LED2_MODE LED_MODE_FINDME
#define LED2_RELAY 1
// HJL01 / BL0937
#ifndef HLW8012_SUPPORT
#define HLW8012_SUPPORT 1
#endif
#define HLW8012_SEL_PIN 12
#define HLW8012_CF1_PIN 5
#define HLW8012_CF_PIN 4
#define HLW8012_SEL_CURRENT LOW
#define HLW8012_CURRENT_RATIO 25740
#define HLW8012_VOLTAGE_RATIO 313400
#define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Homecube 16A is similar but some pins differ and it also has RGB LEDs // Homecube 16A is similar but some pins differ and it also has RGB LEDs
// https://www.amazon.de/gp/product/B07D7RVF56/ref=oh_aui_detailpage_o00_s01?ie=UTF8&psc=1 // https://www.amazon.de/gp/product/B07D7RVF56/ref=oh_aui_detailpage_o00_s01?ie=UTF8&psc=1
@ -2896,6 +2983,7 @@
#define SI7021_SUPPORT 1 #define SI7021_SUPPORT 1
#define PMSX003_SUPPORT 1 #define PMSX003_SUPPORT 1
#define SENSEAIR_SUPPORT1 #define SENSEAIR_SUPPORT1
#define VL53L1X_SUPPORT 1
// A bit of lights - pin 5 // A bit of lights - pin 5


+ 3
- 0
code/espurna/config/progmem.h View File

@ -226,6 +226,9 @@ PROGMEM const char espurna_sensors[] =
#if VEML6075_SUPPORT #if VEML6075_SUPPORT
"VEML6075 " "VEML6075 "
#endif #endif
#if VL53L1X_SUPPORT
"VL53L1X "
#endif
""; "";


+ 2
- 0
code/espurna/config/prototypes.h View File

@ -69,6 +69,8 @@ extern "C" {
#include <EEPROM_Rotate.h> #include <EEPROM_Rotate.h>
EEPROM_Rotate EEPROMr; EEPROM_Rotate EEPROMr;
void eepromSectorsDebug();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GPIO // GPIO
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 52
- 2
code/espurna/config/sensors.h View File

@ -115,6 +115,39 @@
#define BH1750_MODE BH1750_CONTINUOUS_HIGH_RES_MODE #define BH1750_MODE BH1750_CONTINUOUS_HIGH_RES_MODE
//------------------------------------------------------------------------------
// VL53L1X
// Enable support by passing VL53L1X_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef VL53L1X_SUPPORT
#define VL53L1X_SUPPORT 0
#endif
#ifndef VL53L1X_I2C_ADDRESS
#define VL53L1X_I2C_ADDRESS 0x00 // 0x00 means auto
#endif
#ifndef VL53L1X_DISTANCE_MODE
#define VL53L1X_DISTANCE_MODE VL53L1X::Long // The distance mode of the sensor. Can be one of
#endif // `VL53L1X::Short`, `VL53L1X::Medium`, or `VL53L1X::Long.
// Shorter distance modes are less affected by ambient light
// but have lower maximum ranges, especially in the dark.
#ifndef VL53L1X_MEASUREMENT_TIMING_BUDGET
#define VL53L1X_MEASUREMENT_TIMING_BUDGET 140000 // The time, in microseconds, allocated for a single
// measurement. A longer timing budget allows for more
// accurate at the cost of power. The minimum budget is
// 20 ms (20000 us) in short distance mode and 33 ms for
// medium and long distance modes.
#endif
#ifndef VL53L1X_INTER_MEASUREMENT_PERIOD
#define VL53L1X_INTER_MEASUREMENT_PERIOD 50 // Period, in milliseconds, determining how
#endif // often the sensor takes a measurement.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// BME280/BMP280 // BME280/BMP280
// Enable support by passing BMX280_SUPPORT=1 build flag // Enable support by passing BMX280_SUPPORT=1 build flag
@ -245,7 +278,7 @@
#define EMON_FILTER_SPEED 512 // Mobile average filter speed #define EMON_FILTER_SPEED 512 // Mobile average filter speed
#define EMON_MAINS_VOLTAGE 230 // Mains voltage #define EMON_MAINS_VOLTAGE 230 // Mains voltage
#define EMON_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC #define EMON_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC
#define EMON_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A)
#define EMON_CURRENT_RATIO 30 // Current ratio in the clamp (30A/1V)
#define EMON_REPORT_CURRENT 0 // Report current #define EMON_REPORT_CURRENT 0 // Report current
#define EMON_REPORT_POWER 1 // Report power #define EMON_REPORT_POWER 1 // Report power
#define EMON_REPORT_ENERGY 1 // Report energy #define EMON_REPORT_ENERGY 1 // Report energy
@ -600,6 +633,18 @@
#define PZEM004T_HW_PORT Serial // Hardware serial port (if PZEM004T_USE_SOFT == 0) #define PZEM004T_HW_PORT Serial // Hardware serial port (if PZEM004T_USE_SOFT == 0)
#endif #endif
#ifndef PZEM004T_ADDRESSES
#define PZEM004T_ADDRESSES "192.168.1.1" // Device(s) address(es), separated by space, "192.168.1.1 192.168.1.2 192.168.1.3"
#endif
#ifndef PZEM004T_READ_INTERVAL
#define PZEM004T_READ_INTERVAL 1500 // Read interval between same device
#endif
#ifndef PZEM004T_MAX_DEVICES
#define PZEM004T_MAX_DEVICES 3
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// SHT3X I2C (Wemos) temperature & humidity sensor // SHT3X I2C (Wemos) temperature & humidity sensor
// Enable support by passing SHT3X_I2C_SUPPORT=1 build flag // Enable support by passing SHT3X_I2C_SUPPORT=1 build flag
@ -744,7 +789,8 @@
SONAR_SUPPORT || \ SONAR_SUPPORT || \
TMP3X_SUPPORT || \ TMP3X_SUPPORT || \
V9261F_SUPPORT || \ V9261F_SUPPORT || \
VEML6075_SUPPORT \
VEML6075_SUPPORT || \
VL53L1X_SUPPORT \
) )
#endif #endif
@ -906,4 +952,8 @@
#include "../sensors/VEML6075Sensor.h" #include "../sensors/VEML6075Sensor.h"
#endif #endif
#if VL53L1X_SUPPORT
#include "../sensors/VL53L1XSensor.h"
#endif
#endif // SENSOR_SUPPORT #endif // SENSOR_SUPPORT

+ 1
- 0
code/espurna/config/types.h View File

@ -280,6 +280,7 @@
#define SENSOR_MICS2710_ID 0x28 #define SENSOR_MICS2710_ID 0x28
#define SENSOR_MICS5525_ID 0x29 #define SENSOR_MICS5525_ID 0x29
#define SENSOR_VEML6075_ID 0x30 #define SENSOR_VEML6075_ID 0x30
#define SENSOR_VL53L1X_ID 0x31
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Magnitudes // Magnitudes


+ 18
- 2
code/espurna/debug.ino View File

@ -209,6 +209,11 @@ void debugSetup() {
*/ */
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack_start, uint32_t stack_end ) { extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack_start, uint32_t stack_end ) {
// Do not record crash data when resetting the board
if (checkNeedsReset()) {
return;
}
// This method assumes EEPROM has already been initialized // This method assumes EEPROM has already been initialized
// which is the first thing ESPurna does // which is the first thing ESPurna does
@ -231,9 +236,13 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
EEPROMr.put(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_START, stack_start); EEPROMr.put(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_START, stack_start);
EEPROMr.put(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_END, stack_end); EEPROMr.put(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_END, stack_end);
// write stack trace to EEPROM
// starting address of Embedis data plus reserve
const uint16_t settings_start = SPI_FLASH_SEC_SIZE - settingsSize() - 0x10;
// write stack trace to EEPROM and avoid overwriting settings
int16_t current_address = SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_TRACE; int16_t current_address = SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_TRACE;
for (uint32_t i = stack_start; i < stack_end; i++) { for (uint32_t i = stack_start; i < stack_end; i++) {
if (current_address >= settings_start) break;
byte* byteValue = (byte*) i; byte* byteValue = (byte*) i;
EEPROMr.write(current_address++, *byteValue); EEPROMr.write(current_address++, *byteValue);
} }
@ -273,16 +282,23 @@ void debugDumpCrashInfo() {
EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_EPC3, epc3); EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_EPC3, epc3);
EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_EXCVADDR, excvaddr); EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_EXCVADDR, excvaddr);
EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_DEPC, depc); EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_DEPC, depc);
DEBUG_MSG_P(PSTR("[DEBUG] epc1=0x%08x epc2=0x%08x epc3=0x%08x\n"), epc1, epc2, epc3); DEBUG_MSG_P(PSTR("[DEBUG] epc1=0x%08x epc2=0x%08x epc3=0x%08x\n"), epc1, epc2, epc3);
DEBUG_MSG_P(PSTR("[DEBUG] excvaddr=0x%08x depc=0x%08x\n"), excvaddr, depc); DEBUG_MSG_P(PSTR("[DEBUG] excvaddr=0x%08x depc=0x%08x\n"), excvaddr, depc);
uint32_t stack_start, stack_end; uint32_t stack_start, stack_end;
EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_START, stack_start); EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_START, stack_start);
EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_END, stack_end); EEPROMr.get(SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_END, stack_end);
DEBUG_MSG_P(PSTR("[DEBUG] >>>stack>>>\n[DEBUG] "));
DEBUG_MSG_P(PSTR("[DEBUG] sp=0x%08x end=0x%08x\n"), stack_start, stack_end);
int16_t current_address = SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_TRACE; int16_t current_address = SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_TRACE;
int16_t stack_len = stack_end - stack_start; int16_t stack_len = stack_end - stack_start;
uint32_t stack_trace; uint32_t stack_trace;
DEBUG_MSG_P(PSTR("[DEBUG] >>>stack>>>\n[DEBUG] "));
for (int16_t i = 0; i < stack_len; i += 0x10) { for (int16_t i = 0; i < stack_len; i += 0x10) {
DEBUG_MSG_P(PSTR("%08x: "), stack_start + i); DEBUG_MSG_P(PSTR("%08x: "), stack_start + i);
for (byte j = 0; j < 4; j++) { for (byte j = 0; j < 4; j++) {


+ 43
- 0
code/espurna/eeprom.ino View File

@ -8,6 +8,11 @@ EEPROM MODULE
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool _eeprom_commit = false;
uint32_t _eeprom_commit_count = 0;
bool _eeprom_last_commit_result = false;
void eepromRotate(bool value) { void eepromRotate(bool value) {
// Enable/disable EEPROM rotation only if we are using more sectors than the // Enable/disable EEPROM rotation only if we are using more sectors than the
// reserved by the memory layout // reserved by the memory layout
@ -34,15 +39,44 @@ String eepromSectors() {
return response; return response;
} }
void eepromSectorsDebug() {
DEBUG_MSG_P(PSTR("[MAIN] EEPROM sectors: %s\n"), (char *) eepromSectors().c_str());
DEBUG_MSG_P(PSTR("[MAIN] EEPROM current: %lu\n"), eepromCurrent());
}
bool _eepromCommit() {
_eeprom_commit_count++;
_eeprom_last_commit_result = EEPROMr.commit();
return _eeprom_last_commit_result;
}
void eepromCommit() {
_eeprom_commit = true;
}
#if TERMINAL_SUPPORT #if TERMINAL_SUPPORT
void _eepromInitCommands() { void _eepromInitCommands() {
settingsRegisterCommand(F("EEPROM"), [](Embedis* e) { settingsRegisterCommand(F("EEPROM"), [](Embedis* e) {
infoMemory("EEPROM", SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE - settingsSize()); infoMemory("EEPROM", SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE - settingsSize());
eepromSectorsDebug();
if (_eeprom_commit_count > 0) {
DEBUG_MSG_P(PSTR("[MAIN] Commits done: %lu\n"), _eeprom_commit_count);
DEBUG_MSG_P(PSTR("[MAIN] Last result: %s\n"), _eeprom_last_commit_result ? "OK" : "ERROR");
}
DEBUG_MSG_P(PSTR("+OK\n")); DEBUG_MSG_P(PSTR("+OK\n"));
}); });
settingsRegisterCommand(F("EEPROM.COMMIT"), [](Embedis* e) {
const bool res = _eepromCommit();
if (res) {
DEBUG_MSG_P(PSTR("+OK\n"));
} else {
DEBUG_MSG_P(PSTR("-ERROR\n"));
}
});
settingsRegisterCommand(F("EEPROM.DUMP"), [](Embedis* e) { settingsRegisterCommand(F("EEPROM.DUMP"), [](Embedis* e) {
EEPROMr.dump(settingsSerial()); EEPROMr.dump(settingsSerial());
DEBUG_MSG_P(PSTR("\n+OK\n")); DEBUG_MSG_P(PSTR("\n+OK\n"));
@ -69,6 +103,13 @@ void _eepromInitCommands() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void eepromLoop() {
if (_eeprom_commit) {
_eepromCommit();
_eeprom_commit = false;
}
}
void eepromSetup() { void eepromSetup() {
#ifdef EEPROM_ROTATE_SECTORS #ifdef EEPROM_ROTATE_SECTORS
@ -92,4 +133,6 @@ void eepromSetup() {
_eepromInitCommands(); _eepromInitCommands();
#endif #endif
espurnaRegisterLoop(eepromLoop);
} }

+ 11
- 24
code/espurna/ir.ino View File

@ -43,8 +43,6 @@ Raw messages:
Payload: 1000,1000,1000,1000,1000 Payload: 1000,1000,1000,1000,1000
| IR codes | | IR codes |
* To support long codes (Air Conditioneer) increase MQTT packet size -DMQTT_MAX_PACKET_SIZE=1200
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
*/ */
@ -91,7 +89,6 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
} }
if (type == MQTT_MESSAGE_EVENT) { if (type == MQTT_MESSAGE_EVENT) {
String t = mqttMagnitude((char *) topic); String t = mqttMagnitude((char *) topic);
// Match topic // Match topic
@ -110,7 +107,7 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
_ir_repeat_size = 1; _ir_repeat_size = 1;
// count & validate repeat-string // count & validate repeat-string
for(int i = col+1; i < len; i++) {
for(unsigned int i = col+1; i < len; i++) {
if (i < len-1) { if (i < len-1) {
if ( payload[i] == ',' && isDigit(payload[i+1]) && i>0 ) { //validate string if ( payload[i] == ',' && isDigit(payload[i+1]) && i>0 ) { //validate string
_ir_repeat_size++; _ir_repeat_size++;
@ -129,7 +126,7 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
} // end of counting & validating repeat code } // end of counting & validating repeat code
// count & validate main code string // count & validate main code string
for(int i = 0; i < len; i++) {
for(unsigned int i = 0; i < len; i++) {
if (i<len-1) { if (i<len-1) {
if ( payload[i] == ',' && isDigit(payload[i+1]) && i>0 ) { //validate string if ( payload[i] == ',' && isDigit(payload[i+1]) && i>0 ) { //validate string
count++; count++;
@ -149,7 +146,7 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
int j = 0; // for populating values of array from comma separated string int j = 0; // for populating values of array from comma separated string
// populating main code array from part of MQTT string // populating main code array from part of MQTT string
for (int i = 0; i < len; i++) {
for (unsigned int i = 0; i < len; i++) {
if (payload[i] != ',') { if (payload[i] != ',') {
value = value + data[i]; value = value + data[i];
} }
@ -173,14 +170,6 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
DEBUG_MSG_P(PSTR("[IR] Raw IR output %d codes, repeat %d times on %d(k)Hz freq.\n"), count, _ir_repeat, _ir_freq); DEBUG_MSG_P(PSTR("[IR] Raw IR output %d codes, repeat %d times on %d(k)Hz freq.\n"), count, _ir_repeat, _ir_freq);
/*
DEBUG_MSG_P(PSTR("[IR] main codes: "));
for(int i = 0; i < count; i++) {
DEBUG_MSG_P(PSTR("%d,"),_ir_raw[i]);
}
DEBUG_MSG_P(PSTR("\n"));
*/
#if defined(IR_RX_PIN) #if defined(IR_RX_PIN)
_ir_receiver.disableIRIn(); _ir_receiver.disableIRIn();
#endif #endif
@ -203,7 +192,7 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
len = data.length(); //redifining length to full lenght len = data.length(); //redifining length to full lenght
// populating repeat code array from part of MQTT string // populating repeat code array from part of MQTT string
for (int i = col+1; i < len; i++) {
for (unsigned int i = col+1; i < len; i++) {
value = value + data[i]; value = value + data[i];
if ((payload[i] == ',') || (i == len - 1)) { if ((payload[i] == ',') || (i == len - 1)) {
_ir_raw[j]= value.toInt(); _ir_raw[j]= value.toInt();
@ -211,7 +200,6 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
j++; j++;
} }
} }
} else { // if repeat code not specified (col<=2) repeat with current main code } else { // if repeat code not specified (col<=2) repeat with current main code
_ir_repeat_size = count; _ir_repeat_size = count;
} }
@ -223,7 +211,7 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
if (col > 0) { if (col > 0) {
_ir_type = data.toInt(); _ir_type = data.toInt();
_ir_code = data.substring(col+1).toInt();
_ir_code = strtoul(data.substring(col+1).c_str(), NULL, 10);
col = data.indexOf(":", col+1); col = data.indexOf(":", col+1);
if (col > 0) { if (col > 0) {
@ -234,9 +222,7 @@ void _irMqttCallback(unsigned int type, const char * topic, const char * payload
} else { } else {
_ir_repeat = IR_REPEAT; _ir_repeat = IR_REPEAT;
} }
} }
} }
if (_ir_repeat > 0) { if (_ir_repeat > 0) {
@ -364,12 +350,9 @@ void _irRXLoop() {
if (millis() - last_time < IR_DEBOUNCE) return; if (millis() - last_time < IR_DEBOUNCE) return;
last_time = millis(); last_time = millis();
// Check code
if (_ir_results.value < 1) return;
if (_ir_results.decode_type < 1) return;
if (_ir_results.bits < 1) return;
#if IR_USE_RAW #if IR_USE_RAW
// Check code
if (_ir_results.rawlen < 1) return;
char * payload; char * payload;
String value = ""; String value = "";
for (int i = 1; i < _ir_results.rawlen; i++) { for (int i = 1; i < _ir_results.rawlen; i++) {
@ -378,6 +361,10 @@ void _irRXLoop() {
} }
payload = const_cast<char*>(value.c_str()); payload = const_cast<char*>(value.c_str());
#else #else
// Check code
if (_ir_results.value < 1) return;
if (_ir_results.decode_type < 1) return;
if (_ir_results.bits < 1) return;
char payload[32]; char payload[32];
snprintf_P(payload, sizeof(payload), PSTR("%u:%lu:%u"), _ir_results.decode_type, (unsigned long) _ir_results.value, _ir_results.bits); snprintf_P(payload, sizeof(payload), PSTR("%u:%lu:%u"), _ir_results.decode_type, (unsigned long) _ir_results.value, _ir_results.bits);
#endif #endif


+ 10
- 0
code/espurna/migrate.ino View File

@ -1223,6 +1223,16 @@ void migrate() {
setSetting("ledGPIO", 1, 15); setSetting("ledGPIO", 1, 15);
setSetting("ledLogic", 1, 0); setSetting("ledLogic", 1, 0);
#elif defined(TONBUX_XSSSA01)
setSetting("board", 92);
setSetting("ledGPIO", 0, 13);
setSetting("ledLogic", 0, 0);
setSetting("btnGPIO", 0, 13);
setSetting("btnRelay", 0, 0);
setSetting("relayGPIO", 0, 5);
setSetting("relayType", 0, RELAY_TYPE_NORMAL);
#else #else
// Allow users to define new settings without migration config // Allow users to define new settings without migration config


+ 1
- 1
code/espurna/mqtt.ino View File

@ -291,7 +291,7 @@ unsigned long _mqttNextMessageId() {
EEPROMr.write(EEPROM_MESSAGE_ID + 1, (id >> 16) & 0xFF); EEPROMr.write(EEPROM_MESSAGE_ID + 1, (id >> 16) & 0xFF);
EEPROMr.write(EEPROM_MESSAGE_ID + 2, (id >> 8) & 0xFF); EEPROMr.write(EEPROM_MESSAGE_ID + 2, (id >> 8) & 0xFF);
EEPROMr.write(EEPROM_MESSAGE_ID + 3, (id >> 0) & 0xFF); EEPROMr.write(EEPROM_MESSAGE_ID + 3, (id >> 0) & 0xFF);
saveSettings();
eepromCommit();
} }
id++; id++;


+ 2
- 2
code/espurna/relay.ino View File

@ -418,7 +418,7 @@ void relaySave(bool do_commit) {
// We are actually enqueuing the commit so it will be // We are actually enqueuing the commit so it will be
// executed on the main loop, in case this is called from a callback // executed on the main loop, in case this is called from a callback
saveSettings();
eepromCommit();
} }
@ -548,7 +548,7 @@ void _relayBoot() {
// Save if there is any relay in the RELAY_BOOT_TOGGLE mode // Save if there is any relay in the RELAY_BOOT_TOGGLE mode
if (trigger_save) { if (trigger_save) {
EEPROMr.write(EEPROM_RELAY_STATUS, mask); EEPROMr.write(EEPROM_RELAY_STATUS, mask);
saveSettings();
eepromCommit();
} }
_relayRecursive = false; _relayRecursive = false;


+ 94
- 1
code/espurna/sensor.ino View File

@ -42,6 +42,10 @@ unsigned char _sensor_temperature_units = SENSOR_TEMPERATURE_UNITS;
double _sensor_temperature_correction = SENSOR_TEMPERATURE_CORRECTION; double _sensor_temperature_correction = SENSOR_TEMPERATURE_CORRECTION;
double _sensor_humidity_correction = SENSOR_HUMIDITY_CORRECTION; double _sensor_humidity_correction = SENSOR_HUMIDITY_CORRECTION;
#if PZEM004T_SUPPORT
PZEM004TSensor *pzem004t_sensor;
#endif
String _sensor_energy_reset_ts = String(); String _sensor_energy_reset_ts = String();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -272,6 +276,63 @@ void _sensorInitCommands() {
} }
DEBUG_MSG_P(PSTR("+OK\n")); DEBUG_MSG_P(PSTR("+OK\n"));
}); });
#if PZEM004T_SUPPORT
settingsRegisterCommand(F("PZ.ADDRESS"), [](Embedis* e) {
if (e->argc == 1) {
DEBUG_MSG_P(PSTR("[SENSOR] PZEM004T\n"));
unsigned char dev_count = pzem004t_sensor->getAddressesCount();
for(unsigned char dev = 0; dev < dev_count; dev++) {
DEBUG_MSG_P(PSTR("Device %d/%s\n"), dev, pzem004t_sensor->getAddress(dev).c_str());
}
DEBUG_MSG_P(PSTR("+OK\n"));
} else if(e->argc == 2) {
IPAddress addr;
if (addr.fromString(String(e->argv[1]))) {
if(pzem004t_sensor->setDeviceAddress(&addr)) {
DEBUG_MSG_P(PSTR("+OK\n"));
}
} else {
DEBUG_MSG_P(PSTR("-ERROR: Invalid address argument\n"));
}
} else {
DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n"));
}
});
settingsRegisterCommand(F("PZ.RESET"), [](Embedis* e) {
if(e->argc > 2) {
DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n"));
} else {
unsigned char init = e->argc == 2 ? String(e->argv[1]).toInt() : 0;
unsigned char limit = e->argc == 2 ? init +1 : pzem004t_sensor->getAddressesCount();
DEBUG_MSG_P(PSTR("[SENSOR] PZEM004T\n"));
for(unsigned char dev = init; dev < limit; dev++) {
float offset = pzem004t_sensor->resetEnergy(dev);
setSetting("pzEneTotal", dev, offset);
DEBUG_MSG_P(PSTR("Device %d/%s - Offset: %s\n"), dev, pzem004t_sensor->getAddress(dev).c_str(), String(offset).c_str());
}
DEBUG_MSG_P(PSTR("+OK\n"));
}
});
settingsRegisterCommand(F("PZ.VALUE"), [](Embedis* e) {
if(e->argc > 2) {
DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n"));
} else {
unsigned char init = e->argc == 2 ? String(e->argv[1]).toInt() : 0;
unsigned char limit = e->argc == 2 ? init +1 : pzem004t_sensor->getAddressesCount();
DEBUG_MSG_P(PSTR("[SENSOR] PZEM004T\n"));
for(unsigned char dev = init; dev < limit; dev++) {
DEBUG_MSG_P(PSTR("Device %d/%s - Current: %s Voltage: %s Power: %s Energy: %s\n"), //
dev,
pzem004t_sensor->getAddress(dev).c_str(),
String(pzem004t_sensor->value(dev * PZ_MAGNITUDE_CURRENT_INDEX)).c_str(),
String(pzem004t_sensor->value(dev * PZ_MAGNITUDE_VOLTAGE_INDEX)).c_str(),
String(pzem004t_sensor->value(dev * PZ_MAGNITUDE_POWER_ACTIVE_INDEX)).c_str(),
String(pzem004t_sensor->value(dev * PZ_MAGNITUDE_ENERGY_INDEX)).c_str());
}
DEBUG_MSG_P(PSTR("+OK\n"));
}
});
#endif
} }
#endif #endif
@ -593,13 +654,20 @@ void _sensorLoad() {
#if PZEM004T_SUPPORT #if PZEM004T_SUPPORT
{ {
PZEM004TSensor * sensor = new PZEM004TSensor();
PZEM004TSensor * sensor = pzem004t_sensor = new PZEM004TSensor();
#if PZEM004T_USE_SOFT #if PZEM004T_USE_SOFT
sensor->setRX(PZEM004T_RX_PIN); sensor->setRX(PZEM004T_RX_PIN);
sensor->setTX(PZEM004T_TX_PIN); sensor->setTX(PZEM004T_TX_PIN);
#else #else
sensor->setSerial(& PZEM004T_HW_PORT); sensor->setSerial(& PZEM004T_HW_PORT);
#endif #endif
sensor->setAddresses(PZEM004T_ADDRESSES);
// Read saved energy offset
unsigned char dev_count = sensor->getAddressesCount();
for(unsigned char dev = 0; dev < dev_count; dev++) {
float value = getSetting("pzEneTotal", dev, 0).toFloat();
if (value > 0) sensor->resetEnergy(dev, value);
}
_sensors.push_back(sensor); _sensors.push_back(sensor);
} }
#endif #endif
@ -644,6 +712,15 @@ void _sensorLoad() {
sensor->setDynamicMode(VEML6075_DYNAMIC_MODE); sensor->setDynamicMode(VEML6075_DYNAMIC_MODE);
_sensors.push_back(sensor); _sensors.push_back(sensor);
} }
#if VL53L1X_SUPPORT
{
VL53L1XSensor * sensor = new VL53L1XSensor();
sensor->setInterMeasurementPeriod(VL53L1X_INTER_MEASUREMENT_PERIOD);
sensor->setDistanceMode(VL53L1X_DISTANCE_MODE);
sensor->setMeasurementTimingBudget(VL53L1X_MEASUREMENT_TIMING_BUDGET);
_sensors.push_back(sensor);
}
#endif #endif
} }
@ -978,6 +1055,22 @@ void _sensorConfigure() {
#endif // CSE7766_SUPPORT #endif // CSE7766_SUPPORT
#if PZEM004T_SUPPORT
if (_sensors[i]->getID() == SENSOR_PZEM004T_ID) {
PZEM004TSensor * sensor = (PZEM004TSensor *) _sensors[i];
if (getSetting("pwrResetE", 0).toInt() == 1) {
unsigned char dev_count = sensor->getAddressesCount();
for(unsigned char dev = 0; dev < dev_count; dev++) {
sensor->resetEnergy(dev, 0);
delSetting("pzEneTotal", dev);
}
_sensorResetTS();
}
}
#endif // PZEM004T_SUPPORT
} }
// Update filter sizes // Update filter sizes


+ 6
- 6
code/espurna/sensors/PMSX003Sensor.h View File

@ -90,7 +90,7 @@ class PMSX003 {
int avail = _serial->available(); int avail = _serial->available();
#if SENSOR_DEBUG #if SENSOR_DEBUG
//debugSend("[SENSOR] PMS: Packet available = %d\n", avail);
//DEBUG_MSG("[SENSOR] PMS: Packet available = %d\n", avail);
#endif #endif
if (avail < PMS_PACKET_SIZE(data_count)) { if (avail < PMS_PACKET_SIZE(data_count)) {
break; break;
@ -102,7 +102,7 @@ class PMSX003 {
uint16_t size = read16(sum); uint16_t size = read16(sum);
if (size != PMS_PAYLOAD_SIZE(data_count)) { if (size != PMS_PAYLOAD_SIZE(data_count)) {
#if SENSOR_DEBUG #if SENSOR_DEBUG
debugSend(("[SENSOR] PMS: Payload size: %d != %d.\n"), size, PMS_PAYLOAD_SIZE(data_count));
DEBUG_MSG(("[SENSOR] PMS: Payload size: %d != %d.\n"), size, PMS_PAYLOAD_SIZE(data_count));
#endif #endif
break; break;
} }
@ -110,7 +110,7 @@ class PMSX003 {
for (int i = 0; i < data_count; i++) { for (int i = 0; i < data_count; i++) {
data[i] = read16(sum); data[i] = read16(sum);
#if SENSOR_DEBUG #if SENSOR_DEBUG
//debugSend(("[SENSOR] PMS: data[%d] = %d\n"), i, data[i]);
//DEBUG_MSG(("[SENSOR] PMS: data[%d] = %d\n"), i, data[i]);
#endif #endif
} }
@ -119,7 +119,7 @@ class PMSX003 {
return true; return true;
} else { } else {
#if SENSOR_DEBUG #if SENSOR_DEBUG
debugSend(("[SENSOR] PMS checksum: %04X != %04X\n"), sum, checksum);
DEBUG_MSG(("[SENSOR] PMS checksum: %04X != %04X\n"), sum, checksum);
#endif #endif
} }
break; break;
@ -282,7 +282,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
readCycle = _readCount % 30; readCycle = _readCount % 30;
if (readCycle == 0) { if (readCycle == 0) {
#if SENSOR_DEBUG #if SENSOR_DEBUG
debugSend("[SENSOR] %s: Wake up: %d\n", pms_specs[_type].name, _readCount);
DEBUG_MSG("[SENSOR] %s: Wake up: %d\n", pms_specs[_type].name, _readCount);
#endif #endif
wakeUp(); wakeUp();
return; return;
@ -321,7 +321,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
if (readCycle == 6) { if (readCycle == 6) {
sleep(); sleep();
#if SENSOR_DEBUG #if SENSOR_DEBUG
debugSend("[SENSOR] %s: Enter sleep mode: %d\n", pms_specs[_type].name, _readCount);
DEBUG_MSG("[SENSOR] %s: Enter sleep mode: %d\n", pms_specs[_type].name, _readCount);
#endif #endif
return; return;
} }


+ 188
- 24
code/espurna/sensors/PZEM004TSensor.h View File

@ -3,6 +3,48 @@
// Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com> // Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Connection Diagram:
// -------------------
//
// Needed when connecting multiple PZEM004T devices on the same UART
// *You must set the PZEM004T device address prior using this configuration*
//
// +---------+
// | ESPurna | +VCC
// | Node | ^
// | G T R | |
// +-+--+--+-+ R (10K)
// | | | |
// | | +-----------------+---------------+---------------+
// | +-----------------+--|------------+--|------------+ |
// +-----------------+--|--|---------+--|--|---------+ | |
// | | | | | | | | |
// | | V | | V | | V
// | | - | | - | | -
// +-+--+--+-+ +-+--+--+-+ +-+--+--+-+
// | G R T | | G R T | | G R T |
// |PZEM-004T| |PZEM-004T| |PZEM-004T|
// | Module | | Module | | Module |
// +---------+ +---------+ +---------+
//
// Where:
// ------
// G = GND
// R = ESPurna UART RX
// T = ESPurna UART TX
// V = Small Signal Schottky Diode, like BAT43,
// Cathode to PZEM TX, Anode to Espurna RX
// R = Resistor to VCC, 10K
//
// More Info:
// ----------
// See ESPurna Wiki - https://github.com/xoseperez/espurna/wiki/Sensor-PZEM004T
//
// Reference:
// ----------
// UART/TTL-Serial network with single master and multiple slaves:
// http://cool-emerald.blogspot.com/2009/10/multidrop-network-for-rs232.html
#if SENSOR_SUPPORT && PZEM004T_SUPPORT #if SENSOR_SUPPORT && PZEM004T_SUPPORT
#pragma once #pragma once
@ -12,6 +54,13 @@
#include <PZEM004T.h> #include <PZEM004T.h>
#define PZ_MAGNITUDE_COUNT 4
#define PZ_MAGNITUDE_CURRENT_INDEX 0
#define PZ_MAGNITUDE_VOLTAGE_INDEX 1
#define PZ_MAGNITUDE_POWER_ACTIVE_INDEX 2
#define PZ_MAGNITUDE_ENERGY_INDEX 3
class PZEM004TSensor : public BaseSensor { class PZEM004TSensor : public BaseSensor {
public: public:
@ -21,9 +70,7 @@ class PZEM004TSensor : public BaseSensor {
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
PZEM004TSensor(): BaseSensor() { PZEM004TSensor(): BaseSensor() {
_count = 4;
_sensor_id = SENSOR_PZEM004T_ID; _sensor_id = SENSOR_PZEM004T_ID;
_ip = IPAddress(192,168,1,1);
} }
~PZEM004TSensor() { ~PZEM004TSensor() {
@ -49,6 +96,53 @@ class PZEM004TSensor : public BaseSensor {
_dirty = true; _dirty = true;
} }
// Set the devices physical addresses managed by this sensor
void setAddresses(const char *addresses) {
char const * sep = " ";
char tokens[strlen(addresses) + 1];
strlcpy(tokens, addresses, sizeof(tokens));
char *address = tokens;
int i = 0;
address = strtok(address, sep);
while (address != 0 && i++ < PZEM004T_MAX_DEVICES) {
IPAddress addr;
reading_t reading;
reading.current = PZEM_ERROR_VALUE;
reading.voltage = PZEM_ERROR_VALUE;
reading.power = PZEM_ERROR_VALUE;
reading.energy = PZEM_ERROR_VALUE;
if (addr.fromString(address)) {
_devices.push_back(addr);
_energy_offsets.push_back(0);
_readings.push_back(reading);
}
address = strtok(0, sep);
}
_count = _devices.size() * PZ_MAGNITUDE_COUNT;
_dirty = true;
}
// Return the number of devices managed by this sensor
unsigned char getAddressesCount() {
return _devices.size();
}
// Get device physical address based on the device index
String getAddress(unsigned char dev) {
return _devices[dev].toString();
}
// Set the device physical address
bool setDeviceAddress(IPAddress *addr) {
while(_busy) { yield(); };
_busy = true;
bool res = _pzem->setAddress(*addr);
_busy = false;
return res;
}
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
unsigned char getRX() { unsigned char getRX() {
@ -61,12 +155,11 @@ class PZEM004TSensor : public BaseSensor {
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
void resetEnergy(double value = 0) {
if (_ready) {
_energy_offset = value - (_pzem->energy(_ip) * 3600);
} else {
_energy_offset = value;
}
// If called with value = -1, the offset will be the last energy reading
// otherwise, it will be the value provided
float resetEnergy(unsigned char dev, float value = -1) {
_energy_offsets[dev] = value != -1 ? value : _readings[dev].energy;
return _energy_offsets[dev];
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -75,7 +168,6 @@ class PZEM004TSensor : public BaseSensor {
// Initialization method, must be idempotent // Initialization method, must be idempotent
void begin() { void begin() {
if (!_dirty) return; if (!_dirty) return;
if (_pzem) delete _pzem; if (_pzem) delete _pzem;
@ -84,16 +176,15 @@ class PZEM004TSensor : public BaseSensor {
} else { } else {
_pzem = new PZEM004T(_pin_rx, _pin_tx); _pzem = new PZEM004T(_pin_rx, _pin_tx);
} }
_pzem->setAddress(_ip);
if(_devices.size() == 1) _pzem->setAddress(_devices[0]);
_ready = true; _ready = true;
_dirty = false; _dirty = false;
} }
// Descriptive name of the sensor // Descriptive name of the sensor
String description() { String description() {
char buffer[28];
char buffer[27];
if (_serial) { if (_serial) {
snprintf(buffer, sizeof(buffer), "PZEM004T @ HwSerial"); snprintf(buffer, sizeof(buffer), "PZEM004T @ HwSerial");
} else { } else {
@ -104,34 +195,99 @@ class PZEM004TSensor : public BaseSensor {
// Descriptive name of the slot # index // Descriptive name of the slot # index
String slot(unsigned char index) { String slot(unsigned char index) {
return description();
int dev = index / PZ_MAGNITUDE_COUNT;
char buffer[25];
snprintf(buffer, sizeof(buffer), "(%u/%s)", dev, getAddress(dev).c_str());
return description() + String(buffer);
}; };
// Address of the sensor (it could be the GPIO or I2C address) // Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) { String address(unsigned char index) {
return _ip.toString();
int dev = index / PZ_MAGNITUDE_COUNT;
return _devices[dev].toString();
} }
// Type for slot # index // Type for slot # index
unsigned char type(unsigned char index) { unsigned char type(unsigned char index) {
if (index == 0) return MAGNITUDE_CURRENT;
if (index == 1) return MAGNITUDE_VOLTAGE;
if (index == 2) return MAGNITUDE_POWER_ACTIVE;
if (index == 3) return MAGNITUDE_ENERGY;
int dev = index / PZ_MAGNITUDE_COUNT;
index = index - (dev * PZ_MAGNITUDE_COUNT);
if (index == PZ_MAGNITUDE_CURRENT_INDEX) return MAGNITUDE_CURRENT;
if (index == PZ_MAGNITUDE_VOLTAGE_INDEX) return MAGNITUDE_VOLTAGE;
if (index == PZ_MAGNITUDE_POWER_ACTIVE_INDEX) return MAGNITUDE_POWER_ACTIVE;
if (index == PZ_MAGNITUDE_ENERGY_INDEX) return MAGNITUDE_ENERGY;
return MAGNITUDE_NONE; return MAGNITUDE_NONE;
} }
// Current value for slot # index // Current value for slot # index
double value(unsigned char index) { double value(unsigned char index) {
int dev = index / PZ_MAGNITUDE_COUNT;
index = index - (dev * PZ_MAGNITUDE_COUNT);
double response = 0; double response = 0;
if (index == 0) response = _pzem->current(_ip);
if (index == 1) response = _pzem->voltage(_ip);
if (index == 2) response = _pzem->power(_ip);
if (index == 3) response = _energy_offset + (_pzem->energy(_ip) * 3600);
if (index == PZ_MAGNITUDE_CURRENT_INDEX) response = _readings[dev].current;
if (index == PZ_MAGNITUDE_VOLTAGE_INDEX) response = _readings[dev].voltage;
if (index == PZ_MAGNITUDE_POWER_ACTIVE_INDEX) response = _readings[dev].power;
if (index == PZ_MAGNITUDE_ENERGY_INDEX) response = (_readings[dev].energy * 3600) - _energy_offsets[dev];
if (response < 0) response = 0; if (response < 0) response = 0;
return response; return response;
} }
// Post-read hook (usually to reset things)
void post() {
_error = SENSOR_ERROR_OK;
}
// Loop-like method, call it in your main loop
void tick() {
static unsigned char dev = 0;
static unsigned char magnitude = 0;
static unsigned long last_millis = 0;
if (_busy || millis() - last_millis < PZEM004T_READ_INTERVAL) return;
_busy = true;
// Clear buffer in case of late response(Timeout)
while(Serial.available() > 0) Serial.read();
float read;
float* readings_p;
switch(magnitude) {
case PZ_MAGNITUDE_CURRENT_INDEX:
read = _pzem->current(_devices[dev]);
readings_p = &_readings[dev].current;
break;
case PZ_MAGNITUDE_VOLTAGE_INDEX:
read = _pzem->voltage(_devices[dev]);
readings_p = &_readings[dev].voltage;
break;
case PZ_MAGNITUDE_POWER_ACTIVE_INDEX:
read = _pzem->power(_devices[dev]);
readings_p = &_readings[dev].power;
break;
case PZ_MAGNITUDE_ENERGY_INDEX:
read = _pzem->energy(_devices[dev]);
readings_p = &_readings[dev].energy;
break;
default:
_busy = false;
return;
}
if(read == PZEM_ERROR_VALUE) {
_error = SENSOR_ERROR_TIMEOUT;
} else {
*readings_p = read;
}
if(++dev == _devices.size()) {
dev = 0;
last_millis = millis();
if(++magnitude == PZ_MAGNITUDE_COUNT) {
magnitude = 0;
}
}
_busy = false;
}
protected: protected:
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -140,10 +296,18 @@ class PZEM004TSensor : public BaseSensor {
unsigned int _pin_rx = PZEM004T_RX_PIN; unsigned int _pin_rx = PZEM004T_RX_PIN;
unsigned int _pin_tx = PZEM004T_TX_PIN; unsigned int _pin_tx = PZEM004T_TX_PIN;
IPAddress _ip;
bool _busy = false;
typedef struct {
float voltage;
float current;
float power;
float energy;
} reading_t;
std::vector<reading_t> _readings;
std::vector<float> _energy_offsets;
std::vector<IPAddress> _devices;
HardwareSerial * _serial = NULL; HardwareSerial * _serial = NULL;
PZEM004T * _pzem = NULL; PZEM004T * _pzem = NULL;
double _energy_offset = 0;
}; };


+ 119
- 0
code/espurna/sensors/VL53L1XSensor.h View File

@ -0,0 +1,119 @@
// -----------------------------------------------------------------------------
// VL53L1X Sensor over I2C
// Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
// -----------------------------------------------------------------------------
#if SENSOR_SUPPORT && VL53L1X_SUPPORT
#pragma once
#undef I2C_SUPPORT
#define I2C_SUPPORT 1 // Explicitly request I2C support.
#include "Arduino.h"
#include "I2CSensor.h"
#include "VL53L1X.h"
class VL53L1XSensor : public I2CSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
VL53L1XSensor(): I2CSensor() {
_count = 1;
_sensor_id = SENSOR_VL53L1X_ID;
_vl53l1x = new VL53L1X();
}
~VL53L1XSensor() {
delete _vl53l1x;
}
// ---------------------------------------------------------------------
void setDistanceMode(VL53L1X::DistanceMode mode) {
_vl53l1x->setDistanceMode(mode);
}
void setMeasurementTimingBudget(uint32_t budget_us) {
_vl53l1x->setMeasurementTimingBudget(budget_us);
}
void setInterMeasurementPeriod(unsigned int period) {
if (_inter_measurement_period == period) return;
_inter_measurement_period = period;
_dirty = true;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
void begin() {
if (!_dirty) {
return;
}
// I2C auto-discover
unsigned char addresses[] = {0x29};
_address = _begin_i2c(_address, sizeof(addresses), addresses);
if (_address == 0) return;
_vl53l1x->setAddress(_address);
if (!_vl53l1x->init()) {
return;
};
_vl53l1x->startContinuous(_inter_measurement_period);
_ready = true;
_dirty = false;
}
// Descriptive name of the sensor
String description() {
char buffer[21];
snprintf(buffer, sizeof(buffer), "VL53L1X @ I2C (0x%02X)", _address);
return String(buffer);
}
// Descriptive name of the slot # index
String slot(unsigned char index) {
return description();
};
// Type for slot # index
unsigned char type(unsigned char index) {
if (index == 0) return MAGNITUDE_DISTANCE;
return MAGNITUDE_NONE;
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
if (!_vl53l1x->dataReady()) {
return;
}
_distance = (double) _vl53l1x->read(false) / 1000.00;
}
// Current value for slot # index
double value(unsigned char index) {
if (index != 0) return 0;
return _distance;
}
protected:
VL53L1X * _vl53l1x = NULL;
unsigned int _inter_measurement_period;
double _distance = 0;
};
#endif // SENSOR_SUPPORT && VL53L1X_SUPPORT

+ 4
- 11
code/espurna/settings.ino View File

@ -22,8 +22,6 @@ EmbedisWrap embedis(_serial, TERMINAL_BUFFER_SIZE);
#endif // SERIAL_RX_ENABLED #endif // SERIAL_RX_ENABLED
#endif // TERMINAL_SUPPORT #endif // TERMINAL_SUPPORT
bool _settings_save = false;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Reverse engineering EEPROM storage format // Reverse engineering EEPROM storage format
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -189,6 +187,7 @@ void _settingsInitCommands() {
settingsRegisterCommand(F("ERASE.CONFIG"), [](Embedis* e) { settingsRegisterCommand(F("ERASE.CONFIG"), [](Embedis* e) {
DEBUG_MSG_P(PSTR("+OK\n")); DEBUG_MSG_P(PSTR("+OK\n"));
resetReason(CUSTOM_RESET_TERMINAL); resetReason(CUSTOM_RESET_TERMINAL);
_eepromCommit();
ESP.eraseConfig(); ESP.eraseConfig();
*((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494 *((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494
}); });
@ -310,7 +309,7 @@ void _settingsInitCommands() {
#if not SETTINGS_AUTOSAVE #if not SETTINGS_AUTOSAVE
settingsRegisterCommand(F("SAVE"), [](Embedis* e) { settingsRegisterCommand(F("SAVE"), [](Embedis* e) {
_settings_save = true;
eepromCommit();
DEBUG_MSG_P(PSTR("\n+OK\n")); DEBUG_MSG_P(PSTR("\n+OK\n"));
}); });
#endif #endif
@ -367,7 +366,7 @@ bool hasSetting(const String& key, unsigned int index) {
void saveSettings() { void saveSettings() {
#if not SETTINGS_AUTOSAVE #if not SETTINGS_AUTOSAVE
_settings_save = true;
eepromCommit();
#endif #endif
} }
@ -464,7 +463,7 @@ void settingsSetup() {
[](size_t pos) -> char { return EEPROMr.read(pos); }, [](size_t pos) -> char { return EEPROMr.read(pos); },
[](size_t pos, char value) { EEPROMr.write(pos, value); }, [](size_t pos, char value) { EEPROMr.write(pos, value); },
#if SETTINGS_AUTOSAVE #if SETTINGS_AUTOSAVE
[]() { _settings_save = true; }
[]() { eepromCommit(); }
#else #else
[]() {} []() {}
#endif #endif
@ -485,12 +484,6 @@ void settingsSetup() {
void settingsLoop() { void settingsLoop() {
if (_settings_save) {
EEPROMr.commit();
_settings_save = false;
}
#if TERMINAL_SUPPORT #if TERMINAL_SUPPORT
#if DEBUG_SERIAL_SUPPORT #if DEBUG_SERIAL_SUPPORT


+ 9
- 1
code/espurna/system.ino View File

@ -42,7 +42,7 @@ void systemCheck(bool stable) {
} }
} }
EEPROMr.write(EEPROM_CRASH_COUNTER, value); EEPROMr.write(EEPROM_CRASH_COUNTER, value);
EEPROMr.commit();
eepromCommit();
} }
bool systemCheck() { bool systemCheck() {
@ -77,6 +77,14 @@ unsigned long systemLoadAverage() {
void systemLoop() { void systemLoop() {
// -------------------------------------------------------------------------
// User requested reset
// -------------------------------------------------------------------------
if (checkNeedsReset()) {
reset();
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Check system stability // Check system stability
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------


+ 13
- 5
code/espurna/utils.ino View File

@ -9,6 +9,8 @@ Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
#include <Ticker.h> #include <Ticker.h>
Ticker _defer_reset; Ticker _defer_reset;
uint8_t _reset_reason = 0;
String getIdentifier() { String getIdentifier() {
char buffer[20]; char buffer[20];
snprintf_P(buffer, sizeof(buffer), PSTR("%s-%06X"), APP_NAME, ESP.getChipId()); snprintf_P(buffer, sizeof(buffer), PSTR("%s-%06X"), APP_NAME, ESP.getChipId());
@ -182,6 +184,9 @@ void heartbeat() {
#if (HEARTBEAT_REPORT_HOSTNAME) #if (HEARTBEAT_REPORT_HOSTNAME)
mqttSend(MQTT_TOPIC_HOSTNAME, getSetting("hostname").c_str()); mqttSend(MQTT_TOPIC_HOSTNAME, getSetting("hostname").c_str());
#endif #endif
#if (HEARTBEAT_REPORT_SSID)
mqttSend(MQTT_TOPIC_SSID, WiFi.SSID().c_str());
#endif
#if (HEARTBEAT_REPORT_IP) #if (HEARTBEAT_REPORT_IP)
mqttSend(MQTT_TOPIC_IP, getIP().c_str()); mqttSend(MQTT_TOPIC_IP, getIP().c_str());
#endif #endif
@ -347,8 +352,7 @@ void info() {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
DEBUG_MSG_P(PSTR("[MAIN] EEPROM sectors: %s\n"), (char *) eepromSectors().c_str());
DEBUG_MSG_P(PSTR("[MAIN] EEPROM current: %lu\n"), eepromCurrent());
eepromSectorsDebug();
DEBUG_MSG_P(PSTR("\n")); DEBUG_MSG_P(PSTR("\n"));
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -464,8 +468,9 @@ unsigned char resetReason() {
} }
void resetReason(unsigned char reason) { void resetReason(unsigned char reason) {
_reset_reason = reason;
EEPROMr.write(EEPROM_CUSTOM_RESET, reason); EEPROMr.write(EEPROM_CUSTOM_RESET, reason);
EEPROMr.commit();
eepromCommit();
} }
void reset() { void reset() {
@ -473,8 +478,11 @@ void reset() {
} }
void deferredReset(unsigned long delay, unsigned char reason) { void deferredReset(unsigned long delay, unsigned char reason) {
resetReason(reason);
_defer_reset.once_ms(delay, reset);
_defer_reset.once_ms(delay, resetReason, reason);
}
bool checkNeedsReset() {
return _reset_reason > 0;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 1
- 1
code/html/custom.js View File

@ -47,7 +47,7 @@ function sensorName(id) {
"Events", "PMSX003", "BMX280", "MHZ19", "SI7021", "Events", "PMSX003", "BMX280", "MHZ19", "SI7021",
"SHT3X I2C", "BH1750", "PZEM004T", "AM2320 I2C", "GUVAS12SD", "SHT3X I2C", "BH1750", "PZEM004T", "AM2320 I2C", "GUVAS12SD",
"TMP3X", "Sonar", "SenseAir", "GeigerTicks", "GeigerCPM", "TMP3X", "Sonar", "SenseAir", "GeigerTicks", "GeigerCPM",
"NTC", "SDS011", "MICS2710", "MICS5525", "VEML6075"
"NTC", "SDS011", "MICS2710", "MICS5525", "VL53L1X", "VEML6075"
]; ];
if (1 <= id && id <= names.length) { if (1 <= id && id <= names.length) {
return names[id - 1]; return names[id - 1];


+ 76
- 0
code/platformio.ini View File

@ -98,6 +98,7 @@ lib_deps =
https://github.com/xoseperez/Time https://github.com/xoseperez/Time
NewPing NewPing
https://github.com/sparkfun/SparkFun_VEML6075_Arduino_Library#V_1.0.3 https://github.com/sparkfun/SparkFun_VEML6075_Arduino_Library#V_1.0.3
https://github.com/pololu/vl53l1x-arduino#1.0.1
lib_ignore = lib_ignore =
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -2011,6 +2012,30 @@ upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags} upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts} extra_scripts = ${common.extra_scripts}
[env:maxcio-wde004]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DMAXCIO_WDE004
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:maxcio-wde004-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DMAXCIO_WDE004
upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:yidian-xsssa05] [env:yidian-xsssa05]
platform = ${common.platform} platform = ${common.platform}
framework = ${common.framework} framework = ${common.framework}
@ -2035,6 +2060,31 @@ upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags} upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts} extra_scripts = ${common.extra_scripts}
[env:tonbux-xsssa01]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_4m1m} -DTONBUX_XSSSA01
upload_speed = ${common.upload_speed_fast}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:tonbux-xsssa01-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_4m1m} -DTONBUX_XSSSA01
upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:tonbux-xsssa06] [env:tonbux-xsssa06]
platform = ${common.platform} platform = ${common.platform}
framework = ${common.framework} framework = ${common.framework}
@ -2503,6 +2553,32 @@ upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags} upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts} extra_scripts = ${common.extra_scripts}
[env:blitzwolf-bwshp2-v23]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DBLITZWOLF_BWSHP2_V23
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:blitzwolf-bwshp2-v23-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DBLITZWOLF_BWSHP2_V23
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:homecube-16a] [env:homecube-16a]
platform = ${common.platform} platform = ${common.platform}
framework = ${common.framework} framework = ${common.framework}


BIN
images/devices/tonbux-xs-ssa01.jpg View File

Before After
Width: 400  |  Height: 400  |  Size: 13 KiB

Loading…
Cancel
Save