Browse Source

:q:Merge branch 'dev' into sensors

alexa
Xose Pérez 6 years ago
parent
commit
7886f6eddc
34 changed files with 1053 additions and 137 deletions
  1. +1
    -1
      .travis.yml
  2. +4
    -3
      README.md
  3. +8
    -1
      code/build.sh
  4. +7
    -6
      code/debug.sh
  5. +1
    -0
      code/espurna/api.ino
  6. +3
    -0
      code/espurna/config/arduino.h
  7. +12
    -0
      code/espurna/config/general.h
  8. +135
    -0
      code/espurna/config/hardware.h
  9. +16
    -5
      code/espurna/config/progmem.h
  10. +3
    -0
      code/espurna/config/prototypes.h
  11. +81
    -2
      code/espurna/config/sensors.h
  12. +16
    -11
      code/espurna/config/types.h
  13. +18
    -2
      code/espurna/debug.ino
  14. +43
    -0
      code/espurna/eeprom.ino
  15. +11
    -24
      code/espurna/ir.ino
  16. +10
    -0
      code/espurna/migrate.ino
  17. +1
    -1
      code/espurna/mqtt.ino
  18. +1
    -1
      code/espurna/ntp.ino
  19. +2
    -2
      code/espurna/relay.ino
  20. +9
    -3
      code/espurna/rfbridge.ino
  21. +103
    -1
      code/espurna/sensor.ino
  22. +1
    -1
      code/espurna/sensors/GUVAS12SDSensor.h
  23. +21
    -18
      code/espurna/sensors/HLW8012Sensor.h
  24. +6
    -6
      code/espurna/sensors/PMSX003Sensor.h
  25. +188
    -24
      code/espurna/sensors/PZEM004TSensor.h
  26. +96
    -0
      code/espurna/sensors/VEML6075Sensor.h
  27. +119
    -0
      code/espurna/sensors/VL53L1XSensor.h
  28. +4
    -11
      code/espurna/settings.ino
  29. +9
    -1
      code/espurna/system.ino
  30. +13
    -5
      code/espurna/utils.ino
  31. +2
    -2
      code/html/custom.js
  32. +6
    -6
      code/ota.py
  33. +103
    -0
      code/platformio.ini
  34. 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


+ 4
- 3
README.md View File

