diff --git a/.travis.yml b/.travis.yml index 52d9af97..ec31cea6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,21 @@ sudo: false cache: directories: - "~/.platformio" + - "$TRAVIS_BUILD_DIR/code/.piolibdeps" + - "$TRAVIS_BUILD_DIR/code/espurna/node_modules" install: - pip install -U platformio - cd code ; npm install --only=dev ; cd .. +env: + global: + - BUILDER_TOTAL_THREADS=4 + matrix: + - BUILDER_THREAD=0 + - BUILDER_THREAD=1 + - BUILDER_THREAD=2 + - BUILDER_THREAD=3 script: -- cd code && ./build.sh && cd .. +- cd code && ./build.sh -p && cd .. before_deploy: - mv firmware/*/espurna-*.bin firmware/ deploy: diff --git a/code/build.sh b/code/build.sh index 5b1fd86d..beda36b3 100755 --- a/code/build.sh +++ b/code/build.sh @@ -9,15 +9,36 @@ travis=$(grep env: platformio.ini | grep travis | sed 's/\[env://' | sed 's/\]/ available=$(grep env: platformio.ini | grep -v ota | grep -v ssl | grep -v travis | sed 's/\[env://' | sed 's/\]/ /' | sort) # Parameters +while getopts "lp" opt; do + case $opt in + l) + echo "--------------------------------------------------------------" + echo "Available environments:" + for environment in $available; do + echo "* $environment" + done + exit + ;; + p) + par_build=1 + par_thread=${BUILDER_THREAD:-0} + par_total_threads=${BUILDER_TOTAL_THREADS:-4} + if [ ${par_thread} -ne ${par_thread} -o \ + ${par_total_threads} -ne ${par_total_threads} ]; then + echo "Parallel threads should be a number." + exit + fi + if [ ${par_thread} -ge ${par_total_threads} ]; then + echo "Current thread is greater than total threads. Doesn't make sense" + exit + fi + ;; + esac +done + +shift $((OPTIND-1)) + environments=$@ -if [ "$environments" == "list" ]; then - echo "--------------------------------------------------------------" - echo "Available environments:" - for environment in $available; do - echo "* $environment" - done - exit -fi # Environments to build if [ $# -eq 0 ]; then @@ -63,9 +84,16 @@ node node_modules/gulp/bin/gulp.js || exit echo "--------------------------------------------------------------" echo "Building firmware images..." mkdir -p ../firmware/espurna-$version -for environment in $environments; do - echo "* espurna-$version-$environment.bin" +if [ ${par_build} ]; then + to_build=$(echo ${environments} | awk -v par_thread=${par_thread} -v par_total_threads=${par_total_threads} '{ for (i = 1; i <= NF; i++) if (++j % par_total_threads == par_thread ) print $i; }') +else + to_build=${environments} +fi + +for environment in $to_build; do + echo -n "* espurna-$version-$environment.bin --- " platformio run --silent --environment $environment || exit 1 + stat -c %s .pioenvs/$environment/firmware.bin mv .pioenvs/$environment/firmware.bin ../firmware/espurna-$version/espurna-$version-$environment.bin done echo "--------------------------------------------------------------" diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index a263eda5..7bc40090 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -141,6 +141,7 @@ //#define HCSR04_SUPPORT 1 //#define HLW8012_SUPPORT 1 //#define MHZ19_SUPPORT 1 +//#define NTC_SUPPORT 1 //#define PMSX003_SUPPORT 1 //#define PZEM004T_SUPPORT 1 //#define SHT3X_I2C_SUPPORT 1 diff --git a/code/espurna/config/progmem.h b/code/espurna/config/progmem.h index 8a23389f..d1e44c4f 100644 --- a/code/espurna/config/progmem.h +++ b/code/espurna/config/progmem.h @@ -175,6 +175,9 @@ PROGMEM const char espurna_sensors[] = #if MHZ19_SUPPORT "MHZ19 " #endif + #if NTC_SUPPORT + "NTC " + #endif #if PMSX003_SUPPORT "PMSX003 " #endif diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 771b7c50..4df614e4 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -79,6 +79,14 @@ #define ANALOG_SUPPORT 0 #endif +#ifndef ANALOG_SAMPLES +#define ANALOG_SAMPLES 10 // Number of samples +#endif + +#ifndef ANALOG_DELAY +#define ANALOG_DELAY 0 // Delay between samples in micros +#endif + //------------------------------------------------------------------------------ // BH1750 // Enable support by passing BH1750_SUPPORT=1 build flag @@ -422,6 +430,43 @@ #define MHZ19_TX_PIN 15 #endif +//------------------------------------------------------------------------------ +// NTC sensor +// Enable support by passing NTC_SUPPORT=1 build flag +//-------------------------------------------------------------------------------- + +#ifndef NTC_SUPPORT +#define NTC_SUPPORT 0 +#endif + +#ifndef NTC_SAMPLES +#define NTC_SAMPLES 10 // Number of samples +#endif + +#ifndef NTC_DELAY +#define NTC_DELAY 0 // Delay between samples in micros +#endif + +#ifndef NTC_R_UP +#define NTC_R_UP 0 // Resistor upstream, set to 0 if none +#endif + +#ifndef NTC_R_DOWN +#define NTC_R_DOWN 10000 // Resistor downstream, set to 0 if none +#endif + +#ifndef NTC_T0 +#define NTC_T0 298.15 // 25 Celsius +#endif + +#ifndef NTC_R0 +#define NTC_R0 10000 // Resistance at T0 +#endif + +#ifndef NTC_BETA +#define NTC_BETA 3977 // Beta coeficient +#endif + //------------------------------------------------------------------------------ // SenseAir CO2 sensor // Enable support by passing SENSEAIR_SUPPORT=1 build flag @@ -581,6 +626,7 @@ HCSR04_SUPPORT || \ HLW8012_SUPPORT || \ MHZ19_SUPPORT || \ + NTC_SUPPORT || \ SENSEAIR_SUPPORT || \ PMSX003_SUPPORT || \ PZEM004T_SUPPORT || \ @@ -711,6 +757,11 @@ #include "../sensors/MHZ19Sensor.h" #endif +#if NTC_SUPPORT + #include "../sensors/AnalogSensor.h" + #include "../sensors/NTCSensor.h" +#endif + #if SENSEAIR_SUPPORT #include #include "../sensors/SenseAirSensor.h" diff --git a/code/espurna/config/types.h b/code/espurna/config/types.h index 76aeb45c..b7dbbca8 100644 --- a/code/espurna/config/types.h +++ b/code/espurna/config/types.h @@ -270,6 +270,7 @@ #define SENSOR_HCSR04_ID 0x23 #define SENSOR_SENSEAIR_ID 0x24 #define SENSOR_GEIGER_ID 0x25 +#define SENSOR_NTC_ID 0x26 //-------------------------------------------------------------------------------- // Magnitudes diff --git a/code/espurna/light.ino b/code/espurna/light.ino index 13e927d1..ad1deaf3 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -284,14 +284,14 @@ void _fromHSV(const char * hsv) { void _fromKelvin(unsigned long kelvin) { if (!_light_has_color) return; + + _light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS); if (_light_use_cct) { _setRGBInputValue(LIGHT_MAX_VALUE, LIGHT_MAX_VALUE, LIGHT_MAX_VALUE); return; } - _light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS); - // Calculate colors kelvin /= 100; unsigned int red = (kelvin <= 66) diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index eccaca32..d3b28155 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -318,6 +318,8 @@ void _sensorLoad() { #if ANALOG_SUPPORT { AnalogSensor * sensor = new AnalogSensor(); + sensor->setSamples(ANALOG_SAMPLES); + sensor->setDelay(ANALOG_DELAY); _sensors.push_back(sensor); } #endif @@ -494,6 +496,20 @@ void _sensorLoad() { } #endif + #if NTC_SUPPORT + { + NTCSensor * sensor = new NTCSensor(); + sensor->setSamples(NTC_SAMPLES); + sensor->setDelay(NTC_DELAY); + sensor->setUpstreamResistor(NTC_R_UP); + sensor->setDownstreamResistor(NTC_R_DOWN); + sensor->setBeta(NTC_BETA); + sensor->setR0(NTC_R0); + sensor->setT0(NTC_T0); + _sensors.push_back(sensor); + } + #endif + #if SENSEAIR_SUPPORT { SenseAirSensor * sensor = new SenseAirSensor(); diff --git a/code/espurna/sensors/AnalogSensor.h b/code/espurna/sensors/AnalogSensor.h index e988ab96..e13d2cee 100644 --- a/code/espurna/sensors/AnalogSensor.h +++ b/code/espurna/sensors/AnalogSensor.h @@ -3,7 +3,7 @@ // Copyright (C) 2017-2018 by Xose Pérez // ----------------------------------------------------------------------------- -#if SENSOR_SUPPORT && ANALOG_SUPPORT +#if SENSOR_SUPPORT && (ANALOG_SUPPORT || NTC_SUPPORT) #pragma once @@ -27,6 +27,24 @@ class AnalogSensor : public BaseSensor { _sensor_id = SENSOR_ANALOG_ID; } + void setSamples(unsigned int samples) { + if (_samples > 0) _samples = samples; + } + + void setDelay(unsigned long micros) { + _micros = micros; + } + + // --------------------------------------------------------------------- + + unsigned int getSamples() { + return _samples; + } + + unsigned long getDelay() { + return _micros; + } + // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -60,10 +78,24 @@ class AnalogSensor : public BaseSensor { // Current value for slot # index double value(unsigned char index) { - if (index == 0) return analogRead(0); + if (index == 0) return _read(); return 0; } + protected: + + unsigned int _read() { + if (1 == _samples) return analogRead(0); + unsigned long sum = 0; + for (unsigned int i=0; i<_samples; i++) { + if (i>0) delayMicroseconds(_micros); + sum += analogRead(0); + } + return sum / _samples; + } + + unsigned int _samples = 1; + unsigned long _micros = 0; }; diff --git a/code/espurna/sensors/NTCSensor.h b/code/espurna/sensors/NTCSensor.h new file mode 100644 index 00000000..91426b3e --- /dev/null +++ b/code/espurna/sensors/NTCSensor.h @@ -0,0 +1,125 @@ +// ----------------------------------------------------------------------------- +// NTC Sensor (maps to a NTCSensor) +// Copyright (C) 2018 by Xose Pérez +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && NTC_SUPPORT + +#pragma once + +// Set ADC to TOUT pin +#undef ADC_MODE_VALUE +#define ADC_MODE_VALUE ADC_TOUT + +#include "Arduino.h" +#include "AnalogSensor.h" + +extern "C" { + #include "../libs/fs_math.h" +} + +class NTCSensor : public AnalogSensor { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + NTCSensor(): AnalogSensor() { + _count = 1; + _sensor_id = SENSOR_NTC_ID; + } + + void setBeta(unsigned long beta) { + if (beta > 0) _beta = beta; + } + + void setUpstreamResistor(unsigned long resistance) { + _resistance_up = resistance; + if (_resistance_up > 0) _resistance_down = 0; + } + + void setDownstreamResistor(unsigned long resistance) { + _resistance_down = resistance; + if (_resistance_down > 0) _resistance_up = 0; + } + + void setR0(unsigned long resistance) { + if (resistance > 0) _R0 = resistance; + } + + void setT0(double temperature) { + if (temperature > 0) _T0 = temperature; + } + + // --------------------------------------------------------------------- + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Descriptive name of the sensor + String description() { + return String("NTC @ TOUT"); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String("0"); + } + + // Type for slot # index + unsigned char type(unsigned char index) { + if (index == 0) return MAGNITUDE_TEMPERATURE; + return MAGNITUDE_NONE; + } + + // Current value for slot # index + double value(unsigned char index) { + + double temperature = 0; + + if (index == 0) { + + // sampled reading + double read = _read(); + + // Ru = (1023/c - 1) * Rd + double resistance; + double alpha = (1023.0 / read) - 1; + if (_resistance_down > 0) { + resistance = _resistance_down * alpha; + } else if (0 == alpha) { + resistance = _R0; + } else { + resistance = _resistance_up / alpha; + } + + // 1/T = 1/T0 + 1/B * ln(R/R0) + temperature = fs_log(resistance / _R0); + temperature = (1.0 / _T0) + (temperature / _beta); + temperature = 1.0 / temperature - 273.15; + + } + + return temperature; + + } + + protected: + + unsigned long _beta = NTC_BETA; + unsigned long _resistance_up = NTC_R_UP; + unsigned long _resistance_down = NTC_R_DOWN; + unsigned long _R0 = NTC_R0; + double _T0 = NTC_T0; + +}; + +#endif // SENSOR_SUPPORT && NTC_SUPPORT diff --git a/code/espurna/settings.ino b/code/espurna/settings.ino index efa16675..aa6ac5fc 100644 --- a/code/espurna/settings.ino +++ b/code/espurna/settings.ino @@ -35,9 +35,10 @@ std::vector _setting_key_check_callbacks; unsigned long settingsSize() { unsigned pos = SPI_FLASH_SEC_SIZE - 1; while (size_t len = EEPROMr.read(pos)) { + if (0xFF == len) break; pos = pos - len - 2; } - return SPI_FLASH_SEC_SIZE - pos; + return SPI_FLASH_SEC_SIZE - pos + EEPROM_DATA_END; } // ----------------------------------------------------------------------------- @@ -53,6 +54,7 @@ unsigned int settingsKeyCount() { unsigned count = 0; unsigned pos = SPI_FLASH_SEC_SIZE - 1; while (size_t len = EEPROMr.read(pos)) { + if (0xFF == len) break; pos = pos - len - 2; len = EEPROMr.read(pos); pos = pos - len - 2; @@ -68,6 +70,7 @@ String settingsKeyName(unsigned int index) { unsigned count = 0; unsigned pos = SPI_FLASH_SEC_SIZE - 1; while (size_t len = EEPROMr.read(pos)) { + if (0xFF == len) break; pos = pos - len - 2; if (count == index) { s.reserve(len); diff --git a/code/platformio.ini b/code/platformio.ini index 510cd5b5..f3e7494f 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -79,7 +79,7 @@ lib_deps = https://bitbucket.org/xoseperez/fauxmoesp.git#2.4.2 https://github.com/xoseperez/hlw8012.git#1.1.0 https://github.com/markszabo/IRremoteESP8266#v2.2.0 - https://github.com/xoseperez/justwifi.git#2.0.0 + https://github.com/xoseperez/justwifi.git#2.0.1 https://github.com/madpilot/mDNSResolver#4cfcda1 https://github.com/xoseperez/my92xx#3.0.1 https://bitbucket.org/xoseperez/nofuss.git#0.2.5