Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Controllers
  3. Home Assistant
  4. Correct presentation of Sensebender temperature and humidity?

Correct presentation of Sensebender temperature and humidity?

Scheduled Pinned Locked Moved Home Assistant
7 Posts 3 Posters 2.8k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • MadhiasM Offline
    MadhiasM Offline
    Madhias
    wrote on last edited by Madhias
    #1

    Hi,

    I am starting slowly to get into MySensors, and currently my setup is sporting one Sensebender connected to a Raspberry serial gateway and Home Assistant on this Raspberry. This setup works, and the controller gets temperature and humidity from the sensor.

    I have some questions regarding the presentation in the loop function: the current temperature must be presented? Humidity also? To get the current temperature I have to add in the loop function everything needed to get a temperature value - since the values of the loop function are seen in Home Assistant? So looking at the sketch the temperature and humidity is sent twice to the gateway - once in loop, once in sendTempHumidityMeasurements? Should I get rid of one measurement sent to the gateway?

    Sorry for my basic questions... I am really happy to be so far though :)

    Here are those parts of the sketch:

    void presentation()  {
      sendSketchInfo("Sensebender Micro", RELEASE);
    
      present(CHILD_ID_TEMP,S_TEMP);
      present(CHILD_ID_HUM,S_HUM);
        
    #ifdef BATT_SENSOR
      present(BATT_SENSOR, S_POWER);
    #endif
    }
    
    void loop() {
      if (!initialValueSent) {
        si7021_env data = humiditySensor.getHumidityAndTemperature();
        float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
        int humidity = data.humidityPercent;
        Serial.println("Sending initial value");
        send(msgTemp.set(temperature,1));
        send(msgHum.set(humidity));
        wait(2000, C_SET, V_STATUS);
      }
    }
    
    void sendTempHumidityMeasurements(bool force)
    {
      bool tx = force;
    
      si7021_env data = humiditySensor.getHumidityAndTemperature();
      
      raHum.addValue(data.humidityPercent);
      
      float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100.0);
      float diffHum = abs(lastHumidity - raHum.getAverage());
    
      Serial.print(F("TempDiff :"));Serial.println(diffTemp);
      Serial.print(F("HumDiff  :"));Serial.println(diffHum); 
    
      if (isnan(diffHum)) tx = true; 
      if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true;
      if (diffHum > HUMI_TRANSMIT_THRESHOLD) tx = true;
    
      if (tx) {
        measureCount = 0;
        float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
         
        int humidity = data.humidityPercent;
        Serial.print("T: ");Serial.println(temperature);
        Serial.print("H: ");Serial.println(humidity);
        
        send(msgTemp.set(temperature,1));
        send(msgHum.set(humidity));
        lastTemperature = temperature;
        lastHumidity = humidity;
        transmission_occured = true;
        if (sendBattery > 60) {
         sendBattLevel(true); // Not needed to send battery info that often
         sendBattery = 0;
        }
      }
    }
    
    martinhjelmareM 1 Reply Last reply
    0
    • MadhiasM Madhias

      Hi,

      I am starting slowly to get into MySensors, and currently my setup is sporting one Sensebender connected to a Raspberry serial gateway and Home Assistant on this Raspberry. This setup works, and the controller gets temperature and humidity from the sensor.

      I have some questions regarding the presentation in the loop function: the current temperature must be presented? Humidity also? To get the current temperature I have to add in the loop function everything needed to get a temperature value - since the values of the loop function are seen in Home Assistant? So looking at the sketch the temperature and humidity is sent twice to the gateway - once in loop, once in sendTempHumidityMeasurements? Should I get rid of one measurement sent to the gateway?

      Sorry for my basic questions... I am really happy to be so far though :)

      Here are those parts of the sketch:

      void presentation()  {
        sendSketchInfo("Sensebender Micro", RELEASE);
      
        present(CHILD_ID_TEMP,S_TEMP);
        present(CHILD_ID_HUM,S_HUM);
          
      #ifdef BATT_SENSOR
        present(BATT_SENSOR, S_POWER);
      #endif
      }
      
      void loop() {
        if (!initialValueSent) {
          si7021_env data = humiditySensor.getHumidityAndTemperature();
          float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
          int humidity = data.humidityPercent;
          Serial.println("Sending initial value");
          send(msgTemp.set(temperature,1));
          send(msgHum.set(humidity));
          wait(2000, C_SET, V_STATUS);
        }
      }
      
      void sendTempHumidityMeasurements(bool force)
      {
        bool tx = force;
      
        si7021_env data = humiditySensor.getHumidityAndTemperature();
        
        raHum.addValue(data.humidityPercent);
        
        float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100.0);
        float diffHum = abs(lastHumidity - raHum.getAverage());
      
        Serial.print(F("TempDiff :"));Serial.println(diffTemp);
        Serial.print(F("HumDiff  :"));Serial.println(diffHum); 
      
        if (isnan(diffHum)) tx = true; 
        if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true;
        if (diffHum > HUMI_TRANSMIT_THRESHOLD) tx = true;
      
        if (tx) {
          measureCount = 0;
          float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
           
          int humidity = data.humidityPercent;
          Serial.print("T: ");Serial.println(temperature);
          Serial.print("H: ");Serial.println(humidity);
          
          send(msgTemp.set(temperature,1));
          send(msgHum.set(humidity));
          lastTemperature = temperature;
          lastHumidity = humidity;
          transmission_occured = true;
          if (sendBattery > 60) {
           sendBattLevel(true); // Not needed to send battery info that often
           sendBattery = 0;
          }
        }
      }
      
      martinhjelmareM Offline
      martinhjelmareM Offline
      martinhjelmare
      Plugin Developer
      wrote on last edited by martinhjelmare
      #2

      @Madhias

      Just call sendTempHumidityMeasurements, with force argument set to true, from inside the if block in the loop. Then you don't need to duplicate code so much.

      You also need to change the last argument in the call to wait inside the if block in the loop. V_STATUS is not the correct type for temperature and humidity that you are waiting for. I think you can leave the last argument out in the call to wait. Let me double check that.

      Edit:
      No, you either have to call wait with all three arguments or only call it with one argument for time to wait. I guess you can put either V_HUM or V_TEMP as the last argument and just make sure you request that value last. BTW, you're missing a call to request as well. Put it after you send in the values ie after the call to sendTempHumidityMeasurements.

      1 Reply Last reply
      2
      • MadhiasM Offline
        MadhiasM Offline
        Madhias
        wrote on last edited by
        #3

        I have called the measurement function now inside the loop function (that is way better of course), and changed the third wait argument to V_TEMP. That works.

        I had a request in the code, but commented it out, it was like: request(CHILD_ID_TEMP, V_TEMP); because I was not sure if it is needed.

        Thanks for your help!

        1 Reply Last reply
        2
        • Mark69M Offline
          Mark69M Offline
          Mark69
          wrote on last edited by Mark69
          #4

          Hi Madhias, would you mind sharing your final sketch ?
          I am trying to get the very same thing working right now and am very new to programming for arduino's.
          Thanks in advance :)

          MadhiasM 1 Reply Last reply
          0
          • Mark69M Mark69

            Hi Madhias, would you mind sharing your final sketch ?
            I am trying to get the very same thing working right now and am very new to programming for arduino's.
            Thanks in advance :)

            MadhiasM Offline
            MadhiasM Offline
            Madhias
            wrote on last edited by Madhias
            #5

            I thought I have a correct sketch now, but as I loaded the sketch to another sensor, something must be wrong, since I always get this error in the Home Assistant log:

            WARNING:mysensors.mysensors:Node 2 is unknown
            INFO:mysensors.mysensors:Requesting new presentation for node 2
            INFO:homeassistant.components.mysensors:No sketch_name: node 2
            WARNING:mysensors.mysensors:child_id 1 already exists in children of node 2, cannot add child
            WARNING:mysensors.mysensors:child_id 2 already exists in children of node 2, cannot add child
            

            The json file looks like it got some values (I just changed the format for better reading here):

            {
                "2": {
                    "sketch_version": "1.4",
                    "children": {
                        "1": {
                            "type": 6,
                            "id": 1,
                            "description": "",
                            "values": {
                                "0": "25.6"
                            }
                        },
                        "2": {
                            "type": 7,
                            "id": 2,
                            "description": "",
                            "values": {
                                "1": "65"
                            }
                        }
                    },
                    "sensor_id": 2,
                    "type": 17,
                    "protocol_version": "2.1.1",
                    "sketch_name": null,
                    "battery_level": 104
                }
            }
            

            This is the sketch:

            // Enable debug prints to serial monitor
            #define MY_DEBUG 
            
            // Define a static node address, remove if you want auto address assignment
            #define MY_NODE_ID 2
            
            // Enable and select radio type attached
            #define MY_RADIO_NRF24
            //#define MY_RADIO_RFM69
            
            // Enable to support OTA for this node (needs DualOptiBoot boot-loader to fully work)
            #define MY_OTA_FIRMWARE_FEATURE
            
            #include <SPI.h>
            #include <MySensors.h>
            #include <Wire.h>
            #include <SI7021.h>
            #ifndef MY_OTA_FIRMWARE_FEATURE
            #include "drivers/SPIFlash/SPIFlash.cpp"
            #endif
            #include <EEPROM.h>  
            #include <sha204_lib_return_codes.h>
            #include <sha204_library.h>
            #include <RunningAverage.h>
            //#include <avr/power.h>
            
            // Uncomment the line below, to transmit battery voltage as a normal sensor value
            //#define BATT_SENSOR    199
            
            #define RELEASE "1.4"
            
            #define AVERAGES 2
            
            // Child sensor ID's
            #define CHILD_ID_TEMP  1
            #define CHILD_ID_HUM   2
            
            // How many milli seconds between each measurement
            #define MEASURE_INTERVAL 60000
            
            // How many milli seconds should we wait for OTA?
            #define OTA_WAIT_PERIOD 300
            
            // FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller
            #define FORCE_TRANSMIT_INTERVAL 30 
            
            // When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes.
            // Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement
            
            // HUMI_TRANSMIT_THRESHOLD tells how much the humidity should have changed since last time it was transmitted. Likewise with
            // TEMP_TRANSMIT_THRESHOLD for temperature threshold.
            #define HUMI_TRANSMIT_THRESHOLD 0.5
            #define TEMP_TRANSMIT_THRESHOLD 0.5
            
            // Pin definitions
            #define TEST_PIN       A0
            #define LED_PIN        A2
            #define ATSHA204_PIN   17 // A3
            
            const int sha204Pin = ATSHA204_PIN;
            atsha204Class sha204(sha204Pin);
            
            SI7021 humiditySensor;
            SPIFlash flash(8, 0x1F65);
            
            // Sensor messages
            MyMessage msgHum(CHILD_ID_HUM, V_HUM);
            MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
            
            #ifdef BATT_SENSOR
            MyMessage msgBatt(BATT_SENSOR, V_VOLTAGE);
            #endif
            
            // Global settings
            int measureCount = 0;
            int sendBattery = 0;
            boolean isMetric = true;
            boolean highfreq = true;
            boolean transmission_occured = false;
            
            bool state = false;
            bool initialValueSent = false;
            
            // Storage of old measurements
            float lastTemperature = -100;
            int lastHumidity = -100;
            long lastBattery = -100;
            
            RunningAverage raHum(AVERAGES);
            
            /****************************************************
             *
             * Setup code 
             *
             ****************************************************/
            void setup() {
              
              pinMode(LED_PIN, OUTPUT);
              digitalWrite(LED_PIN, LOW);
            
              Serial.begin(115200);
              Serial.print(F("Sensebender Micro FW "));
              Serial.print(RELEASE);
              Serial.flush();
            
              // First check if we should boot into test mode
            
              pinMode(TEST_PIN,INPUT);
              digitalWrite(TEST_PIN, HIGH); // Enable pullup
              if (!digitalRead(TEST_PIN)) testMode();
            
              // Make sure that ATSHA204 is not floating
              pinMode(ATSHA204_PIN, INPUT);
              digitalWrite(ATSHA204_PIN, HIGH);
              
              digitalWrite(TEST_PIN,LOW);
              
              digitalWrite(LED_PIN, HIGH); 
            
              humiditySensor.begin();
            
              digitalWrite(LED_PIN, LOW);
            
              Serial.flush();
              Serial.println(F(" - Online!"));
              
              isMetric = getControllerConfig().isMetric;
              Serial.print(F("isMetric: ")); Serial.println(isMetric);
              raHum.clear();
              sendTempHumidityMeasurements(false);
              sendBattLevel(false);
              
            #ifdef MY_OTA_FIRMWARE_FEATURE  
              Serial.println("OTA FW update enabled");
            #endif
            
            }
            
            void presentation()  {
              sendSketchInfo("Sensebender Micro", RELEASE);
            
              present(CHILD_ID_TEMP, S_TEMP);
              present(CHILD_ID_HUM, S_HUM);
                
            #ifdef BATT_SENSOR
              present(BATT_SENSOR, S_POWER);
            #endif
            }
            
            
            /***********************************************
             *
             *  Main loop function
             *
             ***********************************************/
            void loop() {
            
              if (!initialValueSent) {
                bool forceMeasure = true;
                sendTempHumidityMeasurements(forceMeasure);
                Serial.println("Requesting initial value from controller");
                request(CHILD_ID_HUM, V_HUM);
                request(CHILD_ID_TEMP, V_TEMP);
                wait(2000, C_SET, V_TEMP);
              }
              
              measureCount ++;
              sendBattery ++;
              bool forceTransmit = false;
              transmission_occured = false;
            #ifndef MY_OTA_FIRMWARE_FEATURE
              if ((measureCount == 5) && highfreq) 
              {
                clock_prescale_set(clock_div_8); // Switch to 1Mhz for the reminder of the sketch, save power.
                highfreq = false;
              } 
            #endif
              
              if (measureCount > FORCE_TRANSMIT_INTERVAL) { // force a transmission
                forceTransmit = true; 
                measureCount = 0;
              }
                
              sendTempHumidityMeasurements(forceTransmit);
            /*  if (sendBattery > 60) 
              {
                 sendBattLevel(forceTransmit); // Not needed to send battery info that often
                 sendBattery = 0;
              }*/
            #ifdef MY_OTA_FIRMWARE_FEATURE
              if (transmission_occured) {
                  wait(OTA_WAIT_PERIOD);
              }
            #endif
            
              sleep(MEASURE_INTERVAL);  
            }
            
            
            /*********************************************
             *
             * Sends temperature and humidity from Si7021 sensor
             *
             * Parameters
             * - force : Forces transmission of a value (even if it's the same as previous measurement)
             *
             *********************************************/
            void sendTempHumidityMeasurements(bool force)
            {
              bool tx = force;
            
              si7021_env data = humiditySensor.getHumidityAndTemperature();
              
              raHum.addValue(data.humidityPercent);
              
              float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100.0);
              float diffHum = abs(lastHumidity - raHum.getAverage());
            
              Serial.print(F("TempDiff :"));Serial.println(diffTemp);
              Serial.print(F("HumDiff  :"));Serial.println(diffHum); 
            
              if (isnan(diffHum)) tx = true; 
              if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true;
              if (diffHum > HUMI_TRANSMIT_THRESHOLD) tx = true;
            
              if (tx) {
                measureCount = 0;
                float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
                 
                int humidity = data.humidityPercent;
                Serial.print("T: ");Serial.println(temperature);
                Serial.print("H: ");Serial.println(humidity);
                
                send(msgTemp.set(temperature,1));
                send(msgHum.set(humidity));
                lastTemperature = temperature;
                lastHumidity = humidity;
                transmission_occured = true;
                if (sendBattery > 60) {
                 sendBattLevel(true); // Not needed to send battery info that often
                 sendBattery = 0;
                }
              }
            }
            
            /********************************************
             *
             * Sends battery information (battery percentage)
             *
             * Parameters
             * - force : Forces transmission of a value
             *
             *******************************************/
            void sendBattLevel(bool force)
            {
              if (force) lastBattery = -1;
              long vcc = readVcc();
              if (vcc != lastBattery) {
                lastBattery = vcc;
            
            #ifdef BATT_SENSOR
                float send_voltage = float(vcc)/1000.0f;
                send(msgBatt.set(send_voltage,3));
            #endif
            
                // Calculate percentage
            
                vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at
                
                long percent = vcc / 14.0;
                sendBatteryLevel(percent);
                transmission_occured = true;
              }
            }
            
            /*******************************************
             *
             * Internal battery ADC measuring 
             *
             *******************************************/
            long readVcc() {
              // Read 1.1V reference against AVcc
              // set the reference to Vcc and the measurement to the internal 1.1V reference
              #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
                ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
              #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
                ADMUX = _BV(MUX5) | _BV(MUX0);
              #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
                ADcdMUX = _BV(MUX3) | _BV(MUX2);
              #else
                ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
              #endif  
             
              delay(2); // Wait for Vref to settle
              ADCSRA |= _BV(ADSC); // Start conversion
              while (bit_is_set(ADCSRA,ADSC)); // measuring
             
              uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
              uint8_t high = ADCH; // unlocks both
             
              long result = (high<<8) | low;
             
              result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
              return result; // Vcc in millivolts
             
            }
            
            /****************************************************
             *
             * Verify all peripherals, and signal via the LED if any problems.
             *
             ****************************************************/
            void testMode()
            {
              uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
              uint8_t ret_code;
              byte tests = 0;
              
              digitalWrite(LED_PIN, HIGH); // Turn on LED.
              Serial.println(F(" - TestMode"));
              Serial.println(F("Testing peripherals!"));
              Serial.flush();
              Serial.print(F("-> SI7021 : ")); 
              Serial.flush();
              
              if (humiditySensor.begin()) 
              {
                Serial.println(F("ok!"));
                tests ++;
              }
              else
              {
                Serial.println(F("failed!"));
              }
              Serial.flush();
            
              Serial.print(F("-> Flash : "));
              Serial.flush();
              if (flash.initialize())
              {
                Serial.println(F("ok!"));
                tests ++;
              }
              else
              {
                Serial.println(F("failed!"));
              }
              Serial.flush();
            
              
              Serial.print(F("-> SHA204 : "));
              ret_code = sha204.sha204c_wakeup(rx_buffer);
              Serial.flush();
              if (ret_code != SHA204_SUCCESS)
              {
                Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
              }
              Serial.flush();
              if (ret_code == SHA204_SUCCESS)
              {
                ret_code = sha204.getSerialNumber(rx_buffer);
                if (ret_code != SHA204_SUCCESS)
                {
                  Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
                }
                else
                {
                  Serial.print(F("Ok (serial : "));
                  for (int i=0; i<9; i++)
                  {
                    if (rx_buffer[i] < 0x10)
                    {
                      Serial.print('0'); // Because Serial.print does not 0-pad HEX
                    }
                    Serial.print(rx_buffer[i], HEX);
                  }
                  Serial.println(")");
                  tests ++;
                }
            
              }
              Serial.flush();
            
              Serial.println(F("Test finished"));
              
              if (tests == 3) 
              {
                Serial.println(F("Selftest ok!"));
                while (1) // Blink OK pattern!
                {
                  digitalWrite(LED_PIN, HIGH);
                  delay(200);
                  digitalWrite(LED_PIN, LOW);
                  delay(200);
                }
              }
              else 
              {
                Serial.println(F("----> Selftest failed!"));
                while (1) // Blink FAILED pattern! Rappidly blinking..
                {
                }
              }  
            }
            

            @Mark69 Can't post a helpful sketch so far. Sorry!

            martinhjelmareM 1 Reply Last reply
            0
            • MadhiasM Madhias

              I thought I have a correct sketch now, but as I loaded the sketch to another sensor, something must be wrong, since I always get this error in the Home Assistant log:

              WARNING:mysensors.mysensors:Node 2 is unknown
              INFO:mysensors.mysensors:Requesting new presentation for node 2
              INFO:homeassistant.components.mysensors:No sketch_name: node 2
              WARNING:mysensors.mysensors:child_id 1 already exists in children of node 2, cannot add child
              WARNING:mysensors.mysensors:child_id 2 already exists in children of node 2, cannot add child
              

              The json file looks like it got some values (I just changed the format for better reading here):

              {
                  "2": {
                      "sketch_version": "1.4",
                      "children": {
                          "1": {
                              "type": 6,
                              "id": 1,
                              "description": "",
                              "values": {
                                  "0": "25.6"
                              }
                          },
                          "2": {
                              "type": 7,
                              "id": 2,
                              "description": "",
                              "values": {
                                  "1": "65"
                              }
                          }
                      },
                      "sensor_id": 2,
                      "type": 17,
                      "protocol_version": "2.1.1",
                      "sketch_name": null,
                      "battery_level": 104
                  }
              }
              

              This is the sketch:

              // Enable debug prints to serial monitor
              #define MY_DEBUG 
              
              // Define a static node address, remove if you want auto address assignment
              #define MY_NODE_ID 2
              
              // Enable and select radio type attached
              #define MY_RADIO_NRF24
              //#define MY_RADIO_RFM69
              
              // Enable to support OTA for this node (needs DualOptiBoot boot-loader to fully work)
              #define MY_OTA_FIRMWARE_FEATURE
              
              #include <SPI.h>
              #include <MySensors.h>
              #include <Wire.h>
              #include <SI7021.h>
              #ifndef MY_OTA_FIRMWARE_FEATURE
              #include "drivers/SPIFlash/SPIFlash.cpp"
              #endif
              #include <EEPROM.h>  
              #include <sha204_lib_return_codes.h>
              #include <sha204_library.h>
              #include <RunningAverage.h>
              //#include <avr/power.h>
              
              // Uncomment the line below, to transmit battery voltage as a normal sensor value
              //#define BATT_SENSOR    199
              
              #define RELEASE "1.4"
              
              #define AVERAGES 2
              
              // Child sensor ID's
              #define CHILD_ID_TEMP  1
              #define CHILD_ID_HUM   2
              
              // How many milli seconds between each measurement
              #define MEASURE_INTERVAL 60000
              
              // How many milli seconds should we wait for OTA?
              #define OTA_WAIT_PERIOD 300
              
              // FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller
              #define FORCE_TRANSMIT_INTERVAL 30 
              
              // When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes.
              // Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement
              
              // HUMI_TRANSMIT_THRESHOLD tells how much the humidity should have changed since last time it was transmitted. Likewise with
              // TEMP_TRANSMIT_THRESHOLD for temperature threshold.
              #define HUMI_TRANSMIT_THRESHOLD 0.5
              #define TEMP_TRANSMIT_THRESHOLD 0.5
              
              // Pin definitions
              #define TEST_PIN       A0
              #define LED_PIN        A2
              #define ATSHA204_PIN   17 // A3
              
              const int sha204Pin = ATSHA204_PIN;
              atsha204Class sha204(sha204Pin);
              
              SI7021 humiditySensor;
              SPIFlash flash(8, 0x1F65);
              
              // Sensor messages
              MyMessage msgHum(CHILD_ID_HUM, V_HUM);
              MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
              
              #ifdef BATT_SENSOR
              MyMessage msgBatt(BATT_SENSOR, V_VOLTAGE);
              #endif
              
              // Global settings
              int measureCount = 0;
              int sendBattery = 0;
              boolean isMetric = true;
              boolean highfreq = true;
              boolean transmission_occured = false;
              
              bool state = false;
              bool initialValueSent = false;
              
              // Storage of old measurements
              float lastTemperature = -100;
              int lastHumidity = -100;
              long lastBattery = -100;
              
              RunningAverage raHum(AVERAGES);
              
              /****************************************************
               *
               * Setup code 
               *
               ****************************************************/
              void setup() {
                
                pinMode(LED_PIN, OUTPUT);
                digitalWrite(LED_PIN, LOW);
              
                Serial.begin(115200);
                Serial.print(F("Sensebender Micro FW "));
                Serial.print(RELEASE);
                Serial.flush();
              
                // First check if we should boot into test mode
              
                pinMode(TEST_PIN,INPUT);
                digitalWrite(TEST_PIN, HIGH); // Enable pullup
                if (!digitalRead(TEST_PIN)) testMode();
              
                // Make sure that ATSHA204 is not floating
                pinMode(ATSHA204_PIN, INPUT);
                digitalWrite(ATSHA204_PIN, HIGH);
                
                digitalWrite(TEST_PIN,LOW);
                
                digitalWrite(LED_PIN, HIGH); 
              
                humiditySensor.begin();
              
                digitalWrite(LED_PIN, LOW);
              
                Serial.flush();
                Serial.println(F(" - Online!"));
                
                isMetric = getControllerConfig().isMetric;
                Serial.print(F("isMetric: ")); Serial.println(isMetric);
                raHum.clear();
                sendTempHumidityMeasurements(false);
                sendBattLevel(false);
                
              #ifdef MY_OTA_FIRMWARE_FEATURE  
                Serial.println("OTA FW update enabled");
              #endif
              
              }
              
              void presentation()  {
                sendSketchInfo("Sensebender Micro", RELEASE);
              
                present(CHILD_ID_TEMP, S_TEMP);
                present(CHILD_ID_HUM, S_HUM);
                  
              #ifdef BATT_SENSOR
                present(BATT_SENSOR, S_POWER);
              #endif
              }
              
              
              /***********************************************
               *
               *  Main loop function
               *
               ***********************************************/
              void loop() {
              
                if (!initialValueSent) {
                  bool forceMeasure = true;
                  sendTempHumidityMeasurements(forceMeasure);
                  Serial.println("Requesting initial value from controller");
                  request(CHILD_ID_HUM, V_HUM);
                  request(CHILD_ID_TEMP, V_TEMP);
                  wait(2000, C_SET, V_TEMP);
                }
                
                measureCount ++;
                sendBattery ++;
                bool forceTransmit = false;
                transmission_occured = false;
              #ifndef MY_OTA_FIRMWARE_FEATURE
                if ((measureCount == 5) && highfreq) 
                {
                  clock_prescale_set(clock_div_8); // Switch to 1Mhz for the reminder of the sketch, save power.
                  highfreq = false;
                } 
              #endif
                
                if (measureCount > FORCE_TRANSMIT_INTERVAL) { // force a transmission
                  forceTransmit = true; 
                  measureCount = 0;
                }
                  
                sendTempHumidityMeasurements(forceTransmit);
              /*  if (sendBattery > 60) 
                {
                   sendBattLevel(forceTransmit); // Not needed to send battery info that often
                   sendBattery = 0;
                }*/
              #ifdef MY_OTA_FIRMWARE_FEATURE
                if (transmission_occured) {
                    wait(OTA_WAIT_PERIOD);
                }
              #endif
              
                sleep(MEASURE_INTERVAL);  
              }
              
              
              /*********************************************
               *
               * Sends temperature and humidity from Si7021 sensor
               *
               * Parameters
               * - force : Forces transmission of a value (even if it's the same as previous measurement)
               *
               *********************************************/
              void sendTempHumidityMeasurements(bool force)
              {
                bool tx = force;
              
                si7021_env data = humiditySensor.getHumidityAndTemperature();
                
                raHum.addValue(data.humidityPercent);
                
                float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100.0);
                float diffHum = abs(lastHumidity - raHum.getAverage());
              
                Serial.print(F("TempDiff :"));Serial.println(diffTemp);
                Serial.print(F("HumDiff  :"));Serial.println(diffHum); 
              
                if (isnan(diffHum)) tx = true; 
                if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true;
                if (diffHum > HUMI_TRANSMIT_THRESHOLD) tx = true;
              
                if (tx) {
                  measureCount = 0;
                  float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
                   
                  int humidity = data.humidityPercent;
                  Serial.print("T: ");Serial.println(temperature);
                  Serial.print("H: ");Serial.println(humidity);
                  
                  send(msgTemp.set(temperature,1));
                  send(msgHum.set(humidity));
                  lastTemperature = temperature;
                  lastHumidity = humidity;
                  transmission_occured = true;
                  if (sendBattery > 60) {
                   sendBattLevel(true); // Not needed to send battery info that often
                   sendBattery = 0;
                  }
                }
              }
              
              /********************************************
               *
               * Sends battery information (battery percentage)
               *
               * Parameters
               * - force : Forces transmission of a value
               *
               *******************************************/
              void sendBattLevel(bool force)
              {
                if (force) lastBattery = -1;
                long vcc = readVcc();
                if (vcc != lastBattery) {
                  lastBattery = vcc;
              
              #ifdef BATT_SENSOR
                  float send_voltage = float(vcc)/1000.0f;
                  send(msgBatt.set(send_voltage,3));
              #endif
              
                  // Calculate percentage
              
                  vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at
                  
                  long percent = vcc / 14.0;
                  sendBatteryLevel(percent);
                  transmission_occured = true;
                }
              }
              
              /*******************************************
               *
               * Internal battery ADC measuring 
               *
               *******************************************/
              long readVcc() {
                // Read 1.1V reference against AVcc
                // set the reference to Vcc and the measurement to the internal 1.1V reference
                #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
                  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
                  ADMUX = _BV(MUX5) | _BV(MUX0);
                #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
                  ADcdMUX = _BV(MUX3) | _BV(MUX2);
                #else
                  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                #endif  
               
                delay(2); // Wait for Vref to settle
                ADCSRA |= _BV(ADSC); // Start conversion
                while (bit_is_set(ADCSRA,ADSC)); // measuring
               
                uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
                uint8_t high = ADCH; // unlocks both
               
                long result = (high<<8) | low;
               
                result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
                return result; // Vcc in millivolts
               
              }
              
              /****************************************************
               *
               * Verify all peripherals, and signal via the LED if any problems.
               *
               ****************************************************/
              void testMode()
              {
                uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
                uint8_t ret_code;
                byte tests = 0;
                
                digitalWrite(LED_PIN, HIGH); // Turn on LED.
                Serial.println(F(" - TestMode"));
                Serial.println(F("Testing peripherals!"));
                Serial.flush();
                Serial.print(F("-> SI7021 : ")); 
                Serial.flush();
                
                if (humiditySensor.begin()) 
                {
                  Serial.println(F("ok!"));
                  tests ++;
                }
                else
                {
                  Serial.println(F("failed!"));
                }
                Serial.flush();
              
                Serial.print(F("-> Flash : "));
                Serial.flush();
                if (flash.initialize())
                {
                  Serial.println(F("ok!"));
                  tests ++;
                }
                else
                {
                  Serial.println(F("failed!"));
                }
                Serial.flush();
              
                
                Serial.print(F("-> SHA204 : "));
                ret_code = sha204.sha204c_wakeup(rx_buffer);
                Serial.flush();
                if (ret_code != SHA204_SUCCESS)
                {
                  Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
                }
                Serial.flush();
                if (ret_code == SHA204_SUCCESS)
                {
                  ret_code = sha204.getSerialNumber(rx_buffer);
                  if (ret_code != SHA204_SUCCESS)
                  {
                    Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
                  }
                  else
                  {
                    Serial.print(F("Ok (serial : "));
                    for (int i=0; i<9; i++)
                    {
                      if (rx_buffer[i] < 0x10)
                      {
                        Serial.print('0'); // Because Serial.print does not 0-pad HEX
                      }
                      Serial.print(rx_buffer[i], HEX);
                    }
                    Serial.println(")");
                    tests ++;
                  }
              
                }
                Serial.flush();
              
                Serial.println(F("Test finished"));
                
                if (tests == 3) 
                {
                  Serial.println(F("Selftest ok!"));
                  while (1) // Blink OK pattern!
                  {
                    digitalWrite(LED_PIN, HIGH);
                    delay(200);
                    digitalWrite(LED_PIN, LOW);
                    delay(200);
                  }
                }
                else 
                {
                  Serial.println(F("----> Selftest failed!"));
                  while (1) // Blink FAILED pattern! Rappidly blinking..
                  {
                  }
                }  
              }
              

              @Mark69 Can't post a helpful sketch so far. Sorry!

              martinhjelmareM Offline
              martinhjelmareM Offline
              martinhjelmare
              Plugin Developer
              wrote on last edited by
              #6

              @Madhias

              Sketchname is missing in the persistence file, so maybe that message doesn't go through? Have you looked at the serial log of the node and confirmed that all messages are sent ok?

              MadhiasM 1 Reply Last reply
              1
              • martinhjelmareM martinhjelmare

                @Madhias

                Sketchname is missing in the persistence file, so maybe that message doesn't go through? Have you looked at the serial log of the node and confirmed that all messages are sent ok?

                MadhiasM Offline
                MadhiasM Offline
                Madhias
                wrote on last edited by Madhias
                #7

                @martinhjelmare It works now! I think it is a hardware issue I have here, since I just put the decoupling capacitor in between the radio and the pin header socket. Checking that connection helped (pushing again in), and the presentation was correct now - including the sketch name.

                1 Reply Last reply
                1
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                20

                Online

                11.7k

                Users

                11.2k

                Topics

                113.1k

                Posts


                Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • MySensors
                • OpenHardware.io
                • Categories
                • Recent
                • Tags
                • Popular