@ -5,9 +5,10 @@ It uses the Arduino Core for ESP8266 framework and a number of 3rd party librari
[![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-sensors-orange.svg)](https://github.com/xoseperez/espurna/tree/sensors/) [![branch](https://img.shields.io/badge/branch-sensors-orange.svg)](https://github.com/xoseperez/espurna/tree/sensors/)
[![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=sensors)](https://travis-ci.org/xoseperez/espurna) [![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=sensors)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard) [![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard)
[![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
[![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)|


+ 8
- 1
code/build.sh View File

@ -9,6 +9,13 @@ is_git() {
return 0 return 0
} }
stat_bytes() {
case "$(uname -s)" in
Darwin) stat -f %z "$1";;
*) stat -c %s "$1";;
esac
}
# Script settings # Script settings
destination=../firmware destination=../firmware
@ -104,7 +111,7 @@ build_environments() {
for environment in $environments; do for environment in $environments; do
echo -n "* espurna-$version-$environment.bin --- " echo -n "* espurna-$version-$environment.bin --- "
platformio run --silent --environment $environment || exit 1 platformio run --silent --environment $environment || exit 1
stat -c %s .pioenvs/$environment/firmware.bin
stat_bytes .pioenvs/$environment/firmware.bin
[[ "${TRAVIS_BUILD_STAGE_NAME}" = "Test" ]] || \ [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Test" ]] || \
mv .pioenvs/$environment/firmware.bin $destination/espurna-$version/espurna-$version-$environment.bin mv .pioenvs/$environment/firmware.bin $destination/espurna-$version/espurna-$version-$environment.bin
done done


+ 7
- 6
code/debug.sh View File

@ -19,7 +19,7 @@ rm -rf $FILE
function help { function help {
echo echo
echo "Syntax: $0 [-e <environment>] [-d <dumpfile>]"
echo "Syntax: $0 [-e <environment>] [-f <elf_file>] [-d <dumpfile>]"
echo echo
} }
@ -29,6 +29,10 @@ while [[ $# -gt 1 ]]; do
key="$1" key="$1"
case $key in case $key in
-f)
ELF="$2"
shift
;;
-e) -e)
ENVIRONMENT="$2" ENVIRONMENT="$2"
shift shift
@ -44,12 +48,9 @@ while [[ $# -gt 1 ]]; do
done done
# check environment folder # check environment folder
if [ $ENVIRONMENT == "" ]; then
echo "No environment defined"
help
exit 1
if [ ! -f $ELF ]; then
ELF=.pioenvs/$ENVIRONMENT/firmware.elf
fi fi
ELF=.pioenvs/$ENVIRONMENT/firmware.elf
if [ ! -f $ELF ]; then if [ ! -f $ELF ]; then
echo "Could not find ELF file for the selected environment: $ELF" echo "Could not find ELF file for the selected environment: $ELF"
exit 2 exit 2


+ 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);


+ 3
- 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
@ -100,6 +101,7 @@
//#define PHYX_ESP12_RGB //#define PHYX_ESP12_RGB
//#define IWOOLE_LED_TABLE_LAMP //#define IWOOLE_LED_TABLE_LAMP
//#define EXS_WIFI_RELAY_V50 //#define EXS_WIFI_RELAY_V50
//#define TECKIN_SP22_V14
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Features (values below are non-default values) // Features (values below are non-default values)
@ -173,3 +175,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


+ 135
- 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,94 @@
#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
// -----------------------------------------------------------------------------
// Teckin SP22 v1.4 - v1.6
// -----------------------------------------------------------------------------
#elif defined(TECKIN_SP22_V14)
// Info
#define MANUFACTURER "TECKIN"
#define DEVICE "SP22_V14"
// 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 3
#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 20730
#define HLW8012_VOLTAGE_RATIO 264935
#define HLW8012_POWER_RATIO 2533110
#define HLW8012_INTERRUPT_ON FALLING
//#define HLW8012_WAIT_FOR_WIFI 1
//#define ALEXA_SUPPORT 0
//#define DOMOTICZ_SUPPORT 0
//#define HOMEASSISTANT_SUPPORT 0
//#define THINGSPEAK_SUPPORT 0
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// 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 +3030,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


+ 16
- 5
code/espurna/config/progmem.h View File

@ -226,6 +226,12 @@ PROGMEM const char espurna_sensors[] =
#if V9261F_SUPPORT #if V9261F_SUPPORT
"V9261F " "V9261F "
#endif #endif
#if VEML6075_SUPPORT
"VEML6075 "
#endif
#if VL53L1X_SUPPORT
"VL53L1X "
#endif
""; "";
@ -235,7 +241,9 @@ PROGMEM const unsigned char magnitude_decimals[] = {
3, 0, 0, 0, 0, 0, 0, 0, // Power decimals 3, 0, 0, 0, 0, 0, 0, 0, // Power decimals
0, 0, 0, // analog, digital, event 0, 0, 0, // analog, digital, event
0, 0, 0, // PM 0, 0, 0, // PM
0, 0, 3, 3, 0,
0, 0,
0, 0, 3, // UVA, UVB, UVI
3, 0,
4, 4, // Geiger Counter decimals 4, 4, // Geiger Counter decimals
0, 0,
0, 0, 0 // NO2, CO, Ohms 0, 0, 0 // NO2, CO, Ohms
@ -261,7 +269,9 @@ PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5";
PROGMEM const char magnitude_pm10_topic[] = "pm10"; PROGMEM const char magnitude_pm10_topic[] = "pm10";
PROGMEM const char magnitude_co2_topic[] = "co2"; PROGMEM const char magnitude_co2_topic[] = "co2";
PROGMEM const char magnitude_lux_topic[] = "lux"; PROGMEM const char magnitude_lux_topic[] = "lux";
PROGMEM const char magnitude_uv_topic[] = "uv";
PROGMEM const char magnitude_uva_topic[] = "uva";
PROGMEM const char magnitude_uvb_topic[] = "uvb";
PROGMEM const char magnitude_uvi_topic[] = "uvi";
PROGMEM const char magnitude_distance_topic[] = "distance"; PROGMEM const char magnitude_distance_topic[] = "distance";
PROGMEM const char magnitude_hcho_topic[] = "hcho"; PROGMEM const char magnitude_hcho_topic[] = "hcho";
PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute] PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute]
@ -278,7 +288,8 @@ PROGMEM const char* const magnitude_topics[] = {
magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic, magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic, magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic,
magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic, magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic,
magnitude_co2_topic, magnitude_lux_topic, magnitude_uv_topic,
magnitude_co2_topic, magnitude_lux_topic,
magnitude_uva_topic, magnitude_uvb_topic, magnitude_uvi_topic,
magnitude_distance_topic, magnitude_hcho_topic, magnitude_distance_topic, magnitude_hcho_topic,
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic, magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic,
magnitude_count_topic, magnitude_count_topic,
@ -299,7 +310,6 @@ PROGMEM const char magnitude_kwh[] = "kWh";
PROGMEM const char magnitude_ugm3[] = "µg/m³"; PROGMEM const char magnitude_ugm3[] = "µg/m³";
PROGMEM const char magnitude_ppm[] = "ppm"; PROGMEM const char magnitude_ppm[] = "ppm";
PROGMEM const char magnitude_lux[] = "lux"; PROGMEM const char magnitude_lux[] = "lux";
PROGMEM const char magnitude_uv[] = "uv";
PROGMEM const char magnitude_distance[] = "m"; PROGMEM const char magnitude_distance[] = "m";
PROGMEM const char magnitude_mgm3[] = "mg/m³"; PROGMEM const char magnitude_mgm3[] = "mg/m³";
PROGMEM const char magnitude_geiger_cpm[] = "cpm"; // Counts per Minute: Unit of local dose rate (Geiger counting) PROGMEM const char magnitude_geiger_cpm[] = "cpm"; // Counts per Minute: Unit of local dose rate (Geiger counting)
@ -314,7 +324,8 @@ PROGMEM const char* const magnitude_units[] = {
magnitude_percentage, magnitude_joules, magnitude_joules, magnitude_percentage, magnitude_joules, magnitude_joules,
magnitude_empty, magnitude_empty, magnitude_empty, magnitude_empty, magnitude_empty, magnitude_empty,
magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3,
magnitude_ppm, magnitude_lux, magnitude_uv,
magnitude_ppm, magnitude_lux,
magnitude_empty, magnitude_empty, magnitude_empty,
magnitude_distance, magnitude_mgm3, magnitude_distance, magnitude_mgm3,
magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units
magnitude_empty, // magnitude_empty, //


+ 3
- 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
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -193,3 +195,4 @@ void webRequestRegister(web_request_callback_f callback);
#include "JustWifi.h" #include "JustWifi.h"
typedef std::function<void(justwifi_messages_t code, char * parameter)> wifi_callback_f; typedef std::function<void(justwifi_messages_t code, char * parameter)> wifi_callback_f;
void wifiRegister(wifi_callback_f callback); void wifiRegister(wifi_callback_f callback);
bool wifiConnected();

+ 81
- 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
@ -407,6 +440,11 @@
#define HLW8012_USE_INTERRUPTS 1 // Use interrupts to trap HLW8012 signals #define HLW8012_USE_INTERRUPTS 1 // Use interrupts to trap HLW8012 signals
#endif #endif
#ifndef HLW8012_WAIT_FOR_WIFI
#define HLW8012_WAIT_FOR_WIFI 0 // Weather to enable interrupts only after
// wifi connection has been stablished
#endif
#ifndef HLW8012_INTERRUPT_ON #ifndef HLW8012_INTERRUPT_ON
#define HLW8012_INTERRUPT_ON CHANGE // When to trigger the interrupt #define HLW8012_INTERRUPT_ON CHANGE // When to trigger the interrupt
// Use CHANGE for HLW8012 // Use CHANGE for HLW8012
@ -588,6 +626,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
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// SDS011 particulates sensor // SDS011 particulates sensor
// Enable support by passing SDS011_SUPPORT=1 build flag // Enable support by passing SDS011_SUPPORT=1 build flag
@ -712,6 +762,25 @@
#define V9261F_POWER_FACTOR 153699.0 #define V9261F_POWER_FACTOR 153699.0
#define V9261F_RPOWER_FACTOR V9261F_CURRENT_FACTOR #define V9261F_RPOWER_FACTOR V9261F_CURRENT_FACTOR
//------------------------------------------------------------------------------
// VEML6075 based power sensor
// Enable support by passing VEML6075_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef VEML6075_SUPPORT
#define VEML6075_SUPPORT 0
#endif
#ifndef VEML6075_INTEGRATION_TIME
#define VEML6075_INTEGRATION_TIME VEML6075::IT_100MS // The time, in milliseconds, allocated for a single
#endif // measurement. A longer timing budget allows for more
// accurate results at the cost of power.
#ifndef VEML6075_DYNAMIC_MODE
#define VEML6075_DYNAMIC_MODE VEML6075::DYNAMIC_NORMAL // The dynamic mode can either be normal or high. In high
#endif // dynamic mode, the resolution increases by about two
// times.
// ============================================================================= // =============================================================================
// Sensor helpers configuration - can't move to dependencies.h // Sensor helpers configuration - can't move to dependencies.h
// ============================================================================= // =============================================================================
@ -747,7 +816,9 @@
SI7021_SUPPORT || \ SI7021_SUPPORT || \
SONAR_SUPPORT || \ SONAR_SUPPORT || \
TMP3X_SUPPORT || \ TMP3X_SUPPORT || \
V9261F_SUPPORT \
V9261F_SUPPORT || \
VEML6075_SUPPORT || \
VL53L1X_SUPPORT \
) )
#endif #endif
@ -909,4 +980,12 @@
#include "../sensors/V9261FSensor.h" #include "../sensors/V9261FSensor.h"
#endif #endif
#if VEML6075_SUPPORT
#include "../sensors/VEML6075Sensor.h"
#endif
#if VL53L1X_SUPPORT
#include "../sensors/VL53L1XSensor.h"
#endif
#endif // SENSOR_SUPPORT #endif // SENSOR_SUPPORT

+ 16
- 11
code/espurna/config/types.h View File

@ -250,6 +250,7 @@
// These should remain over time, do not modify them, only add new ones at the end // These should remain over time, do not modify them, only add new ones at the end
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
<<<<<<< HEAD
#define SENSOR_DHTXX_ID 01 #define SENSOR_DHTXX_ID 01
#define SENSOR_DALLAS_ID 02 #define SENSOR_DALLAS_ID 02
#define SENSOR_EMON_ANALOG_ID 03 #define SENSOR_EMON_ANALOG_ID 03
@ -280,6 +281,8 @@
#define SENSOR_MICS2710_ID 28 #define SENSOR_MICS2710_ID 28
#define SENSOR_MICS5525_ID 29 #define SENSOR_MICS5525_ID 29
#define SENSOR_PULSEMETER_ID 30 #define SENSOR_PULSEMETER_ID 30
#define SENSOR_VEML6075_ID 31
#define SENSOR_VL53L1X_ID 32
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Magnitudes // Magnitudes
@ -305,14 +308,16 @@
#define MAGNITUDE_PM10 17 #define MAGNITUDE_PM10 17
#define MAGNITUDE_CO2 18 #define MAGNITUDE_CO2 18
#define MAGNITUDE_LUX 19 #define MAGNITUDE_LUX 19
#define MAGNITUDE_UV 20
#define MAGNITUDE_DISTANCE 21
#define MAGNITUDE_HCHO 22
#define MAGNITUDE_GEIGER_CPM 23
#define MAGNITUDE_GEIGER_SIEVERT 24
#define MAGNITUDE_COUNT 25
#define MAGNITUDE_NO2 26
#define MAGNITUDE_CO 27
#define MAGNITUDE_RESISTANCE 28
#define MAGNITUDE_MAX 29
#define MAGNITUDE_UVA 20
#define MAGNITUDE_UVB 21
#define MAGNITUDE_UVI 22
#define MAGNITUDE_DISTANCE 23
#define MAGNITUDE_HCHO 24
#define MAGNITUDE_GEIGER_CPM 25
#define MAGNITUDE_GEIGER_SIEVERT 26
#define MAGNITUDE_COUNT 27
#define MAGNITUDE_NO2 28
#define MAGNITUDE_CO 29
#define MAGNITUDE_RESISTANCE 30
#define MAGNITUDE_MAX 31

+ 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++;


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

@ -128,7 +128,7 @@ void _ntpBackwards() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool ntpSynced() { bool ntpSynced() {
return (year() > 2017);
return (NTP.getLastNTPSync() > 0);
} }
String ntpDateTime(time_t t) { String ntpDateTime(time_t t) {


+ 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;


+ 9
- 3
code/espurna/rfbridge.ino View File

@ -19,6 +19,8 @@ Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
// DEFINITIONS // DEFINITIONS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// EFM8 Protocol
#define RF_MESSAGE_SIZE 9 #define RF_MESSAGE_SIZE 9
#define RF_MAX_MESSAGE_SIZE (112+4) #define RF_MAX_MESSAGE_SIZE (112+4)
#define RF_CODE_START 0xAA #define RF_CODE_START 0xAA
@ -37,6 +39,10 @@ Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
#define RF_CODE_RFOUT_BUCKET 0xB0 #define RF_CODE_RFOUT_BUCKET 0xB0
#define RF_CODE_STOP 0x55 #define RF_CODE_STOP 0x55
// Settings
#define RF_MAX_KEY_LENGTH (9)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GLOBALS TO THE MODULE // GLOBALS TO THE MODULE
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -523,13 +529,13 @@ void _rfbMqttCallback(unsigned int type, const char * topic, const char * payloa
void rfbStore(unsigned char id, bool status, const char * code) { void rfbStore(unsigned char id, bool status, const char * code) {
DEBUG_MSG_P(PSTR("[RFBRIDGE] Storing %d-%s => '%s'\n"), id, status ? "ON" : "OFF", code); DEBUG_MSG_P(PSTR("[RFBRIDGE] Storing %d-%s => '%s'\n"), id, status ? "ON" : "OFF", code);
char key[8] = {0};
char key[RF_MAX_KEY_LENGTH] = {0};
snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id); snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id);
setSetting(key, code); setSetting(key, code);
} }
String rfbRetrieve(unsigned char id, bool status) { String rfbRetrieve(unsigned char id, bool status) {
char key[8] = {0};
char key[RF_MAX_KEY_LENGTH] = {0};
snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id); snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id);
return getSetting(key); return getSetting(key);
} }
@ -586,7 +592,7 @@ void rfbLearn(unsigned char id, bool status) {
void rfbForget(unsigned char id, bool status) { void rfbForget(unsigned char id, bool status) {
char key[8] = {0};
char key[RF_MAX_KEY_LENGTH] = {0};
snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id); snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id);
delSetting(key); delSetting(key);


+ 103
- 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();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -278,6 +282,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
@ -590,13 +651,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
@ -652,6 +720,24 @@ void _sensorLoad() {
} }
#endif #endif
#if VEML6075_SUPPORT
{
VEML6075Sensor * sensor = new VEML6075Sensor();
sensor->setIntegrationTime(VEML6075_INTEGRATION_TIME);
sensor->setDynamicMode(VEML6075_DYNAMIC_MODE);
_sensors.push_back(sensor);
}
#endif
#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
} }
void _sensorCallback(unsigned char i, unsigned char type, double value) { void _sensorCallback(unsigned char i, unsigned char type, double value) {
@ -1003,6 +1089,22 @@ void _sensorConfigure() {
} }
#endif // PULSEMETER_SUPPORT #endif // PULSEMETER_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


+ 1
- 1
code/espurna/sensors/GUVAS12SDSensor.h View File

@ -104,7 +104,7 @@ class GUVAS12SDSensor : public BaseSensor {
// 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_UV;
if (index == 0) return MAGNITUDE_UVI;
return MAGNITUDE_NONE; return MAGNITUDE_NONE;
} }


