Navigation

    • Register
    • Login
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. fleinze
    3. Posts
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Posts made by fleinze

    • RE: Chinese Arduino Nanos with Atmega328PB

      I got two different boards from the same seller:
      https://de.aliexpress.com/item/2pcs-Nano-3-0-controller-compatible-with-for-arduino-nano-Atmega328P-CH340-USB-driver-NO-with/32828478049.html?spm=a2g0s.9042311.0.0.SGrO1Y
      and
      https://de.aliexpress.com/item/Freeshipping-2pcs-lot-Nano-3-0-controller-compatible-for-arduino-nano-CH340-USB-driver-NO-CABLE/32818556647.html?spm=a2g0s.9042311.0.0.SGrO1Y

      They are not advertised to contain the PB and the pictures also show a P so I guess there is no guarantee...

      posted in Hardware
      fleinze
      fleinze
    • Chinese Arduino Nanos with Atmega328PB

      Today I received some chinese Nanos which actually feature the Atmega328PB instead of the P variant.
      I did not yet test any of the extra features yet but at least the device signature checks out.
      The boards are standard layout so the pins 3 and 6 are not useable on this board.

      posted in Hardware
      fleinze
      fleinze
    • RE: 💬 Building a Raspberry Pi Gateway

      I compiled the gateway for spi1 because I have a display using spi0. Two problems I came across:

      1. the master branch doesn't work. It compiles, it seems to work but it never receives anything.
      2. the development branch works but I needed to define the right cs-pin even if I redirected the pin in config.txt (with dtoverlay=spi1-1cs,cs0_pin=16)
        The following configure worked for me:
      ./configure --spi-driver=SPIDEV --spi-spidev-device=/dev/spidev1.0 --my-rf24-cs-pin=36 --my-rf24-ce-pin=33 --my-rf24-irq-pin=31
      
      posted in Announcements
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      Hi,

      this is my code working with 2.1 version. The code is not tidied up, please excuse.

      /*
         MySensors-Node for DS18B20 Temperature-Sensors.
         Mysensors.Library-Version 1.6
      */
      
      #define MY_RADIO_NRF24
      
      #define MY_TRANSPORT_UPLINK_CHECK_DISABLED
      
      //#define MY_DEBUG
      
      
      #include <MySensors.h>
      #include <SPI.h>
      #include <Wire.h>
      #include <SI7021.h>
      
      #define BATT_SENSOR
      //#define VCCGND_PINS
      
      #ifdef VCCGND_PINS
      const uint8_t GND = A2;
      const uint8_t VCC = A3;
      #endif
      
      #ifdef BATT_SENSOR
      #define REPORT_VOLTAGE
      #endif
      
      const unsigned long SLEEP_TIME = 300000; // Sleep time between reads (in milliseconds)
      
      const uint8_t TEMP_TIME = 12; //at least every nth time battery is reported
      const uint8_t HUM_TIME = 12;
      const uint8_t BATT_TIME = 12; //when also BATT-LEVEL is reportet
      const float BATT_100 = 3; //3.3V for CR2032, 3V for 2xAA
      const float BATT_0 = 2.2;
      
      SI7021 sensor;
      
      float lastTemperature, lastHum;
      uint8_t lastTempSent = 0;//, lastHumSent = 0;
      uint8_t numSensors = 0;
      boolean receivedConfig = false;
      boolean metric = true;
      // Initialize temperature message
      MyMessage msgTemp(0, V_TEMP);
      MyMessage msgHum(0, V_HUM);
      #ifdef REPORT_VOLTAGE
      MyMessage msgBatt(1, V_VOLTAGE);
      #endif
      #ifdef BATT_SENSOR
      uint8_t battReport = BATT_TIME - 1; //First report at startup
      long oldvalue = 0;
      #endif
      
      
      void setup()
      {
      
        #ifdef VCCGND_PINS
        pinMode(VCC, OUTPUT);
        digitalWrite(VCC, HIGH);
        pinMode(GND, OUTPUT);
        digitalWrite(GND, LOW);
        #endif
        
        if (!sensor.begin()) {
          Serial.println("No Sensor found!");
          while (true);
        }
        
      
      }
      
      void presentation() {
      
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("TempHumSi7021", "0.1a");
      
        // Present all sensors to controller
        present(0, S_HUM);
        //present(1, S_HUM);
      #ifdef REPORT_VOLTAGE
        present(1, S_MULTIMETER);
      #endif
      }
      
      
      void loop()
      {
        //delay(2000);//for sensor to start up
        boolean tempsent = false;
      
        // Fetch temperatures from Dallas sensors
        si7021_thc temphum = sensor.getTempAndRH();
      
        // Read temperatures and send them to controller
        // Fetch and round temperature to one decimal
        float temperature = (float)(temphum.celsiusHundredths) / 100.0;
        float humidity = (float)(temphum.humidityPercent);
        // Only send data if temperature has changed and no error
        if ((lastTemperature != temperature) || lastHum != humidity || (++lastTempSent >= TEMP_TIME)) {
          // Send in the new temperature
          send(msgTemp.set(temperature, 1));
          send(msgHum.set(humidity, 1));
          lastHum = humidity;
          lastTemperature = temperature;
          lastTempSent = 0;
          tempsent = true;
        }
      
      
      #ifdef BATT_SENSOR
        if (++battReport >= BATT_TIME && tempsent) {
      
          //gw.sleep(10);
          long value = readVcc();
      
      
          if (value != oldvalue) {
            int percent = (( (float)(value) / 1000 ) - BATT_0) / (BATT_100 - BATT_0) * 100;
            percent = (percent > 100) ? 100 : percent;
            percent = (percent < 0) ? 0 : percent;
            sendBatteryLevel(percent);
      #ifdef REPORT_VOLTAGE
            send(msgBatt.set((float)(value) / 1000, 2));
      #endif
          }
          oldvalue = value;
          battReport = 0;
        }
      #endif
        sleep(SLEEP_TIME);//wake on interrupt or after sleep-time
        //delay(2000);//for sensor to start up
      }
      
      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__)
        ADMUX = _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
      }```
      posted in My Project
      fleinze
      fleinze
    • Defective pro mini and the solution

      Hi!
      I had a pro mini which stopped working with the following symptoms:

      • No communication
      • not even a flicker on Pin 13 LED
      • not responding to programming attempts, not even with ISP.
      • RST pin has a voltage of ca. 100mV

      The pro mini started working again without me doing anything and then after a few months stopped working again.

      After a lot of soldering (replacing most components including the atmega) it turned out that the board had a ca. 100 Ohm short between RST and GND...

      So if you experience the above symptoms just measure resistance between RST and GND.

      posted in Hardware
      fleinze
      fleinze
    • RE: NRF24L01+PA+LNA distance problem

      Sometimes we get shitty modules from china:
      https://forum.mysensors.org/topic/1153/we-are-mostly-using-fake-nrf24l01-s-but-worse-fakes-are-emerging
      I made good experiance with these rather expensive ones:
      https://de.aliexpress.com/item/2pcs-RF2401F20-2-4G-high-integrated-RF-module-with-Nordic-s-RF-chip-nRF24L01-For-Free/32302870943.html
      But even with these I had to be very careful about antenna placement

      posted in Troubleshooting
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      I put the arduino to sleep during the conversion time, so this is not a big issue. But I agree that the DS18B20 is not the best, but it is widely available. For newer nodes I try to use the Si7021 where possible.

      posted in My Project
      fleinze
      fleinze
    • RE: NRF24L01+PA+LNA distance problem

      @yd-kim In my case I added an extra wire-connection fromm the 5V-side of the LDO-module to the 3.3V-side.

      posted in Troubleshooting
      fleinze
      fleinze
    • RE: Multiple Gateways for redundancy

      @David I think it can work as long as you sure that only one Gateway is able to send and the others are mute. Kind of the same as with redundant hot standby server systems.

      posted in Hardware
      fleinze
      fleinze
    • RE: NRF24L01+PA+LNA distance problem

      I had some issues with pa+lna modules. The solution was a better ground connection.

      posted in Troubleshooting
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @flopp I added the capacitor and put the old battery in. By old battery I mean the one I had replaced a week earlier for a new one. Sensor running smooth since, so great success!

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      I just added an 100uF capacitor to one of my sensors and put an old battery in. Let's see how much more life I can get out of this battery now.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @carmelo42 The fuses only are written when you burn the bootloader, not when uploading the sketch. The Arduino IDE takes the fuse bytes from the boards.txt files.
      It would also be possible to just set the fuse bytes by using the avrdude-program from a command line, but you will still need to use a programmer.
      The extended-fuse setting 0xFF is the same as 0x07 as only the last 3 bits of this bytes are used. Both values will give you BOD disabled.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @carmelo42 sorry I somehow missed your post. I use the standard-bootloader as I did not get Optiboot to run on the 3.3V/8MHz pro minis. I set the extended fuse to 0x07 (BOD disabled) by editing boards.txt.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @Nca78 said:

      add a capacitor of 100-200µF

      I will try this, thanks! Currently I use the 10uF capacitor which is on the arduino pro minis on the raw pin side.

      in your code, add a sleep command between message sending

      How long do you sleep? In normal operation there is only one send command per loop, I only send battery level once every hour. I try to read vcc after sending the temperature so the battery is under some load when measuring.

      use a better sensor that can accept a lower voltage

      I already built one with a Si7021 sensor. But I ran out of CR2032 so I powered it using two AA cells. I should solder it back to coin cell now I got some.

      you can just get Vcc from the A0 pin

      I don't know this method do you have a link or can you explain it?

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @carmelo42

      The no-resistor-library can be found here:
      https://wp.josh.com/2014/06/23/no-external-pull-up-needed-for-ds18b20-temp-sensor/

      The resistors (there are two but the other one is barely visible) are for voltage-measurement. In a later version I got rid of them using this resistor-less method of measurement:
      http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      Measuring the voltage proofed to be worthless for this kind of battery. It is more dependent of the temperature than from anything else.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @carmelo42 I just changed coin-cell on one of my sensors. It lasted since for 10 months, this is ok for me.

      posted in My Project
      fleinze
      fleinze
    • RE: How to control four relays

      @NotTooTechy
      I think you can do this with a lua script on domoticz:
      https://www.domoticz.com/wiki/Scripts

      posted in Domoticz
      fleinze
      fleinze
    • RE: How to: set your power/watermeter for domoticz on rpi

      Well actually i didn't. Thanks a lot!

      posted in Domoticz
      fleinze
      fleinze
    • RE: My controller-less mysensors temperature logger

      Hi @sbackaer !
      The version 1.5 does not have the gateway class. I currently work with the development branch and I didn't use the 1.5 for quite some time; but I think it is enough to

      • remove the mygateway.h include
      • replace the mygateway contructor with a mysensor constructor
      • replace gw.processRadioMessage with gw.process()

      Take a look at the serial gateway example.

      posted in My Project
      fleinze
      fleinze
    • RE: SI7021 boards

      @m26872 @kenci @AWI Thank you very much for your answers!
      I will go for removing the LDO but letting the level-shifter in place, because it is a pain in the ass to bypass the levelshifter.

      Bypassing the desoldered LDO is very easy. Just connect the following point on the resistor-array:
      0_1455974189828_gy21.jpg

      posted in Hardware
      fleinze
      fleinze
    • RE: SI7021 boards

      I just received some si7021 boards from china. They are with LDO and level shifter, similar to
      http://www.aliexpress.com/item/Si7021-Industrial-High-Precision-Humidity-Sensor-with-I2C-Interface-for-Arduino/32529522264.html
      (the original offer went offline, it was from a reseller named "home boutique", no idea why they sold this item)
      If I use them with a battery node, is it sufficient to remove (and short-cut) the LDO or do I need to remove the level shifter too?

      posted in Hardware
      fleinze
      fleinze
    • RE: Is Raspberry a Solid Controller?

      This site (in german) suggests to use a standard power-bank as a raspi-ups:
      http://raspi-ups.appspot.com/de/index.jsp

      posted in Domoticz
      fleinze
      fleinze
    • RE: Fun with magnetometer / digital compass sensors

      I am using the second one, which has a regulator but no level converter. It works with 5v but i will check if i can turn off the internal pull ups on the twi in arduino. (the board seems to have two 10k pull-ups for sda and sck)

      posted in Hardware
      fleinze
      fleinze
    • Fun with magnetometer / digital compass sensors

      A few days ago I got a HMC5883L magnetometer from China. I do not post the link as it is the reseller is offline due to Chinese new year.

      Now I can think of two applications for it:

      1. Replacement for hall-sensors
        I have one of these cheap Chinese hall-sensors using a 3144 or 44e hall switch. They are not linear but switch when a magnetic flux of 30mT is detected.
        They did not work on my very old gas-meter, even if I could measure some magnetic field with an analog compass.
        I tried to measure the field with the magnetometer and I could see a very clear change in the field when gas is flowing.
        I did not write a proper code, but will keep you updated.
        On the pro side ist the high sensitivity of 70nT (about 500000 times better than the hall sensor) and also the low current consumption (100µA in measurement, 2µA in idle mode vs. 25mA on the hall sensor).
        On the con side is the rather high effort for signal processing in code (e.g. low pass filtering for getting rid of the earth magnetic field).

      2. Non-invasive current measurement
        The maximum sampling rate of the HMC5883L is 160Hz, which is in theory enough to signals of up to 80Hz.
        Hence it can be used to measure the magnetic field of 50Hz or 60Hz currents.
        I did a first test with my 60W solder iron. When holding the sensor to the cable I got a very clear Signal with an amplitude of about 20mT.
        It might be hard to calculate an exact current from this reading, as the magnetic field depends on the exact position of the sensor.
        But it can be used as a binary switch sensor which reports the power state of some device. One could e.g. use it to monitor the fridge and send an alarm if the fridge is running for too long.

      Has anyone any experiences with the applications above?

      posted in Hardware
      fleinze
      fleinze
    • RE: Is Raspberry a Solid Controller?

      I run domoticz on a Rpi 1 B+. At first I had some issues with a weak power supply, but never had any problems since.
      Domoticz doesn't use more than a few percent of the cpu, I didn't even have problems running kodi on the same rpi or compiling large software packages at the same time as running domoticz.
      I am sure it would even run on the new zero without problems, but this piece of hardware seems unavailable for a decent price.

      posted in Domoticz
      fleinze
      fleinze
    • RE: water meter - reading method with Line Track Sensor

      @Mikael-Kermorgant You can change the trigger point of the line track sensor using the potentiometer. Did you try this? I used this method on a ferraris-powermeter and finding the right point was quite delicate.

      posted in Hardware
      fleinze
      fleinze
    • RE: Mini-controller using Arduino?

      I did exactly this:
      http://forum.mysensors.org/topic/1812/my-controller-less-mysensors-temperature-logger

      All the network-functions work without a controller. Only for the auto-node-id-feature a controller is needed.

      posted in Development
      fleinze
      fleinze
    • RE: RFduino

      The RFduino uses the NRF51822 which is discussed here: http://forum.mysensors.org/topic/1788/nrf51822-as-an-all-in-one

      posted in Hardware
      fleinze
      fleinze
    • How to: set your power/watermeter for domoticz on rpi

      This worked for me.
      All steps are done in command line, so you don't need screen/keyboard on the raspberry pi. To get to the commandline you need to open a ssh-session (command ssh pi@raspberrypi.local on linux and macos, use putty on windows)
      You can also do the same steps with a graphical sqlite-editor.

      1. Get a db-editor
        Download:
        wget --no-check-certificate https://www.sqlite.org/2016/sqlite-amalgamation-3100100.zip
        (please look which version is current on the sqlite page)
        unzip:
        unzip sqlite-amalgamation-3100100.zip
        Build:
        cd sqlite-amalgamation-3100100
        gcc shell.c sqlite3.c -lpthread -ldl
        Get a cup of tee, this takes a while... Don't close the ssh-session!
        When the compiler is done, it has created a file named a.out, i rename it for convenience:
        mv a.out sqlit3
        this is an executable file, you can move it wherever you want.

      2. make a copy of the domoticz database in case something goes wrong!
        you can find this in the domoticz web interface at setup->settings->backup or you can copy the file directly on the rpi (need admin-rights):
        sudo cp <path-to-domoticz>/domoticz.db <some-save-path>

      3. Get domoticz and the node ready:
        Stop domoticz:
        sudo <path-to-domoticz>/domoticz.sh stop or in the web interface. It this does not work you might need to make the script executable: chmod +x domoticz.sh
        Stop the power/watermeter node (e.g. unplug the power supply).
        Read the meter. Calculate the pulse-variable by multiplying the meter-reading with the pulse-factor.
        In this example the meter reads 1150.210 kWh, the pulse-factor is 500. The pulse-variable needs to be set to 575105.

      4. Do the edit.
        Open the domoticz.db:
        sudo ./sqlite3 <path-to-domoticz>/domoticz.db
        The table to edit is MySensorsVars.
        In this example the powermeter node has the id 12, the pulse variable is set to 575105.
        UPDATE MySensorsVars SET Value=575105 WHERE NodeID=12;
        Check the result with
        SELECT * FROM MySensorsVars;
        Exit sqlite with .quit

      5. Restart
        sudo <path-to-domoticz>/domoticz.sh start
        plug in the power/watermeter-node.

      Have Fun!

      posted in Domoticz
      fleinze
      fleinze
    • RE: Read battery voltage without resistors.

      I didn't realize that this has already been discussed. Just thought this is a very good option - at least when powering directly from battery. Maybe it could be mentioned in the battery powering section on the mysensors webpage.

      posted in Development
      fleinze
      fleinze
    • RE: Read battery voltage without resistors.

      Thats right. But with the same principle you can also read an external voltage that is fed into the Aref-pin. Just read the value of the internal 1.1V reference against the external reference.
      Sadly the Aref is not available on the pro mini boards. With some soldering skills it could be obtained directly from the chip.

      posted in Development
      fleinze
      fleinze
    • Read battery voltage without resistors.

      You can read the battery voltage on arduino without any voltage dividers using a trick. It is described here:
      http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
      The trick is to read the value of the internal 1.1V reference against the battery voltage. This is not supported by the analogRead(); command

      posted in Development
      fleinze
      fleinze
    • RE: Doorbell node

      calling the millis(); function will return a time variable in milli seconds. Save it into a variable and compare it to the current value later to see how much time has passed.

      posted in Development
      fleinze
      fleinze
    • RE: 2 channel in wall dimmer

      Could you share schematics?
      How many Watt/Ampere are you trying to dim? Is residual heat from the transistore/thyristors? an issue?

      posted in My Project
      fleinze
      fleinze
    • RE: Temperature / humidity node with OLED display

      I experienced some burn in effect on this SSD1306 displays after a few months of running, so turning the display off is a good idea!

      posted in My Project
      fleinze
      fleinze
    • Text-Node as Temperature-Display

      Hi!

      I use MySensors with Domoticz for tracking indoor and outdoor temperatures. In summer it is important for me to know the temperatures, so I don't open the windows before it is cooler outside than inside.
      On the hottest summer nights the time to open the windows can be in the middle of the night. At this time it isn't very handy to check the Domoticz-page with a Laptop or Phone.
      For this application I found a good solution with the V_TEXT-node.

      Currently it is still a breadboard-design, but I will make something more permanent soon.
      I plan to power it with a battery and switch it off after reading.
      DSC_0030a.jpg

      The arduino-sketch requests 5 texts (for 5 display lines) and goes to sleep afterwards. It can be woken up again with a button on pin 3. In this case, the texts are requested again.

      /*
       * Text-Node:
       * this node requests five texts and goes to sleep afterwards
       *
       */
      
      #define MY_RADIO_NRF24
      #define MY_RF24_CE_PIN 5
      #define MY_RF24_CS_PIN 6
      #define MY_NODE_ID 51
      
      #include "U8glib.h"
      #include <MySensor.h>
      #include <SPI.h>
      
      U8GLIB_SSD1306_128X64 u8g(7, 8, 9); //u8g constructor cs=7, dc=8, res=9
      
      char lastLCD[5][21] = {"Booting", "MySens up", "", "", ""};                  //array of strings
      unsigned long lastUpdate = 0;
      boolean received[5] = {false, false, false, false, false};
      
      void setup() {
        pinMode(3, INPUT_PULLUP); //interrupt pin
        updateDisplay();
      
        sendSketchInfo("Temperature Text", "1.0");
      
        strcpy(lastLCD[2], "Info sent");
        updateDisplay();
      
        for ( uint8_t i = 0; i < 5; i++) {
          present(i, S_INFO);
          request(i, V_TEXT);
        }
        
        strcpy(lastLCD[3], "First requ");
        updateDisplay();
      }
      
      void loop() {
        while (received[0] == false || received[1] == false || received[2] == false || received[3] == false || received[4] == false ) {
          unsigned long now = millis();
          transportProcess();
          if (now - lastUpdate > 1000) {//repeat request every second until every string is received.
            for ( uint8_t i = 0; i < 5; i++) {
              if ( !received[i]) request(i, V_TEXT);
            }
            lastUpdate = now;
          }
          updateDisplay();
        }
      
        sleep(1, FALLING); //sleep forever, interrupt pin 3
      
        for (uint8_t i = 0; i < 5; i++) received[i] = false; //after wake up reset received status
      }
      
      void updateDisplay() {
        u8g.setFont(u8g_font_courB12);
        u8g.setFontPosTop();
      
        u8g.firstPage();
        do {
          for (uint8_t i = 0; i < 5; i++) {
            u8g.drawStr(0, i * 13, lastLCD[i]);
          }
        } while (u8g.nextPage());
      }
      
      void receive(const MyMessage & message) {
        if (message.type == V_TEXT) {                 // Text messages only
      #ifdef MY_DEBUG    // Write some debug info
          Serial.print("Sensor: "); Serial.print(message.sensor); Serial.print(", Message: "); Serial.println(message.getString());
      #endif
          if (message.sensor < 5) {
            strcpy(lastLCD[message.sensor], message.getString());
            received[message.sensor] = true;
          }
        }
      }
      

      On the Domoticz-side is a lua script, which updates the texts whenever the corresponding temperature is updated:

      -- script_device_text.lua
      local line1 = 'Textline1'
      local line1idx = '25'
      local line1text = 'Innen:  '
      local line1temp = 'Wohnzimmer'
      local line2 = 'Textline2'
      local line2idx = '26'
      local line2text = 'Aussen: '
      local line2temp = 'großer Hof'
      local line3 = 'Textline3'
      local line3idx = '27'
      local line3text = 'kl.Hof: '
      local line3temp = 'kleiner Hof'
      local line4 = 'Textline4'
      local line4idx = '28'
      local line4text = 'Kizi:   '
      local line4temp = 'Kinderzimmer'
      local line5 = 'Textline5'
      local line5idx = '29'
      local line5text = 'Gang:   '
      local line5temp = 'Gang aussen'
      
      commandArray = {}
      
      
      if devicechanged[line1temp] then
      	commandArray['UpdateDevice']=line1idx..'|0|'..line1text..otherdevices_svalues[line1temp]
      end
      
      if devicechanged[line2temp] then
      	commandArray['UpdateDevice']=line2idx..'|0|'..line2text..otherdevices_svalues[line2temp]
      end
      
      if devicechanged[line3temp] then
          commandArray['UpdateDevice']=line3idx..'|0|'..line3text..otherdevices_svalues[line3temp]
      end
      
      if devicechanged[line4temp] then
          commandArray['UpdateDevice']=line4idx..'|0|'..line4text..otherdevices_svalues[line4temp]
      end
      
      if devicechanged[line5temp] then
          commandArray['UpdateDevice']=line5idx..'|0|'..line5text..otherdevices_svalues[line5temp]
      end
      
      return commandArray
      

      I also made a sketch for a continuous-update display. As Domoticz doesn't push the texts, the sketch contains a switch. Every time the switch is switched on, the sketch requests the text:

      #define MY_RADIO_NRF24
      #define MY_RF24_CE_PIN 5
      #define MY_RF24_CS_PIN 6
      #define MY_NODE_ID 50
      
      #include "U8glib.h"
      #include <MySensor.h>
      #include <SPI.h>
      
      
      U8GLIB_SSD1306_128X64 u8g(7, 8, 9); //u8g constructor
      
      const byte LCD_CHILD = 1;
      const byte LCD_NEW_SWITCH = 0;
      char lastLCD[21] = "";
      unsigned long lastUpdate = 0, lastDisplay = 0;
      boolean incoming = false;
      
      MyMessage swMsg(LCD_NEW_SWITCH, V_LIGHT);
      
      void setup() {
        sendSketchInfo("text-push-node", "1.0");
        present(LCD_CHILD, S_INFO);
        present(LCD_NEW_SWITCH, S_LIGHT);
      
        request(LCD_CHILD, V_TEXT);
        request(LCD_NEW_SWITCH, V_LIGHT);
      }
      
      void loop() {
        // put your main code here, to run repeatedly:
        unsigned long now = millis();
      
        if (incoming) { //request text, if there is a new one available
          send(swMsg.set(false)); //reset the switch (not needed, but serves as ack)
          request(LCD_CHILD, V_TEXT);
          incoming = false;
        }
      
        if (now - lastDisplay > 1000) { //update every 1 s
          lastDisplay = now;
      
          u8g.setFont(u8g_font_helvB10);
          u8g.setFontPosTop();
      
          //update the Display:
          u8g.firstPage();
          do {
            u8g.drawStr(0, 0, lastLCD);
          } while (u8g.nextPage());
        }
      }
      
      
      void receive(const MyMessage & message) {
        if (message.type == V_TEXT) {                       // Text messages only
          // Write some debug info
      #ifdef MY_DEBUG
          Serial.print("Message: "); Serial.print(message.sensor); Serial.print(", Message: "); Serial.println(message.getString());
      #endif
          if (message.sensor == LCD_CHILD ) {
            strcpy(lastLCD, message.getString());
          }
        }
        else if (message.type == V_LIGHT && message.sensor == LCD_NEW_SWITCH) {
      #ifdef MY_DEBUG
          Serial.print("New status: "); Serial.println(message.getBool());
      #endif
          incoming = true;
        }
      }
      

      In this case you need to set the switch in the lua-script with commandArray[switch]='On' after every update of the text.

      EDIT: The sketches first published were based on an old version (ca. september '15) of the development branch, which is no longer available. Updated the sketches to Version 1.6

      posted in My Project
      fleinze
      fleinze
    • RE: Pulse Powermeter, set to the same value as real power meter?

      I updated the pulse value in the domoticz.db file with an external database editor, then restarted the sensor as it requests the pulse count from domoticz on startup.
      But there should be a better way...

      posted in Domoticz
      fleinze
      fleinze
    • RE: first attempt, 2 Dallas temp sensors on 1 node. Unstable sending.

      What sketch do you use?
      With the provided example it is usual that only one sensor updates. this happens when the temperature of the other sensor did not change.
      but the the repeated line read: 1-1-0 s=1,c=0,t=6,pt=0,l=0,sg=0: seams troubling. This is the presentation message of a temperature sensor at node 1, child id 1 and it is received by your node? Also, this should only be sent after reboot.

      posted in General Discussion
      fleinze
      fleinze
    • RE: Nubie help please

      Hi,

      this message translates to:
      106-106-0: sender of message - last node (when relaying) - destination (0 is gateway)
      s=1: sensor child-id is 1
      c=1: message type presentation
      t=0: subtype temperature
      pt=7: payload-type float
      l=5: length of payload: 5 byte (4 byte float, 1 byte precision)

      other message:
      t=1: subtype humidity

      see also:
      http://www.mysensors.org/download/serial_api_15

      hope this helps

      posted in Troubleshooting
      fleinze
      fleinze
    • RE: Fake DS18B20 sensors.

      @b0rmann well, that is what I thought too. But the chips are definitely labeled "DS18B20" and the device-address also matches a DS18B20.

      posted in General Discussion
      fleinze
      fleinze
    • Fake DS18B20 sensors.

      Hello,

      I just discovered that my last delivery of DS18B20 temperature-sensors seems to be fake. The output values only vary in 0.5C steps. I tried to set the resolution to 12 bit, then read it back and it reads 9 bit. I read the device address and it starts with 0x28 which means, according to dallastemperature.h that it is actually a DS18B20 (with 12-bit resolution).
      This is just a heads up, but maybe someone has experienced similar things?
      I think I should switch to another ebay-supplier because this is not the first counterfeit I received...

      --fleinze

      posted in General Discussion
      fleinze
      fleinze
    • RE: Dallas 1-wire temp only gives 22 degrees C reading. Any suggestions?

      @popunonkok this output looks like you did not set the baud-rate correctly. Please set the baud-rate of the serial monitor to 115200 baud, this is the standard-baud-rate for the mysensors-library.

      posted in General Discussion
      fleinze
      fleinze
    • RE: [security] Introducing signing support to MySensors

      @Anticimex In your original post you said:

      However, the difference is that the gateway will only require signed messages from nodes it knows in turn require signed messages.

      I made pull request 208 to match this behavior in the code:
      https://github.com/mysensors/Arduino/pull/208

      • If node is not a gateway, everything is as always. (1 || x)
      • if node is gateway and the sender requires signed messages, check signature (0 || 1)
      • if node is gateway and the sender does not requires signed messages, do not check signature (0 || 0)
        please consider adding this.
      posted in Development
      fleinze
      fleinze
    • RE: [security] Introducing signing support to MySensors

      @Anticimex
      Ok, I built the node with MySigningAtsha204Soft signer(false); so it does not require signing and the gateway with MySigningAtsha204Soft signer;
      -> no sign error.
      How do I correctly build a node that does not sign in a mixed network (signing and non-signing nodes mixed)?

      posted in Development
      fleinze
      fleinze
    • RE: [security] Introducing signing support to MySensors

      @Anticimex I tried to make it work:

      • took a fresh copy of the development branch
      • activated signing in MyConfig.h
      • flashed the ClearEepromConfig sketch to both the test-gateway and the test-node.
      • built the gateway with MySigningAtsha204Soft signer; (requires signing by default)
      • built the node with MySigningNone signer;

      Still got the no sign message from the gateway...
      Please have a look at this.

      posted in Development
      fleinze
      fleinze
    • RE: [security] Introducing signing support to MySensors

      @Anticimex If I do so, this is the output of the Gateway:

      0;0;3;0;9;gateway started, id=0, parent=0, distance=0
      0;0;3;0;14;Gateway startup complete.
      0;0;3;0;9;no sign
      0;0;3;0;9;no sign
      0;0;3;0;9;no sign
      0;0;3;0;9;no sign
      0;0;3;0;9;read: 2-2-0 s=0,c=0,t=6,pt=0,l=0,sg=0:
      2;0;0;0;6;
      0;0;3;0;9;read: 2-2-0 s=1,c=0,t=30,pt=0,l=0,sg=0:
      2;1;0;0;30;
      0;0;3;0;9;no sign
      0;0;3;0;9;no sign
      0;0;3;0;9;no sign
      

      I tried to compile the node with deactivated signing feature and also with MySigningNone.
      The messages get rejected because in MySensor.cpp line 570 (developement branch) it is not checked if the sender requires signing:

      	if (signer.requestSignatures() && msg.destination == nc.nodeId && mGetLength(msg) && !mGetAck(msg) &&
      		(mGetCommand(msg) != C_INTERNAL ||
      		 (msg.type != I_GET_NONCE_RESPONSE && msg.type != I_GET_NONCE && msg.type != I_REQUEST_SIGNING &&
      		  msg.type != I_ID_REQUEST && msg.type != I_ID_RESPONSE &&
      		  msg.type != I_FIND_PARENT && msg.type != I_FIND_PARENT_RESPONSE)))
      

      My thought is that if I have a mixed network (signing and non-signing nodes) for some sensors I do not need signing (i.e. temperature-sensors). But if I have a button sensor that can actually switch something on or off (via the controller), it would be a security benefit if the messages from the sensor to the gateway are signed.

      posted in Development
      fleinze
      fleinze
    • RE: [security] Introducing signing support to MySensors

      👍 The change only effects gateways. I will put a pull request, thx.

      posted in Development
      fleinze
      fleinze
    • RE: MyController.org

      @jkandasa said:

      How often node sends battery percentage?

      That depends on your sketch. I update battery every hour, but only if there are changes.

      posted in MyController.org
      fleinze
      fleinze
    • RE: [security] Introducing signing support to MySensors

      @Anticimex
      I think I may have found a bug in the code:
      I wanted to build a gateway that accepts both signed and unsigned messages. For this I used MySigningAtsha204Soft signer(false);.
      Now the gateway did accept unsigned messages, but also all messages sent to the gateway by another node with signing where unsigned.
      After changing this line in MySensor.cpp:

      if (signer.requestSignatures() && DO_SIGN(msg.sender))
      

      to

      if (signer.requestSignatures() || DO_SIGN(msg.sender))
      

      it worked as I wanted it. The gateway accepts unsigned messages from nodes but if a node expects signed messages, the messages to the gateway are also signed.
      This line means that the gateway requests signing from the node if he always requests signing or if the node requests signing.
      What do you think?

      posted in Development
      fleinze
      fleinze
    • RE: My controller-less mysensors temperature logger

      @AWI: No, I use hardware SPI. I just changed the CE and CSN-pins.

      posted in My Project
      fleinze
      fleinze
    • RE: Random Sensor Readings

      @diggs: This is definitely the sensor sending zero degree. I think a digital reading of zero also corresponds to 0 degree C.

      posted in General Discussion
      fleinze
      fleinze
    • RE: Light Switch UK 240v

      If you are talking about switches connected like this (pic from wikipedia):
      https://upload.wikimedia.org/wikipedia/commons/9/9d/Light_Switch_Chain.png
      You can connect a relay like this:
      Drawing.png
      I would suggest a bistable relay so it doesn't switch your lights on/off when your MySensor fails.

      posted in General Discussion
      fleinze
      fleinze
    • RE: How Can I Add the NRF24L01 ratio to the 2-wire Temp Probe Sketch

      Hi @Newzwaver!
      please consider using using the code-feature of the forum, because it makes the code much more readable.
      You still had a lot of code from the dallastemp-example in your code which is not needed in you case. I tried to clean it up for you, but I did

      #include <MySensor.h>
      #include <SPI.h>
      
      #define THERMISTORPIN A0
      #define THERMISTORNOMINAL 10000
      #define TEMPERATURENOMINAL 25
      #define NUMSAMPLES 5
      #define BCOEFFICIENT 3950
      #define SERIESRESISTOR 10000
      
      const unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
      
      MySensor gw;
      
      // Initialize temperature message
      MyMessage msg(0,V_TEMP);
      
      int samples[NUMSAMPLES];
      
      void setup(void) {
      
        pinMode(THERMISTORPIN, INPUT);
        analogReference(EXTERNAL);
      
        // Startup and initialize MySensors library. Set callback for incoming messages.
        gw.begin();
      
        // Send the sketch version information to the gateway and Controller
        gw.sendSketchInfo("Temperature Sensor", "1.1");
      
        // Present all sensors to controller
        gw.present(0, S_TEMP);
      }
      
      void loop(void) {
        // Process incoming messages (like config from server)
        gw.process();
      
        float average;
      
        // take N samples in a row, with a slight delay
        for (uint8_t i=0; i< NUMSAMPLES; i++) {
          samples[i] = analogRead(THERMISTORPIN);
          delay(10);
        }
        // average all the samples out
        average = 0;
        for (uint8_t i=0; i< NUMSAMPLES; i++) {
          average += samples[i];
        }
        average /= NUMSAMPLES;
      
        Serial.print("Average analog reading ");
        Serial.println(average);
      
        // convert the value to resistance
        average = 1023 / average - 1;
        average = SERIESRESISTOR / average;
        Serial.print("Thermistor resistance ");
        Serial.println(average);
      
        float temperature;
        temperature = average / THERMISTORNOMINAL; // (R/Ro)
        temperature = log(temperature); // ln(R/Ro)
        temperature /= BCOEFFICIENT; // 1/B * ln(R/Ro)
        temperature += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
        temperature = 1.0 / temperature; // Invert
        temperature -= 258.95; // convert to C
      
        Serial.print("Temperature ");
        Serial.print(temperature);
        Serial.println(" *C");
        // Send in the new temperature
        gw.send(msg.setSensor(0).set(temperature,1));
        // delay(1000);
        gw.sleep(SLEEP_TIME);
      }
      

      The original sketch is programmed to present a number of sensors, hence the for loop before gw.present(). You need just one sensor so you can present it at any child-ID (i.e. child-ID 0). The way the for loop was written, gw.present() was never executed. Also when sending the data you sent it as child-ID i. i was set in the last for-loop to 5.
      Try this, it should work.

      posted in Development
      fleinze
      fleinze
    • RE: software AES encryption for NRF24

      Wow, thank you all for your overwhelming feedback!
      @Anticimex: in your first reply you asked about routing. This is not a problem, as all nodes share the same encryption key and the whole packet is decrypted by any relay node, handled and re-encrypted. As the relay node changes the first byte of data, some extra entropy is added as well.
      I decided to encrypt the whole packets because AES has 16byte block size which works good with the 32byte size limit of the NRF-packets. Just encrypting the payload on the other hand would limit the payload-size to 16bytes.

      I also took a look at the ATAES132-chip. The chip offers AES-CCM for encryption and authentification. Using the DECRYPT command on the chip we would need to provide a valid 16-byte MAC-key (which is calculated using the encrypted data and other authenticate-only data bytes). If we don't want to change the protocol to add encrypted MAC-exchange for each packet this is not an option.
      The chip also offers a LEGACY-command which is supposed to be used for encryption and decryption. Normally encryption and decryption are different operations, so I still need to find out what the LEGACY-command does.

      posted in Development
      fleinze
      fleinze
    • software AES encryption for NRF24

      Hey there!

      I really wanted my over-the-air data to be encrypted. As I have a powermeter sensor, I basically broadcast detailed energy usage-statistics, which is a bit more privat than temperatures.
      The encryption is done with a copy of the MyTransportNRF24.h library. This copy is named MyTransportNRF24ENC.h All the data that is sent and received is encrypted respectively decrypted.
      Check it out:
      https://github.com/fleinze/MySensors/tree/Encryption/libraries/MySensors
      To use it you need to replace the MyTransportNRF24.h with MyTransportNRF24ENC.h and the MyTransportNRF24-constructor with MyTransportNRF24ENC.
      If you want to try it yourself please download all files, because it is based on a fork I use.
      For encryption the AES-library of spaniakos is used:
      https://github.com/spaniakos/AES

      The encryption uses an additional 3400 bytes of flash, so it could get a bit tight for an ethernet-gateway.

      This encryption is a all-or-nothing thing. You can't mix encrypted and unencrypted nodes. OTA-update is not possible with this, because the bootloader expects unencrypted messages.

      Identical messages create identical encrypted messages. To prevent a replay attack you need to use message signing.

      posted in Development
      fleinze
      fleinze
    • RE: My controller-less mysensors temperature logger

      Here are the Fotos
      First page, containing most informations
      DSC_1005.jpg
      Just the local DHT-Sensor
      DSC_1006.jpg
      Like first page, but less information and bigger font:
      DSC_1007.jpg
      Local temperature-Sensor plus first MySensor:
      DSC_1008.jpg
      All MySensors-informations on one page: temperature-reading, battery level and last update:
      DSC_1009.jpg
      This one is tricky: it reads the last 128 values from SD-Card and displays a diagram. Actually very slow and nearly unsuable 😞
      DSC_1010.jpg
      This page is for setting the RTC
      DSC_1011.jpg
      Here is the hardware-configuration. Each hardware-entry can be deactivated and restarted after errors. Deactivating the nrf actually causes a reboot with deactivated MySensors.
      DSC_1012.jpg

      It is true that the fonts use a lot of progmem, especially the big types. But I didn't like the look of the adafruit-library-font.

      posted in My Project
      fleinze
      fleinze
    • RE: How Can I Add the NRF24L01 ratio to the 2-wire Temp Probe Sketch

      To initialize the radio and the sensor (in setup):

      gw.begin();
      gw.sendSketchInfo("2-Wire Temperature Sensor", "1.0");
      gw.present(ID_S_TEMP, S_TEMP);//child ID 0
      

      to send the temperature (in loop):

      gw.send(msg.setSensor(ID_S_TEMP).set(temperature, 1));
      

      to save energy use gw.sleep(sleeptime) instead of delay(sleeptime).

      How do you wire the sensors? What do you wire on the external reference pin?

      posted in Development
      fleinze
      fleinze
    • RE: My controller-less mysensors temperature logger

      I will post some pictures soon (hope tomorrow).

      posted in My Project
      fleinze
      fleinze
    • RE: Energy harvester

      What chip do you use for the solar energy harvester board?

      posted in My Project
      fleinze
      fleinze
    • RE: ESP8266 WiFi gateway port for MySensors

      @DrJeff
      I remember that there was an error in the boardmanager-package for MacOS. You need to change the file-permissions to executable:

      sudo chmod +x ~/Library/Arduino15/packages/esp8266/tools/esptool/0.4.4/esptool 
      
      posted in Development
      fleinze
      fleinze
    • RE: Low Power Temperature Sensor

      The problem with the DS18B20 is that it is rated for a minimum voltage of 3.0V. It works below that, but the error might be bigger.
      There is a good article about that here:
      http://openenergymonitor.org/emon/node/2331
      On the other hand my sensor with a DS18B20 works for 4 months now with a coin-cell battery.
      The good thing of the DS18B20 is that it is widely available and really cheap.
      The Sensbender micro has a temperature/humidity chip (Si7021) that is rated 1.9 to 3.6 V.
      This chip is also available as a breakout board on ebay. I did not try it yet but I think this would be the best solution for battery powered temperature-sensors.

      posted in Hardware
      fleinze
      fleinze
    • RE: Duplicate Sensors

      I think you could prevent them from coming back when you disable "Accept new Hardware Devices" in the settings-section.
      I habe a similar issue with a power-meter sensor. From time to time a new device appears which is never updated.

      posted in Domoticz
      fleinze
      fleinze
    • RE: My controller-less mysensors temperature logger

      PS: The program was written for library-version 1.4. For 1.5 there are some minor changes necessary in the MySensors Constructor and the begin-statement.

      posted in My Project
      fleinze
      fleinze
    • NRF24 Channel and Datarate in the MyTransportNRF24-constructor

      Hi,
      I am missing the possibility to select a different channel without editing MyConfig.h. This comes in handy when I want to test some features in a test-system without impairing the main system.
      In Library version 1.4 it was possible in the begin-statement of MySensors.h.
      With the new architecture I think the MyTransportNRF24-constructor would be a good place for this. The new constructor would look like:

      MyTransportNRF24(uint8_t ce, uint8_t cs, uint8_t paLevel, uint8_t channel, rf24_datarate_e datarate);
      

      I made pull-request on github because I think this is a good idee.

      posted in Feature Requests
      fleinze
      fleinze
    • RE: Scrolling Text sensor node with new V_TEXT

      Wow, I so want to build this!

      posted in My Project
      fleinze
      fleinze
    • RE: gw.sleep isn't very accurate on a Pro Mini 3.3V (8Mhz)

      I noticed the same issue. My programmed sleep-time is 5 min, but the sensors actually sleeps for about 5:25. First I thought it has to do with the 8s-cycle, but the explaination of @tbowmo seems to be the answer.
      Thank you!

      posted in Troubleshooting
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      @TheoL: The step-up regulator will most likely drain your battery very quickly. It uses a lot of current in "standby-mode" (when Arduino is powered down)!

      You can power an Arduino and most sensors directly from battery but you need to disable BOD (brown-out-detection). To do this you need an programmer ("Arduino as ISP"-sketch is sufficient) and set the extended-fuse to 0x07. This can be done with the Arduino-IDE, but you need to edit the boards.txt file.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      Kind of. I used a different Arduino and now it works.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      That depends: Does the step-up just feed the measurement or also the arduino?
      Can you post schematics?

      As long as you stay below 20mA you can use the digital pins to power everything.

      Be aware that a step-up regulator has low efficency at low currents, so it is possible that it actually shortens battery life instead of increasing it.

      posted in My Project
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      I think you can just use a arduino-pin to power the soil sensor and the battery power measurement.
      I did this with the battery power measurement even if it only saves about 2uA, probably in the magnitude of the self-discharge rate.

      posted in My Project
      fleinze
      fleinze
    • RE: Raspbery PI + nrf24 (gpio) not work Domoticz Temp+humanidy PLS HELP

      I am a domoticz user, but I have a serial gateway and did not try a direct gateway.
      But I am sure your hardware-configuration is wrong.
      You need to delete the entries no. 5 and 3 and add a "MySensors Gateway USB" with the serial port "/dev/ttyMySensorsGateway".
      The actual sensors are not configured in the hardware-setup. If domoticz receives a reading from a new sensor, you can find the sensor in the devices-section.

      If you are a beginner, I strongly recommend to start with a serial gateway!

      posted in Domoticz
      fleinze
      fleinze
    • RE: coin-cell (CR2032) powered temperature sensor

      Just a quick Update on my coin-cell sensors:
      I still did not figure out why one sensor did not work because I lack of the needed measurement-equipment 😞

      But I figured out something else: The voltage of a CR2032 battery has a very strong temperature-dependence. So for calculating the battery-level I probably need to calculate a temperature-normalized voltage-value.

      posted in My Project
      fleinze
      fleinze
    • RE: id request fails

      I had a similar problem which was solved after I added a capacitor to the gateway.

      posted in Troubleshooting
      fleinze
      fleinze
    • RE: Weather and Forecast Display for Swedish FHEM users

      This is so great! Thank you!

      posted in My Project
      fleinze
      fleinze
    • coin-cell (CR2032) powered temperature sensor

      Hi!

      I would like to share my experience with coin-cell (CR2032) powered temperature sensors:

      DSC_0970.jpg

      DSC_0971.jpg

      The reason for my use of a CR2032 coin cell is that I am really bad at building cases. So I wanted a sensor that will fit into a kinder-surprise egg.

      To maximize battery life I did some modifications to the pro micro clones:

      • I removed all the leds
      • and also the 3.3v-regulator
      • I used a digital pin for the voltage divider so I can turn the divider off
      • I changed the efuse value to 0x07 (BOD off)

      For easier connections I use digital pins to provide the DS18B20 temperature sensor with VCC and GND. I also got rid of the 4k7 resistor by using a modified version of the onewire.h library which uses the internal pullup instead.

      Temperature is transmitted every 5 minutes and battery level every hour.

      For the battery level I used software bounderies: 3.3V is 100%, 2.6V is 0%.

      If anyone is interested, here is the code. It is based on the old example sketch.

      #include <MySensor.h>
      #include <SPI.h>
      #include <DallasTemperature.h>
      #include <OneWire.h>
      
      #define ONE_WIRE_BUS 4 // Pin where dallase sensor is connected
      #define ONE_WIRE_GND 5
      #define ONE_WIRE_VCC 3
      #define BATT_IN_PIN A0
      #define BATT_VCC_PIN 6
      #define MAX_ATTACHED_DS18B20 16
      
      #define SLEEP_TIME 300000  // Sleep time between reads (in milliseconds)
      #define BATT_TIME 12  //when also BATT-LEVEL is reported
      
      #define BATT_100 3.3
      #define BATT_0 2.6
      
      OneWire oneWire(ONE_WIRE_BUS);
      DallasTemperature sensors(&oneWire);
      MySensor gw;
      float lastTemperature[MAX_ATTACHED_DS18B20];
      uint8_t numSensors = 0;
      boolean receivedConfig = false;
      boolean metric = true;
      // Initialize temperature message
      MyMessage msg(0, V_TEMP);
      uint8_t battReport = 0;
      int oldvalue = 0;
      
      void setup()
      {
        // Startup OneWire
      #ifdef ONE_WIRE_VCC
        pinMode(ONE_WIRE_VCC, OUTPUT);
        digitalWrite(ONE_WIRE_VCC, HIGH);
      #endif
      #ifdef ONE_WIRE_GND
        pinMode(ONE_WIRE_GND, OUTPUT);
        digitalWrite(ONE_WIRE_GND, LOW);
      #endif
      
        analogReference(INTERNAL);
        pinMode(BATT_IN_PIN, INPUT);
        pinMode(BATT_VCC_PIN, OUTPUT);
        digitalWrite(BATT_VCC_PIN, LOW);
      
        sensors.begin();
      
        // Startup and initialize MySensors library. Set callback for incoming messages.
        gw.begin();
      
        // Send the sketch version information to the gateway and Controller
        gw.sendSketchInfo("Temperature Sensor", "1.0");
      
        // Fetch the number of attached temperature sensors
        numSensors = sensors.getDeviceCount();
      
        sensors.setWaitForConversion(false);//saves a few mAs per read :-) to debug
      
        // Present all sensors to controller
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          gw.present(i, S_TEMP);
        }
      }
      
      
      void loop()
      {
        // Process incoming messages (like config from server)
        //gw.process();
      
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
      
        gw.sleep(750);//wait for conversion in sleep mode
      
        // Read temperatures and send them to controller
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
      
          // Fetch and round temperature to one decimal
          float temperature = static_cast<float>(static_cast<int>((gw.getConfig().isMetric ? sensors.getTempCByIndex(i) : sensors.getTempFByIndex(i)) * 10.)) / 10.;
      
          // Only send data if temperature has changed and no error
          if (lastTemperature[i] != temperature && temperature != -127.00) {
      
            // Send in the new temperature
            gw.send(msg.setSensor(i).set(temperature, 1));
            lastTemperature[i] = temperature;
          }
        }
        if (++battReport == BATT_TIME) {
          digitalWrite(BATT_VCC_PIN, HIGH);
          delay(1);
          int value = analogRead(BATT_IN_PIN);
          digitalWrite(BATT_VCC_PIN, LOW);
          if (value != oldvalue)
          {
            int percent = (( value * 3.36e-3) - 2.6) / (3.3 - 2.6) * 100;
            percent = (percent > 100) ? 100 : percent;
            percent = (percent < 0) ? 0 : percent;
            gw.sendBatteryLevel(percent);
          }
          oldvalue = value;
          battReport = 0;
        }
        gw.sleep(SLEEP_TIME);//wake on interrupt or after sleep-time
      }
      

      My experience so far:
      On the good side: the first sensor I built started operation on May 23 (about 3 months ago) and is still working great with the same coin cell. I first hoped for a month or two because of the small capacity of a CR2032 coin cell, so my expectation is already exceeded.

      On the bad side: Some other sensors I built later had problems. They worked well with the fresh battery but stopped working after a day or two. After this time they went into a boot loop (serial monitor reads "sensor started, id ..." over and over again) so apparently the startup of the radio somehow triggers a reboot.
      As a modification to prevent this I resoldered the input capacitor of the raw-pin (which is unused) directly to the radio.
      For most sensors this worked fine.
      But one sensor did keep rebooting. I had to change it to a 2xAA-powered sensor. I later used the same CR2032 coin cell, which powered a reboot loop for about 24 hours to power another, newly built sensor and it worked on that one.

      I don't know what the reason for this is, but it has to have something to do with the voltage drop made by the radio. Either some radios are bad and drawing a higher current or some of the pro micro clones are bad and maybe not accepting the changed efuse values.

      Has anyone had similar issues? Are there counterfeit atmega328 around which do not work up to specifications?

      posted in My Project
      fleinze
      fleinze
    • My controller-less mysensors temperature logger

      Hi!

      I built a mysensors-datalogger that does not need a controller. The reason for this is that I wanted to log some temperature-data at my office which has a strict IT-security policy and would not allow any network based controller like rasperry pi or vera.

      This is what it looks like:
      DSC_0945 Kopie.jpg

      I used the following hardware:

      • Arduino Mega 2560 clone (atmega328 has not enough flash for this project)
      • oled-display based on sh1106 chipset
      • rtc based on DS1302 (would not recommend, but had this one available)
      • micro-SD breakout board
      • NRF24L01 module
      • DHT22 temperature and humidity senosr
      • DS18B20 temperature sensor (waterproof)
      • some buttons

      It is possible to deactivate most of the hardware-pieces in the software. If the RTC has an error or is deactivated by hand it falls back to software RTC.
      For powering the NRF24L01 I used the 3.3V regulator of the micro-SD breakout as the mega2560 has a very weak regulator.

      Basically the software continuously fetches the onboard sensors and waits for radio signals. Every 5 minutes it writes all available values to the SD-Card.

      The mysensors-support is very basic. Currently it only supports up to 6 temperature sensors with one temperature and battery reading each.

      Here is the code:

      /*
       Weatherstation-"Gateway" (Stand-alone)
      
       Created by Florian Heinze
      
       This program is free software; you can redistribute it and/or
       modify it under the terms of the GNU General Public License
       version 2 as published by the Free Software Foundation.
      */
      
      
      #include <U8glib.h>
      #include <SPI.h>
      #include "SD.h"
      #include <MySensor.h>
      #include <MyGateway.h>
      #include <stdarg.h>
      #include <DHT.h>
      #include <DallasTemperature.h>
      #include <OneWire.h>
      #include <Time.h>
      #include <DS1302RTC.h>
      #include <EEPROM.h>
      
      const uint8_t ARROW[] U8G_PROGMEM = {
        B00000000,
        B00001100,
        B00000110,
        B11111111,
        B11111111,
        B00000110,
        B00001100,
        B00000000
      };
      
      /*
       * PIN-definitions
       */
      const int DHT_BUS = A9;
      
      const int ONE_WIRE_BUS = 25;
      const int ONE_WIRE_VCC = 23;
      const int ONE_WIRE_GND = 27;
      
      const int NRF_CE_PIN = 30;
      const int NRF_CS_PIN = 36;
      
      const int SD_CS_PIN = 12;
      const int SD_MISO_PIN = 9;
      const int SD_MOSI_PIN = 10;
      const int SD_SCK_PIN = 11;
      
      const int DISP_CS_PIN = A4;
      const int DISP_DC_PIN = A3;
      const int DISP_RES_PIN = A2;
      const int DISP_SCK_PIN = A0;
      const int DISP_MOSI_PIN = A1;
      
      const int RTC_SCK_PIN = 16;
      const int RTC_DAT_PIN = 15;
      const int RTC_RST_PIN = 14;
      
      const int BUTTON_RIGHT_PIN = 4;
      const int BUTTON_LEFT_PIN = 5;
      const int BUTTON_UP_PIN = 6;
      const int BUTTON_DOWN_PIN = 3;
      const int BUTTON_ENTER_PIN = 7;
      
      //Variables for buttons
      boolean right = false;
      boolean left = false;
      boolean up = false;
      boolean down = false;
      boolean enter = false;
      boolean lastright = false;
      boolean lastleft = false;
      boolean lastup = false;
      boolean lastdown = false;
      boolean lastenter = false;
      
      const unsigned long DEBOUNCE_DELAY = 10;
      unsigned long debouncetime = 0;
      unsigned long lastSDWrite = 0;
      
      //Channel for RF
      const int RF24_CUST_CHANNEL = 50;
      
      //EEPROM-addreses. start at 512 so it doesnt collide with mysensors.
      const int START_EEPROM_ADR = 512;
      const int DHT_EEPROM_ADR = START_EEPROM_ADR;
      const int ONEWIRE_EEPROM_ADR = START_EEPROM_ADR + 1;
      const int RTC_EEPROM_ADR = START_EEPROM_ADR + 2;
      const int NRF_EEPROM_ADR = START_EEPROM_ADR + 3;
      const int SD_EEPROM_ADR = START_EEPROM_ADR + 4;
      
      //Filenames
      #define MYS_LOG "myslog.txt"
      #define DATA_LOG "datalog.txt"
      
      const unsigned int WRITE_MINUTE = 5;
      
      //status of hardware
      typedef enum {OFF = 0, ERR, ON} hw_stat_t;
      
      hw_stat_t dht_stat;
      hw_stat_t onewire_stat;
      hw_stat_t rtc_stat;
      hw_stat_t nrf_stat; //no ERR state
      hw_stat_t sd_stat;
      
      //used for rtc
      time_t t = 0;
      boolean clock_set = false;
      enum {DAY, MONTH, YEAR, HOUR, MINUTE, SECOND} set_digit = DAY;
      #define LEAP_YEAR(Y)     ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
      static  const uint8_t monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // API starts months from 1, this array starts from 0
      
      //state of HW-page
      enum {DHT_22 = 0, DS18B22, RTC, NRF, SD_CARD} hw_page_stat = DHT_22;
      
      //state of display
      enum {PAGE1, PAGE2, PAGE3, PAGE4, PAGE5, DIAGRAM, CLOCK, HW_SET} dispstat = PAGE1;
      
      //max number of mysensors
      const int MYS_MAX_SENSORS = 6;
      
      //variables for sensors
      long lastDHTTime;
      long lastOnewireTime;
      float tempDHT = 0;
      float humDHT = 0;
      float tempOnewire = 0;
      float tempMyS[MYS_MAX_SENSORS] = {0};//temp of mysensors
      time_t lastReadMyS[MYS_MAX_SENSORS] = {0};//last time the mysensors are read
      uint8_t battMyS[MYS_MAX_SENSORS] = {0};//battery of mysensors
      
      //used for the diagram
      float diagram[128];
      boolean diagramRead = false;
      boolean diagramScroll = false;
      boolean linesUpdate = false;
      unsigned long diagramStart = 1;
      unsigned long lines = 0;
      uint8_t numDiagram = 1;
      const int BOT_PXL = 64;
      const int TOP_PXL = 0;
      boolean dispOnewire = false;
      
      //objects for hardware: temperature-sensors
      DHT dht;
      OneWire oneWire(ONE_WIRE_BUS);
      DallasTemperature sensors(&oneWire);
      
      //rtc
      DS1302RTC rtc(RTC_RST_PIN, RTC_DAT_PIN, RTC_SCK_PIN);
      
      //display
      U8GLIB_SH1106_128X64 u8g(DISP_SCK_PIN, DISP_MOSI_PIN, DISP_CS_PIN, DISP_DC_PIN, DISP_RES_PIN);
      
      //mysensors
      MyGateway gw(NRF_CE_PIN, NRF_CS_PIN);
      
      //setup-routine of dht
      void setup_dht() {
        dht.setup(DHT_BUS);
        lastDHTTime = millis();
        if (dht.getStatus() == DHT::ERROR_NONE) dht_stat = ON; //check for error
        else dht_stat = ERR;
      }
      
      //setup routine of onewire
      void setup_onewire() {
        sensors.begin();
        sensors.setWaitForConversion(false);
        sensors.requestTemperatures();
      
        if (sensors.getDeviceCount() == 1) onewire_stat = ON; //check for error
        else onewire_stat = ERR;
      
        lastOnewireTime = millis();
      }
      
      //setup rtc
      void setup_rtc() {
        if (rtc.get() == 0) //check for error
        {
          rtc_stat = ERR;
        }
        else
        {
          rtc_stat = ON;
          setSyncProvider(rtc.get); //rtc is set up as sync provider. normal time comes from internal clock.
        }
      }
      
      //setup for sd-card
      void setup_sd() {
        if (SD.begin(SD_CS_PIN, SD_MOSI_PIN, SD_MISO_PIN, SD_SCK_PIN)) {//start and check for error
          sd_stat = ON;
          if (!SD.exists(DATA_LOG)) {//if the file does not exist, write header
            File dataFile = SD.open(DATA_LOG, FILE_WRITE);
            if (dataFile) {
              dataFile.print("time,temp-dht,humidity-dht,temp-onewire");
              for (int i = 1; i <= MYS_MAX_SENSORS; i++) {
                dataFile.print(",temp");
                dataFile.print(i);
              }
              for (int i = 1; i <= MYS_MAX_SENSORS; i++) {
                dataFile.print(",batt");
                dataFile.print(i);
              }
              dataFile.print("\n");
              dataFile.close();
            }
          }
        }
        else
        {
          sd_stat = ERR;
        }
      }
      
      //reads the last line of the datalog-file to initialize the mysensor-values with the last values after reset.
      void readLastMyS() {
        File dataFile = SD.open(DATA_LOG, FILE_READ);
        char buf[106];
        char *str, *p;
      
        if (dataFile) { //11 date 6 time 6 dhttemp 6 dhthum 6 onewire 6*6 onewire 6*4 onewire = 101 max 56 min
          unsigned long filesize = dataFile.size();
          dataFile.seek(filesize - 106);
          dataFile.find("\n");
          dataFile.readBytesUntil('\n', buf, 105); //read a line
          uint8_t j = 0;
          for (str = strtok_r(buf, ",", &p);                // goto last entry before MyS-Data
               str && j < 3;
               str = strtok_r(NULL, ",", &p)
              ) {
            j++;
          }
          for (int i = 0; i < MYS_MAX_SENSORS; i++) { //read MyS-temps
            str = strtok_r(NULL, ",", &p);
            if (str) {
              tempMyS[i] = atof(str);
            }
            else break;
          }
          for (int i = 0; i < MYS_MAX_SENSORS; i++) { //read MyS batts
            str = strtok_r(NULL, ",", &p);
            if (str) {
              battMyS[i] = atoi(str);
            }
            else break;
          }
        }
      }
      
      void(* reset_func) (void) = 0; //declare reset function @ address 0
      
      void setup() {
        pinMode(BUTTON_RIGHT_PIN, INPUT_PULLUP);
        pinMode(BUTTON_LEFT_PIN, INPUT_PULLUP);
        pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
        pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
        pinMode(BUTTON_ENTER_PIN, INPUT_PULLUP);
      
        LoadParameters(); //load hw-state from eeprom
      
        if (digitalRead(BUTTON_ENTER_PIN) == LOW) nrf_stat = OFF; //to power up without NRF24, hold down enter button on startup (no error state)
      
        //startup hardware
        pinMode(ONE_WIRE_GND, OUTPUT);
        pinMode(ONE_WIRE_VCC, OUTPUT);
        digitalWrite(ONE_WIRE_GND, LOW);
        digitalWrite(ONE_WIRE_VCC, HIGH);
        delay(10);//let the sensor power up.
      
        if (onewire_stat != OFF)
        {
          setup_onewire();
        }
      
        if (dht_stat != OFF)
        {
          setup_dht();
        }
      
        if (rtc_stat != OFF)
        {
          setup_rtc();
        }
      
        if (nrf_stat != OFF)//no ERR
        {
          gw.begin(RF24_PA_MAX, RF24_CUST_CHANNEL, RF24_DATARATE, incomingRadio);
        }
        else
        {
          Serial.begin(115200);
        }
      
        if (sd_stat != OFF) {
          setup_sd();
        }
      
        if (sd_stat == ON) { //read last MyS-Data from SD-card
          readLastMyS();
        }
      }
      
      
      void loop() {
        if ( (millis() - lastDHTTime > dht.getMinimumSamplingPeriod()) && (dht_stat == ON) ) //read DHT
        {
          tempDHT = dht.getTemperature();
          humDHT = dht.getHumidity();
          lastDHTTime = millis();
        }
      
        if ( (millis() - lastOnewireTime >= 750) && (onewire_stat == ON) ) //read onewire-sensor
        {
          tempOnewire = sensors.getTempCByIndex(1);
          sensors.requestTemperatures();
          lastOnewireTime = millis();
        }
      
        t = now();//read time
      
        if (nrf_stat != OFF) {//process radio
          gw.processRadioMessage();
        }
      
        updateDisplay();
      
        readButtons();
      
        updateState();//change display states depending on buttons
      
        //write SD
        if (sd_stat == ON && (minute(t) % WRITE_MINUTE == 0) && (millis() - lastSDWrite >= 120000)) {
          writeLogSD();
        }
      }
      
      //read and debounce the buttons
      void readButtons() {
        //inverted for internal pullup
        boolean tempright = !digitalRead(BUTTON_RIGHT_PIN);
        boolean templeft = !digitalRead(BUTTON_LEFT_PIN);
        boolean tempup = !digitalRead(BUTTON_UP_PIN);
        boolean tempdown = !digitalRead(BUTTON_DOWN_PIN);
        boolean tempenter = !digitalRead(BUTTON_ENTER_PIN);
      
        if (right || left || up || down || enter) //any button last pressed
        {
          debouncetime = millis();
        }
        if ( (millis() - debouncetime) > DEBOUNCE_DELAY )
        {
          if (tempright && !lastright) right = tempright;
          if (templeft && !lastleft) left = templeft;
          if (tempup && !lastup) up = tempup;
          if (tempdown && !lastdown) down = tempdown;
          if (tempenter && !lastenter) enter = tempenter;
        }
        else
        {
          right = 0; //right stays high only for one loop
          left = 0;
          up = 0;
          down = 0;
          enter = 0;
        }
        lastright = tempright;
        lastleft = templeft;
        lastup = tempup;
        lastdown = tempdown;
        lastenter = tempenter;
      }
      
      //write line to log-file
      void writeLogSD() {
        File dataFile = SD.open(DATA_LOG, FILE_WRITE);
        if (dataFile) {//"time,temp-dht,humidity-dht,temp-onewire,temp1,temp2,temp3,temp4,temp5,temp6"
          //dataFile.print((float)(t) / 86400 + 25569,6); //excel timestamp
          dataFile.print(day(t) > 9 ? "" : "0");
          dataFile.print(day(t));
          dataFile.print(".");
          dataFile.print(month(t) > 9 ? "" : "0");
          dataFile.print(month(t));
          dataFile.print(".");
          dataFile.print(year(t));
          dataFile.print(" ");
          dataFile.print(hour(t) > 9 ? "" : "0");
          dataFile.print(hour(t));
          dataFile.print(":");
          dataFile.print(minute(t) > 9 ? "" : "0");
          dataFile.print(minute(t));
          dataFile.print(",");
          dataFile.print(tempDHT, 1);
          dataFile.print(",");
          dataFile.print(humDHT, 1);
          dataFile.print(",");
          dataFile.print(tempOnewire, 1);
          for (int i = 0; i < MYS_MAX_SENSORS; i++) {
            dataFile.print(",");
            dataFile.print(tempMyS[i], 1);
          }
          for (int i = 0; i < MYS_MAX_SENSORS; i++) {
            dataFile.print(",");
            dataFile.print(battMyS[i]);
          }
          dataFile.print("\n");
          dataFile.close();
          lastSDWrite = millis();
        }
      }
      
      //returns the number of lines of the logfile
      unsigned long readSDFileLines() {
        unsigned long numLines = 0;
        if (sd_stat != ON) return 0;
        File dataFile = SD.open(DATA_LOG, FILE_READ);
      
        while (dataFile.find("\n")) { //find number of lines
          numLines++;
        }
        dataFile.close();
        return numLines;
      }
      
      //read values from sd-card for the diagramm
      void readTempFromSD(uint8_t numToRead, unsigned long startRecord) {
        char buf[128];
        char *str, *p;
      
        if (sd_stat != ON) return;
      
        File dataFile = SD.open(DATA_LOG, FILE_READ);
      
        for (int i = 0; i < startRecord; i++) {
          dataFile.find("\n");
        }
      
        for (uint8_t i = 0; i < 128; i++) {
          dataFile.readBytesUntil('\n', buf, 127); //read a line
          uint8_t j = 0;
          for (str = strtok_r(buf, ",", &p);        // split using comma
               str && j < numToRead;                               // loop while str is not null an max 5 times
               str = strtok_r(NULL, ",", &p)               // get subsequent tokens
              ) {
            j++;
          }
          if (str) {
            diagram[i] = atof(str);
          }
          else {
            for (; i < 128; i++) {
              diagram[i] = -127;
            }
            break;
          }
        }
        dataFile.close();
      }
      
      //print the diagram
      void printTempDiagram() {
        int maxtemp = (int) ceil(diagram[0]);//start with valid value
        int mintemp = (int) floor(diagram[0]);//start with valid value
        for (int i = 126; i >= 0; i--)
        {
          if (diagram[i] > maxtemp)
          {
            maxtemp = (int) ceil(diagram[i]);
          }
          if (diagram[i] < mintemp && diagram[i] > -127)
          {
            mintemp = (int) floor(diagram[i]);
          }
        }
      
        u8g.setFont(u8g_font_helvB08);
        u8g.setPrintPos(0, TOP_PXL + 8);
        u8g.print(maxtemp); //scale
        u8g.setPrintPos(0, BOT_PXL);
        u8g.print(mintemp); //scale
      
        if (diagramScroll) {
          u8g.setPrintPos(30, BOT_PXL);
          u8g.print("scroll "); //scale
          u8g.print(diagramStart);
        }
      
        u8g.setPrintPos(20, 8);
        if (numDiagram == 1) {
          u8g.print("Temp DHT");
        }
        else if (numDiagram == 2) {
          u8g.print("Hum DHT");
        }
        else if (numDiagram == 3) {
          u8g.print("Temp Onewire");
        }
        else if (numDiagram > 3 && numDiagram <= (3 + MYS_MAX_SENSORS)) {
          u8g.print("Temp MyS ");
          u8g.print(numDiagram - 3);
        }
        else if (numDiagram <= (3 + MYS_MAX_SENSORS * 2)) {
          u8g.print("Batt MyS ");
          u8g.print(numDiagram - 3 - MYS_MAX_SENSORS);
        }
      
        for (int i = 0; i < 128; i++) //print array
        {
          float pxl = (diagram[i] - mintemp) * (BOT_PXL - TOP_PXL) / (-maxtemp + mintemp) + BOT_PXL;
          if (diagram[i] >= mintemp && diagram[i] <= maxtemp) //dont print if out of boundery
          {
            u8g.drawPixel(i, (int)pxl);
          }
        }
      }
      
      //dump the logfile to the serial port
      void dumpFile() {
        if (sd_stat == ON) {
          File dataFile = SD.open(DATA_LOG, FILE_READ);
          if (dataFile) {
            while (dataFile.available()) {
              Serial.write(dataFile.read());
            }
            dataFile.close();
          }
        }
      }
      
      //updates the state-variables depending on pressed buttons
      void updateState() {
        switch (dispstat)
        {
          case PAGE1:
            if (right == true) dispstat = PAGE2;
            if (left == true) dispstat = HW_SET;
            if (enter == true) dumpFile();
            break;
          case PAGE2:
            if (right == true) dispstat = PAGE3;
            if (left == true) dispstat = PAGE1;
            if (up == true || down == true) dispOnewire = !dispOnewire;
            break;
          case PAGE3:
            if (right == true) dispstat = PAGE4;
            if (left == true) dispstat = PAGE2;
            if (up == true || down == true) dispOnewire = !dispOnewire;
            break;
          case PAGE4:
            if (right == true) dispstat = PAGE5;
            if (left == true) dispstat = PAGE3;
            if (up == true || down == true) dispOnewire = !dispOnewire;
            break;
          case PAGE5:
            if (right == true) dispstat = DIAGRAM;
            if (left == true) dispstat = PAGE4;
            break;
          case DIAGRAM:
            if (right == true) {
              if (diagramScroll == false) {
                dispstat = CLOCK;
                linesUpdate = false;
              }
              else {
                if (diagramStart < lines - 256 && lines > 128) {
                  diagramStart += 128;
                }
                else {
                  diagramStart = lines > 128 ? lines - 128 : 1;
                  //Serial.print(diagramStart);
                }
                diagramRead = false;
              }
            }
            else if (left == true) {
              if (diagramScroll == false) {
                dispstat = PAGE5;
                linesUpdate = false;
              }
              else
              {
                if (diagramStart > 128) {
                  diagramStart -= 128;
                }
                else {
                  diagramStart = 1;
                }
                diagramRead = false;
              }
            }
            else if (enter == true) {
              diagramScroll = !diagramScroll;
            }
      
            //unsigned long diagramStart = 0;
            else if (up == true && numDiagram > 1) {
              numDiagram--;
              diagramRead = false;
            }
            else if (down == true && numDiagram < (3 + 2 * MYS_MAX_SENSORS)) {
              numDiagram++;
              diagramRead = false;
            }
            else if (!linesUpdate) {
              lines = readSDFileLines();
              diagramStart = lines - 128;
              linesUpdate = true;
            }
            else if (!diagramRead) {
              //readTempFromSD(numDiagram, diagramStart);
              readTempFromSD(numDiagram, diagramStart);
              diagramRead = true;
            }
            break;
          case CLOCK:
            if (clock_set == false && right == true) dispstat = HW_SET;
            if (clock_set == false && left == true) dispstat = DIAGRAM;
            if (enter == true) clock_set = !clock_set;
            if (clock_set == true) {
              if (left == true) {
                switch (set_digit) {
                  case SECOND:
                    set_digit = MINUTE;
                    break;
                  case MINUTE:
                    set_digit = HOUR;
                    break;
                  case HOUR:
                    set_digit = YEAR;
                    break;
                  case YEAR:
                    set_digit = MONTH;
                    break;
                  case MONTH:
                    set_digit = DAY;
                    break;
                  case DAY:
                    set_digit = SECOND;
                    break;
                }
              }
              else if (right == true) {
                switch (set_digit) {
                  case SECOND:
                    set_digit = DAY;
                    break;
                  case MINUTE:
                    set_digit = SECOND;
                    break;
                  case HOUR:
                    set_digit = MINUTE;
                    break;
                  case YEAR:
                    set_digit = HOUR;
                    break;
                  case MONTH:
                    set_digit = YEAR;
                    break;
                  case DAY:
                    set_digit = MONTH;
                    break;
                }
              }
              if (up == true || down == true) {
                int inc = up - down;
                int d = day(t);
                int m = month(t);
                int y = year(t);
                int h = hour(t);
                int mi = minute(t);
                int s = second(t);
                switch (set_digit) {
                  case SECOND:
                    s += inc;
                    if (s < 0) s = 59;
                    if (s > 59) s = 0;
                    break;
                  case MINUTE:
                    mi += inc;
                    if (mi < 0) mi = 59;
                    if (mi > 59) mi = 0;
                    break;
                  case HOUR:
                    h += inc;
                    if (h < 0) h = 23;
                    if (h > 23) h = 0;
                    break;
                  case YEAR:
                    y += inc;
                    break;
                  case MONTH:
                    m += inc;
                    if (m < 1) m = 12;
                    if (m > 12) m = 1;
                    break;
                  case DAY:
                    d += inc;
                    uint8_t maxday = monthDays[m - 1];
                    if (LEAP_YEAR(y - 1970) && m == 2) maxday = 29;
                    if (d < 1) d = maxday;
                    if (d > maxday) d = 1;
                    break;
                }
      
                //set time
                tmElements_t tm = {s, mi, h, 0, d, m, y - 1970};
                t = makeTime(tm);
                if (rtc_stat == ON) {
                  rtc.set(t);   // set the RTC and the system time to the received value
                }
                setTime(t);
              }
            }
            break;
          case HW_SET:
            if (right == true) dispstat = PAGE1;
            if (left == true) dispstat = CLOCK;
            if (up == true) {
              switch (hw_page_stat) {
                case DHT_22:
                  hw_page_stat = SD_CARD;
                  break;
                case DS18B22:
                  hw_page_stat = DHT_22;
                  break;
                case RTC:
                  hw_page_stat = DS18B22;
                  break;
                case NRF:
                  hw_page_stat = RTC;
                  break;
                case SD_CARD:
                  hw_page_stat = NRF;
                  break;
              }
            }
            if (down == true) {
              switch (hw_page_stat) {
                case DHT_22:
                  hw_page_stat = DS18B22;
                  break;
                case DS18B22:
                  hw_page_stat = RTC;
                  break;
                case RTC:
                  hw_page_stat = NRF;
                  break;
                case NRF:
                  hw_page_stat = SD_CARD;
                  break;
                case SD_CARD:
                  hw_page_stat = DHT_22;
                  break;
              }
            }
            if (enter == true) {
              switch (hw_page_stat) {
                case DHT_22:
                  if (dht_stat == ON) {
                    dht_stat = OFF;
                    tempDHT = 0;
                    humDHT = 0;
                  }
                  else {
                    dht_stat = ON;
                    setup_dht();
                  }
                  break;
                case DS18B22:
                  if (onewire_stat == ON) {
                    onewire_stat = OFF;
                    tempOnewire = 0;
                  }
                  else {
                    onewire_stat = ON;
                    setup_onewire();
                  }
                  break;
                case RTC://TBD
                  if (rtc_stat == ON) {
                    rtc_stat = OFF;
                    setSyncProvider(NULL);
                  }
                  else {
                    rtc_stat = ON;
                    setup_rtc();
                  }
                  break;
                case NRF:
                  if (nrf_stat == ON) {
                    nrf_stat = OFF;
                    SaveParameters();
                    reset_func();
                  }
                  else {
                    nrf_stat = ON;
                    SaveParameters();
                    reset_func();
                  }
                  break;
                case SD_CARD:
                  if (sd_stat == ON) {
                    sd_stat = OFF;
                    SD.end();
                  }
                  else {
                    sd_stat = ON;
                    setup_sd();
                  }
                  break;
              }
              SaveParameters();
            }
            break;
          default:
            break;
        }
      }
      
      //updates the display depending on state-variables
      void updateDisplay() {
        u8g.firstPage();
        do {
          switch (dispstat)
          {
            case PAGE1:
              u8g.setFont(u8g_font_helvB08);
              u8g.setPrintPos(40, 10);
              u8g.print(tempDHT, 1);
              u8g.print("\xb0 C ");
              u8g.print(humDHT, 1);
              u8g.print("%");
              u8g.setPrintPos(40, 20);
              u8g.print(tempOnewire, 1);
              u8g.print("\xb0 C");
              u8g.setPrintPos(40, 30);
              u8g.print(tempMyS[0], 1);
              u8g.print("\xb0 C ");
              u8g.print(tempMyS[1], 1);
              u8g.print("\xb0 C");
              u8g.setPrintPos(40, 40);
              u8g.print(tempMyS[2], 1);
              u8g.print("\xb0 C ");
              u8g.print(tempMyS[3], 1);
              u8g.print("\xb0 C");
              u8g.setPrintPos(0, 60);
              u8g.print(day(t) > 9 ? "" : "0");
              u8g.print(day(t));
              u8g.print(".");
              u8g.print(month(t) > 9 ? "" : "0");
              u8g.print(month(t));
              u8g.print(".");
              u8g.print(year(t));
              u8g.print(" ");
              u8g.print(hour(t) > 9 ? "" : "0");
              u8g.print(hour(t));
              u8g.print(":");
              u8g.print(minute(t) > 9 ? "" : "0");
              u8g.print(minute(t));
              u8g.print(":");
              u8g.print(second(t) > 9 ? "" : "0");
              u8g.print(second(t));
              u8g.setFont(u8g_font_5x7);
              u8g.setPrintPos(0, 10);
              u8g.print("DHT:");
              u8g.setPrintPos(0, 20);
              u8g.print("Dallas:");
              u8g.setPrintPos(0, 30);
              u8g.print("MyS:");
              break;
            case PAGE2:
              u8g.setFont(u8g_font_helvB18);
              u8g.setPrintPos(20, 30);
              u8g.print(dispOnewire ? tempOnewire : tempDHT, 1);
              u8g.print("\xb0 C");
              u8g.setPrintPos(20, 60);
              u8g.print(humDHT, 1);
              u8g.print("%");
              break;
            case PAGE3:
              u8g.setFont(u8g_font_helvB10);
              u8g.setPrintPos(10, 14);
              u8g.print(dispOnewire ? tempOnewire : tempDHT, 1);
              u8g.print("\xb0 C");
              u8g.setPrintPos(74, 14);
              u8g.print(humDHT, 1);
              u8g.print("%");
              u8g.setPrintPos(0, 38);
              u8g.setFont(u8g_font_5x7);
              u8g.print("1 ");
              u8g.setFont(u8g_font_helvB10);
              u8g.print(tempMyS[0], 1);
              u8g.print("\xb0 C ");
              u8g.setPrintPos(64, 38);
              u8g.setFont(u8g_font_5x7);
              u8g.print("2 ");
              u8g.setFont(u8g_font_helvB10);
              u8g.print(tempMyS[1], 1);
              u8g.print("\xb0 C ");
              u8g.setPrintPos(0, 60);
              u8g.setFont(u8g_font_5x7);
              u8g.print("3 ");
              u8g.setFont(u8g_font_helvB10);
              u8g.print(tempMyS[2], 1);
              u8g.print("\xb0 C ");
              u8g.setPrintPos(64, 60);
              u8g.setFont(u8g_font_5x7);
              u8g.print("4 ");
              u8g.setFont(u8g_font_helvB10);
              u8g.print(tempMyS[3], 1);
              u8g.print("\xb0 C ");
              break;
            case PAGE4:
              u8g.setFont(u8g_font_helvB18);
              u8g.setPrintPos(20, 30);
              u8g.print(dispOnewire ? tempOnewire : tempDHT, 1);
              u8g.print("\xb0 C");
              u8g.setPrintPos(20, 60);
              u8g.print(tempMyS[0], 1);
              u8g.print("\xb0 C");
              u8g.setFont(u8g_font_5x7);
              u8g.setPrintPos(0, 30);
              u8g.print("in");
              u8g.setPrintPos(0, 60);
              u8g.print("out");
              break;
            case PAGE5:
              for (uint8_t i = 0; i < MYS_MAX_SENSORS; i++)
              {
                u8g.setFont(u8g_font_helvB08);
                u8g.setPrintPos(0, 10 * (i + 1));
                u8g.print(i + 1);
                u8g.print(":");
                u8g.setPrintPos(10, 10 * (i + 1));
                u8g.print(tempMyS[i], 1);
                u8g.print("\xb0 C");
                u8g.setPrintPos(55, 10 * (i + 1));
                u8g.print(battMyS[i]);
                u8g.print("%");
                u8g.setPrintPos(90, 10 * (i + 1));
                if (lastReadMyS[i] == 0) u8g.print("nie");
                else if (t - lastReadMyS[i] < 60) {
                  u8g.print(t - lastReadMyS[i]);
                  u8g.print("s");
                }
                else if (t - lastReadMyS[i] < 3600) {
                  u8g.print((t - lastReadMyS[i]) / 60, 1);
                  u8g.print("min");
                }
                else {
                  u8g.print((t - lastReadMyS[i]) / 3600, 1);
                  u8g.print("h");
                }
              }
              break;
            case DIAGRAM:
              printTempDiagram();
              break;
            case CLOCK:
              u8g.setFont(u8g_font_helvB08);
              u8g.setPrintPos(14, 40);
              u8g.print(day(t) > 9 ? "" : "0");
              u8g.print(day(t));
              u8g.print(".");
              u8g.print(month(t) > 9 ? "" : "0");
              u8g.print(month(t));
              u8g.print(".");
              u8g.print(year(t));
              u8g.print(" ");
              u8g.print(hour(t) > 9 ? "" : "0");
              u8g.print(hour(t));
              u8g.print(":");
              u8g.print(minute(t) > 9 ? "" : "0");
              u8g.print(minute(t));
              u8g.print(":");
              u8g.print(second(t) > 9 ? "" : "0");
              u8g.print(second(t));
              if (clock_set == true) {
                //u8g.setPrintPos(0,50);
                //u8g.print("set");
                switch (set_digit) {
                  case DAY:
                    u8g.drawFrame(12, 30, 15, 12);
                    break;
                  case MONTH:
                    u8g.drawFrame(27, 30, 15, 12);
                    break;
                  case YEAR:
                    u8g.drawFrame(42, 30, 27, 12);
                    break;
                  case HOUR:
                    u8g.drawFrame(69, 30, 15, 12);
                    break;
                  case MINUTE:
                    u8g.drawFrame(84, 30, 15, 12);
                    break;
                  case SECOND:
                    u8g.drawFrame(99, 30, 15, 12);
                    break;
                }
      
              }
              break;
            case HW_SET:
              u8g.setFont(u8g_font_helvB08);
              u8g.setPrintPos(10, 10);
              u8g.print("DHT");
              u8g.setPrintPos(70, 10);
              if (dht_stat == OFF) u8g.print("OFF");
              if (dht_stat == ON) u8g.print("ON");
              if (dht_stat == ERR) u8g.print("ERR");
              u8g.setPrintPos(10, 20);
              u8g.print("DS18B20");
              u8g.setPrintPos(70, 20);
              if (onewire_stat == OFF) u8g.print("OFF");
              if (onewire_stat == ON) u8g.print("ON");
              if (onewire_stat == ERR) u8g.print("ERR");
              u8g.setPrintPos(10, 30);
              u8g.print("RTC");
              u8g.setPrintPos(70, 30);
              if (rtc_stat == OFF) u8g.print("OFF");
              if (rtc_stat == ON) u8g.print("ON");
              if (rtc_stat == ERR) u8g.print("ERR");
              u8g.setPrintPos(10, 40);
              u8g.print("NRF");
              u8g.setPrintPos(70, 40);
              if (nrf_stat == OFF) u8g.print("OFF");
              if (nrf_stat == ON) u8g.print("ON");
              u8g.setPrintPos(10, 50);
              u8g.print("SD");
              u8g.setPrintPos(70, 50);
              if (sd_stat == OFF) u8g.print("OFF");
              if (sd_stat == ON) u8g.print("ON");
              if (sd_stat == ERR) u8g.print("ERR");
              u8g.drawBitmapP(0, 2 + (hw_page_stat) * 10, 1, 8, ARROW);
              break;
            default:
              break;
          }
        } while ( u8g.nextPage() );
      }
      
      //callback-method called every time something arrives on the radio.
      void incomingRadio(char *message) {
        char *str, *p, *variable;
        uint8_t node = 0;
        uint8_t sensor = 0;
        uint8_t command = 0;
        uint8_t ack = 0;
        uint8_t type = 0;
        uint8_t i = 0;
      
        //log incoming message on SD-card
        if (sd_stat == ON) {
          File dataFile = SD.open(MYS_LOG, FILE_WRITE);
      
          if (dataFile) {
            dataFile.print(day(t) > 9 ? "" : "0");
            dataFile.print(day(t));
            dataFile.print(".");
            dataFile.print(month(t) > 9 ? "" : "0");
            dataFile.print(month(t));
            dataFile.print(".");
            dataFile.print(year(t));
            dataFile.print(" ");
            dataFile.print(hour(t) > 9 ? "" : "0");
            dataFile.print(hour(t));
            dataFile.print(":");
            dataFile.print(minute(t) > 9 ? "" : "0");
            dataFile.print(minute(t));
            dataFile.print(":");
            dataFile.print(second(t) > 9 ? "" : "0");
            dataFile.print(second(t));
            dataFile.print(" ");
            dataFile.print(message);
            dataFile.close();
          }
        }
      
        //process string
        for (str = strtok_r(message, ";", &p);        // split using semicolon
             str && i < 6;                               // loop while str is not null an max 5 times
             str = strtok_r(NULL, ";", &p)               // get subsequent tokens
            ) {
          switch (i) {
            case 0: // Radioid (destination)
              node = atoi(str);
              break;
            case 1: // Childid
              sensor = atoi(str);
              break;
            case 2: // Message type
              command = atoi(str);
              break;
            case 3: // Should we request ack from destination?
              ack = atoi(str);
              break;
            case 4: // Data type
              type = atoi(str);
              break;
            case 5: // Variable value
              variable = str;
              break;
          }
          i++;
        }
        if ( (node <= MYS_MAX_SENSORS) && (command == 1) && (type == 0) ) { //if temp-message: write to array
          tempMyS[node - 1] = atof(variable);
          lastReadMyS[node - 1] = t;
        }
        if ( (node <= MYS_MAX_SENSORS) && (command == 3) && (type == 0) ) { //battery
          battMyS[node - 1] = atoi(variable);
        }
      }
      
      //load parameters from eeprom (hardware-states)
      void LoadParameters() {
        dht_stat = (hw_stat_t) EEPROM.read(DHT_EEPROM_ADR);
        onewire_stat = (hw_stat_t) EEPROM.read(ONEWIRE_EEPROM_ADR);
        rtc_stat = (hw_stat_t) EEPROM.read(RTC_EEPROM_ADR);
        nrf_stat = (hw_stat_t) EEPROM.read(NRF_EEPROM_ADR);
        sd_stat = (hw_stat_t) EEPROM.read(SD_EEPROM_ADR);
        if (dht_stat == 0xff) dht_stat = ON; //after first boot, set state to one
        if (onewire_stat == 0xff) onewire_stat = ON;
        if (rtc_stat == 0xff) rtc_stat = ON;
        if (nrf_stat == 0xff) nrf_stat = ON;
        if (sd_stat == 0xff) sd_stat = ON;
      }
      
      //save parameters to eeprom (hardware-states)
      void SaveParameters() {
        if (dht_stat != (hw_stat_t) EEPROM.read(DHT_EEPROM_ADR)) EEPROM.write(DHT_EEPROM_ADR, (uint8_t) dht_stat);
        if (onewire_stat != (hw_stat_t) EEPROM.read(ONEWIRE_EEPROM_ADR)) EEPROM.write(ONEWIRE_EEPROM_ADR, (uint8_t) onewire_stat);
        if (rtc_stat != (hw_stat_t) EEPROM.read(RTC_EEPROM_ADR)) EEPROM.write(RTC_EEPROM_ADR, (uint8_t) rtc_stat);
        if (nrf_stat != (hw_stat_t) EEPROM.read(NRF_EEPROM_ADR)) EEPROM.write(NRF_EEPROM_ADR, (uint8_t) nrf_stat);
        if (sd_stat != (hw_stat_t) EEPROM.read(SD_EEPROM_ADR)) EEPROM.write(SD_EEPROM_ADR, (uint8_t) sd_stat);
      }
      

      Hope you like it!

      posted in My Project
      fleinze
      fleinze
    • RE: How to sleep the Arduino but still have it respond to the Vera?

      If you want to receive commands, you need to keep the nrf24 in receive mode. In this mode the radio consumes about 12mA which is a lot for a battery powered node.
      I think it would be possible to send the Arduino to sleep while the radio stays in listening mode, waking up the arduino using the irq pin, but it would still consume the 12mA.

      posted in Troubleshooting
      fleinze
      fleinze