diff --git a/hestia-hub/.gitignore b/hestia-hub/.gitignore new file mode 100644 index 0000000..b9f3806 --- /dev/null +++ b/hestia-hub/.gitignore @@ -0,0 +1,2 @@ +.pio +.vscode diff --git a/hestia-hub/lib/Vcc/Vcc.cpp b/hestia-hub/lib/Vcc/Vcc.cpp new file mode 100644 index 0000000..9591f92 --- /dev/null +++ b/hestia-hub/lib/Vcc/Vcc.cpp @@ -0,0 +1,95 @@ +#include + +int Vcc::_intref = 0; + +int Vcc::measure(int repetition, int intref) +{ + int reading; + long acc; + byte oldadcsra; + byte oldprr; + + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \ + || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) \ + || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega324__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) \ + || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega164__) || defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164PA__) || defined(__AVR_ATmega164P__) \ + || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega8535__) \ + || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) + ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); +#elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || \ + defined (__AVR_ATmega168__) || defined (__AVR_ATmega168A__) || defined (__AVR_ATmega168PA__) || \ + defined (__AVR_ATmega168P__) || defined (__AVR_ATmega168PB__) || \ + defined (__AVR_ATmega88__) || defined (__AVR_ATmega88A__) || defined (__AVR_ATmega88P__) || \ + defined (__AVR_ATmega88PA__) || defined (__AVR_ATmega88PB__) || \ + defined (__AVR_ATmega48__) || defined (__AVR_ATmega48A__) || defined (__AVR_ATmega48P__) || \ + defined (__AVR_ATmega48PA__)|| defined (__AVR_ATmega48PB__) || defined(__AVR_ATmega8__) + ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); + //#elif defined(__AVR_ATtiny43U__) //ATtiny43U does not seem to work + //ADMUX = _BV(MUX2) || _BV(MUX0); +#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny24A__) || defined(__AVR_ATtiny44__) \ + || defined(__AVR_ATtiny44A__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny84A__) + ADMUX = _BV(MUX5) | _BV(MUX0); +#elif defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) + ADMUXB = 0; + ADMUXA = _BV(MUX3) | _BV(MUX2) | _BV(MUX0); +#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) + ADMUX = _BV(MUX3) | _BV(MUX2); +#elif defined(__AVR_ATtiny261__) || defined(__AVR_ATtiny261A__) || defined(__AVR_ATtiny461__) \ + || defined(__AVR_ATtiny461A__) || defined(__AVR_ATtiny861__) || defined(__AVR_ATtiny861A__) \ + || defined(__AVR_ATtiny26__) + ADMUX = _BV(MUX1) | _BV(MUX2) | _BV(MUX3) | _BV(MUX4); +#elif defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__) + ADMUX = _BV(MUX3) | _BV(MUX2); +#elif defined(__AVR_ATtiny48__) || defined(__AVR_ATtiny88__) + ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); +#elif defined(__AVR_ATtiny828__) + ADMUXB = 0; + ADMUXA = _BV(MUX0) | _BV(MUX2) | _BV(MUX3) | _BV(MUX4); +#elif defined(__AVR_ATtiny1634__) + ADMUX = _BV(MUX3) | _BV(MUX2) | _BV(MUX0); +#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__) || defined(__AVR_ATtiny4313__) + #error "This MCU does not have an ADC" +#elif defined(__AVR_ATtiny13__) + #error "This MCU does not support measuring Vcc" +#else + #error "Unsupported MCU" +#endif +#if defined(PRR) + oldprr = PRR; + PRR &= ~_BV(PRADC); +#elif defined(PRR0) + oldprr = PRR0; + PRR0 &= ~_BV(PRADC); +#endif + oldadcsra = ADCSRA; + ADCSRA |= _BV(ADEN); + + ADCSRA |= _BV(ADSC); // First conversion after enabling + while (bit_is_set(ADCSRA,ADSC)); + + acc = 0; + for (int i = 0; i < repetition; i++) { + ADCSRA |= _BV(ADSC); // Convert + while (bit_is_set(ADCSRA,ADSC)); + reading = ADC; + acc += ((intref * 1023L) / reading); + } + ADCSRA = oldadcsra; +#if defined(PRR) + PRR = oldprr; +#elif defined(PRR0) + PRR0 = oldprr; +#endif + return acc/repetition; +} + +int Vcc::measure(int repetition) +{ + return measure(repetition, (_intref ? _intref : (eeprom_read_word((unsigned int*)EE_INTREF) == 0xFFFF ? DEFAULT_INTREF : eeprom_read_word((unsigned int*)EE_INTREF)))); +} + +void Vcc::setIntref(int intref) +{ + _intref = intref; +} diff --git a/hestia-hub/lib/Vcc/Vcc.h b/hestia-hub/lib/Vcc/Vcc.h new file mode 100644 index 0000000..b2c18dc --- /dev/null +++ b/hestia-hub/lib/Vcc/Vcc.h @@ -0,0 +1,28 @@ + +#ifndef VCC_H +#define VCC_H + +#include +#include + +#if defined(__AVR_ATmega8__) +#define DEFAULT_INTREF 1300 +#elif defined(__AVR_ATtiny26__) +#define DEFAULT_INTREF 1180 +#elif defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega8535__) +#define DEFAULT_INTREF 1230 +#else +#define DEFAULT_INTREF 1100 +#endif + +#define EE_INTREF (E2END-3) + +class Vcc { + public: + static int measure(int repetition=10); + static int measure(int repetition, int intref); + static void setIntref(int intref); + private: + static int _intref; +}; +#endif diff --git a/hestia-hub/platformio.ini b/hestia-hub/platformio.ini new file mode 100644 index 0000000..8e58965 --- /dev/null +++ b/hestia-hub/platformio.ini @@ -0,0 +1,27 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:pro8MHzatmega328] +platform = atmelavr +board = pro8MHzatmega328 +framework = arduino +lib_deps = + mysensors/MySensors@^2.3.2 + thomasfredericks/Bounce2@^2.72 + adafruit/DHT sensor library@^1.4.6 + +[env:nanoatmega328new] +platform = atmelavr +board = nanoatmega328new +framework = arduino +lib_deps = + mysensors/MySensors@^2.3.2 + thomasfredericks/Bounce2@^2.72 + adafruit/DHT sensor library@^1.4.6 diff --git a/hestia-hub/src/main.cpp b/hestia-hub/src/main.cpp new file mode 100644 index 0000000..f3125e4 --- /dev/null +++ b/hestia-hub/src/main.cpp @@ -0,0 +1,160 @@ +#define PRO_MINI // PRO_MINI o NANO + +#define MY_RADIO_RF24 +#define MY_DEBUG + +#ifdef NANO + #define MY_RF24_CE_PIN 10 + #define MY_RF24_CS_PIN 9 +#endif + +#ifdef PRO_MINI + #define MY_RF24_CE_PIN 9 + #define MY_RF24_CS_PIN 10 +#endif + +#define MY_RF24_CHANNEL 3 + +#ifdef PRO_MINI + #define MY_NODE_ID 5 +#endif + +#ifdef NANO + #define MY_NODE_ID 4 +#endif + +#include + +#ifdef NANO + #include +#endif + +#ifdef PRO_MINI + #include + #include +#endif + +#ifdef NANO + #define RLY_ID 1 + + #define RLY_PIN 4 + #define SW1_PIN 5 + #define SW2_PIN 6 + + MyMessage ch_comm_relay(RLY_ID, V_STATUS); + Bounce sw1Debouncer = Bounce(); +#endif + +#ifdef PRO_MINI + #define DHT_PIN 4 + DHT dht22(DHT_PIN, DHT22); + + #define DHT_ID_TEM 1 + #define DHT_ID_HUM 2 + MyMessage ch_comm_dht_temperature(DHT_ID_TEM, V_TEMP); + MyMessage ch_comm_dht_humidity(DHT_ID_HUM, V_HUM); + + const float VccMin = 3.7; + const float VccMax = 4.2; + Vcc vcc; + + #define VCC_ID 3 + MyMessage ch_comm_vcc(VCC_ID, V_VOLTAGE); +#endif + +void presentation() +{ + sendSketchInfo("HH-1", "1.0"); + #ifdef NANO + present(RLY_ID, S_BINARY); + #endif + + #ifdef PRO_MINI + present(DHT_ID_TEM, S_TEMP); + present(DHT_ID_HUM, S_HUM); + present(VCC_ID, S_MULTIMETER); + #endif +} + +void setup() +{ + Serial.begin(115200); + + #ifdef NANO + pinMode(RLY_PIN, OUTPUT); + pinMode(SW1_PIN, INPUT_PULLUP); // siempre a HIGH a menos que se pulse + pinMode(SW2_PIN, OUTPUT); // siempre a LOW + + digitalWrite(SW2_PIN, LOW); + + sw1Debouncer.attach(SW1_PIN); + sw1Debouncer.interval(25); + + send(ch_comm_relay.set(LOW)); + #endif + + #ifdef PRO_MINI + dht22.begin(); + pinMode(DHT_PIN, INPUT); + #endif + + wait(5000); +} + +void loop() +{ + #ifdef NANO + sw1Debouncer.update(); + static uint8_t lastState = 255; + uint8_t newState = !(sw1Debouncer.read() ^ digitalRead(SW2_PIN)); // SW1 XNOR SW2 + + if (newState != lastState) + { + lastState = newState; + digitalWrite(RLY_PIN, newState); + send(ch_comm_relay.set(newState)); + } + #endif + + #ifdef PRO_MINI + float t = dht22.readTemperature(); + float h = dht22.readHumidity(); + + if (!isnan(t) && !isnan(h)) + { + send(ch_comm_dht_temperature.set(t, 2)); + send(ch_comm_dht_humidity.set(h, 2)); + } + + int voltage = Vcc::measure(100, 1100); + int batteryPercent = static_cast(100.0 * (voltage - VccMin) / (VccMax - VccMin)); + if (batteryPercent > 100) batteryPercent = 100; + if (batteryPercent < 0) batteryPercent = 0; + + sendBatteryLevel(batteryPercent); // función de MySensor que envía el procentaje + + wait(2000); + #endif +} + +#ifdef NANO +void receive(const MyMessage &message) +{ + int dest_node = message.getSensor(); + int msg_type = message.getType(); + + if (dest_node != RLY_ID) + { + return; + } + + if (msg_type != V_STATUS) + { + return; + } + + int new_value = message.getInt(); + digitalWrite(RLY_PIN, new_value); + send(ch_comm_relay.set(new_value)); +} +#endif