+ 21
- 18
code/espurna/sensors/HLW8012Sensor.h View File

@ -9,8 +9,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "BaseSensor.h" #include "BaseSensor.h"
#include <ESP8266WiFi.h>
#include <HLW8012.h> #include <HLW8012.h>
class HLW8012Sensor : public BaseSensor { class HLW8012Sensor : public BaseSensor {
@ -148,14 +146,10 @@ class HLW8012Sensor : public BaseSensor {
// Handle interrupts // Handle interrupts
#if HLW8012_USE_INTERRUPTS #if HLW8012_USE_INTERRUPTS
_enableInterrupts(true);
#else
_onconnect_handler = WiFi.onStationModeGotIP([this](WiFiEventStationModeGotIP ipInfo) {
_enableInterrupts(true);
});
_ondisconnect_handler = WiFi.onStationModeDisconnected([this](WiFiEventStationModeDisconnected ipInfo) {
#if HLW8012_WAIT_FOR_WIFI == 0
_enableInterrupts(false); _enableInterrupts(false);
});
_enableInterrupts(true);
#endif
#endif #endif
_ready = true; _ready = true;
@ -205,6 +199,15 @@ class HLW8012Sensor : public BaseSensor {
return 0; return 0;
} }
// Pre-read hook (usually to populate registers with up-to-date data)
#if HLW8012_USE_INTERRUPTS
#if HLW8012_WAIT_FOR_WIFI
void pre() {
_enableInterrupts(wifiConnected());
}
#endif
#endif
// Toggle between current and voltage monitoring // Toggle between current and voltage monitoring
#if HLW8012_USE_INTERRUPTS == 0 #if HLW8012_USE_INTERRUPTS == 0
// Post-read hook (usually to reset things) // Post-read hook (usually to reset things)
@ -247,10 +250,15 @@ class HLW8012Sensor : public BaseSensor {
} else { } else {
_detach(_cf);
_detach(_cf1);
_interrupt_cf = GPIO_NONE;
_interrupt_cf1 = GPIO_NONE;
if (GPIO_NONE != _interrupt_cf) {
_detach(_interrupt_cf);
_interrupt_cf = GPIO_NONE;
}
if (GPIO_NONE != _interrupt_cf1) {
_detach(_interrupt_cf1);
_interrupt_cf1 = GPIO_NONE;
}
} }
@ -266,11 +274,6 @@ class HLW8012Sensor : public BaseSensor {
HLW8012 * _hlw8012 = NULL; HLW8012 * _hlw8012 = NULL;
#if HLW8012_USE_INTERRUPTS == 0
WiFiEventHandler _onconnect_handler;
WiFiEventHandler _ondisconnect_handler;
#endif
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 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;
}; };


+ 96
- 0
code/espurna/sensors/VEML6075Sensor.h View File

@ -0,0 +1,96 @@
// -----------------------------------------------------------------------------
// VEML6075 Sensor over I2C
// Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
// -----------------------------------------------------------------------------
#if SENSOR_SUPPORT && VEML6075_SUPPORT
#pragma once
#undef I2C_SUPPORT
#define I2C_SUPPORT 1 // Explicitly request I2C support.
#include "Arduino.h"
#include "I2CSensor.h"
#include "SparkFun_VEML6075_Arduino_Library.h"
class VEML6075Sensor : public I2CSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
VEML6075Sensor(): I2CSensor() {
_count = 3;
_sensor_id = SENSOR_VEML6075_ID;
_veml6075 = new VEML6075();
}
~VEML6075Sensor() {
delete _veml6075;
}
void begin() {
if (!_veml6075->begin()) {
return;
};
_ready = true;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
// Descriptive name of the sensor
String description() {
char buffer[25];
snprintf(buffer, sizeof(buffer), "VEML6075 @ 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_UVA;
if (index == 1) return MAGNITUDE_UVB;
if (index == 2) return MAGNITUDE_UVI;
return MAGNITUDE_NONE;
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
_error = SENSOR_ERROR_OK;
}
// Current value for slot # index
double value(unsigned char index) {
if (index == 0) return _veml6075->a();
if (index == 1) return _veml6075->b();
if (index == 2) return _veml6075->index();
return 0;
}
void setIntegrationTime(VEML6075::veml6075_uv_it_t integration_time) {
_veml6075->setIntegrationTime(integration_time);
}
void setDynamicMode(VEML6075::veml6075_hd_t dynamic_mode) {
_veml6075->setHighDynamic(dynamic_mode);
}
protected:
VEML6075 * _veml6075 = NULL;
};
#endif // SENSOR_SUPPORT && VEML6075_SUPPORT

+ 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;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 2
- 2
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"
"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];
@ -61,7 +61,7 @@ function magnitudeType(type) {
"Current", "Voltage", "Active Power", "Apparent Power", "Current", "Voltage", "Active Power", "Apparent Power",
"Reactive Power", "Power Factor", "Energy", "Energy (delta)", "Reactive Power", "Power Factor", "Energy", "Energy (delta)",
"Analog", "Digital", "Event", "Analog", "Digital", "Event",
"PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UV", "Distance" , "HCHO",
"PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UVA", "UVB", "UV Index", "Distance" , "HCHO",
"Local Dose Rate", "Local Dose Rate", "Local Dose Rate", "Local Dose Rate",
"Count", "Count",
"NO2", "CO", "Resistance" "NO2", "CO", "Resistance"


+ 6
- 6
code/ota.py View File

@ -55,9 +55,9 @@ def on_service_state_change(zeroconf, service_type, name, state_change):
'app_name': '', 'app_name': '',
'app_version': '', 'app_version': '',
'target_board': '', 'target_board': '',
'mem_size': '',
'sdk_size': '',
'free_space': '',
'mem_size': 0,
'sdk_size': 0,
'free_space': 0,
} }
for key, item in info.properties.items(): for key, item in info.properties.items():
@ -101,9 +101,9 @@ def list_devices():
device.get('app_name', ''), device.get('app_name', ''),
device.get('app_version', ''), device.get('app_version', ''),
device.get('target_board', ''), device.get('target_board', ''),
device.get('mem_size', ''),
device.get('sdk_size', ''),
device.get('free_space', ''),
device.get('mem_size', 0),
device.get('sdk_size', 0),
device.get('free_space', 0),
)) ))
print() print()


+ 103
- 0
code/platformio.ini View File

@ -97,6 +97,8 @@ lib_deps =
https://github.com/LowPowerLab/RFM69#1.1.3 https://github.com/LowPowerLab/RFM69#1.1.3
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/pololu/vl53l1x-arduino#1.0.1
lib_ignore = lib_ignore =
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -2010,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}
@ -2034,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}
@ -2502,6 +2553,58 @@ 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:teckin-sp22-v14]
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} -DTECKIN_SP22_V14
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:teckin-sp22-v14-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} -DTECKIN_SP22_V14
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