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

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
H

Heizelmann

@Heizelmann
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store
About
Posts
60
Topics
5
Shares
0
Groups
0
Followers
0
Following
0

Posts

Recent Best Controversial

  • Option non blocking registration at gateway
    H Heizelmann

    @tekka OK unplugging the GW leads to a different behaviour.
    First the node didn't detect the failure as long it is not trying to send.
    When it tries to send it fails

    131268 !TSF:MSG:SEND,42-42-0-0,s=1,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=NACK:1
    

    and after some more failure this

    238494 !TSM:READY:UPL FAIL,SNP
    238497 TSM:FPAR
    238534 TSF:MSG:SEND,42-42-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=6,st=OK:
    238995 !TSF:SND:TNR
    240002 !TSF:SND:TNR
    240542 !TSM:FPAR:NO REPLY
    240544 TSM:FPAR
    240581 TSF:MSG:SEND,42-42-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    246683 !TSM:FPAR:FAIL
    246685 TSM:FAIL:CNT=1
    246687 TSM:FAIL:PDT
    

    and after a while mostly only

    609748 !TSF:SND:TNR
    

    When gateway comes back a proper reinitialization takes place:

    620572 TSM:FAIL:RE-INIT
    620574 TSM:INIT
    620581 TSM:INIT:TSP OK
    620583 TSM:INIT:STATID=42
    620587 TSF:SID:OK,ID=42
    620589 TSM:FPAR
    620625 TSF:MSG:SEND,42-42-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    Current: 0.00
    0:0:0
    Current: 0.00
    0:0:0
    621443 TSF:MSG:READ,0-0-42,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    621448 TSF:MSG:FPAR OK,ID=0,D=1
    Current: 0.00
    0:0:0
    Current: 0.00
    0:0:0
    622633 TSM:FPAR:OK
    622635 TSM:ID
    622637 TSM:ID:OK
    622638 TSM:UPL
    622642 TSF:MSG:SEND,42-42-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    622652 TSF:MSG:READ,0-0-42,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    622657 TSF:MSG:PONG RECV,HP=1
    622660 TSM:UPL:OK
    622662 TSM:READY:ID=42,PAR=0,DIS=1
    

    From now the sensor can send again without errors. :smiley:
    So far my tests.
    Except the case where the radio of the sensor went off and causes a lot of logging all test cases where satisfactorily.
    I think this is really an edge case and not so serious.
    From this point of view I would welcome that this beta development version will be published.

    Feature Requests

  • How avoid endless loop when radio init fails?
    H Heizelmann

    @mfalkvidd Thanks for the link to this thread. I didn't found this before. It is exactly my problem, so we can close this thread and continue discussing in thisone.

    @tekka Thank you for this outlook.

    For me this feature is essential and I am wondering if it is not implemented from the beginning. So I hope that it will be published soon.
    Anyway I like MySensors and the great developer community. Many thanks to all.

    Troubleshooting

  • nRf24L01+ connection quality meter
    H Heizelmann

    @AWI Thanks for this great tool. It helped me very much and I tried to implement some extended features.
    Here is my current result: It has now a menu interface with two buttons. You can change the pa level and the send repeat tries. Further you can measure the current of the radio module and reset the store. Configuration parameters are stored in EEPROM. See following code for more details.

    /*
      PROJECT: MySensors / Quality of radio transmission
      PROGRAMMER: AWI (MySensors libraries), modified by Heizelmann
      DATE: 20160529/ last update: 20171012
      FILE: AWI_Send.ino
      LICENSE: Public domain
    
      Hardware: ATMega328p board (e.g. Arduino pro nano) w/ NRF24l01
      and MySensors 2.1.1
    
      Special:
    
    
      Summary:
      Sends a radio message with counter each  x time to determine fault ratio with receiver
      Remarks:
      Fixed node-id & communication channel to other fixed node
    
      Change log:
      20160530 - added moving average on fail/ miss count, update to 2.0
      20171012 - extensions by @Heizelmann
               . added radio current measurement
               . added pa level switching
               . added send repeat option
               . added LCD Display with parallel interface
               . added two button to change pa level, send repeat count, reset store and display radio current
               . store config params in EEPROM
               . connect timeout with MY_TRANSPORT_WAIT_READY_MS
    
      @see https://forum.mysensors.org/topic/3984/nrf24l01-connection-quality-meter
    */
    
    //****  MySensors *****
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
    #define MY_RADIO_NRF24                  // Enable and select radio type attached
    //#define MY_RF24_CHANNEL 80                // radio channel, default = 76
    
    // Set LOW transmit power level  if you have an amplified NRF-module
    // if power your radio separately with a good regulator you can turn up PA level.
    // MIN, LOW, HIGH, MAX
    #define MY_RF24_PA_LEVEL RF24_PA_MAX //default = MAX on nodes, LOW on gateway and repeater
    #define MY_NODE_ID 250
    #define NODE_TXT "Quality counter Q 250"
    // Init timeout for gateway not reachable
    #define MY_TRANSPORT_WAIT_READY_MS 20000 //ms; supported since MySensors V2.1 beta
    
    
    //#define MY_PARENT_NODE_ID 32              // fixed parent to controller when 0 (else comment out = AUTO)
    //#define MY_PARENT_NODE_IS_STATIC
    
    // #define MY_RF24_CE_PIN 7               // Ceech board, 3.3v (7,8)  (pin default 9,10)
    // #define MY_RF24_CS_PIN 8
    
    #define DESTINATION_NODE 0                // receiving fixed node id (default 0 = gateway)
    
    #define MY_BAUD_RATE 115200
    
    #include <SPI.h>
    #include <MySensors.h>
    //#include <LiquidCrystal_I2C.h>                // LCD display with I2C interface
    #include <LiquidCrystal.h>                      // LCD display with parallel interface
    #include <OneButton.h> //from https://github.com/mathertel/OneButton/blob/master/examples/TwoButtons/TwoButtons.ino
    
    // helpers
    #define LOCAL_DEBUG
    
    #ifdef LOCAL_DEBUG
    #define Sprint(a) (Serial.print(a))           // macro as substitute for print, enable if no print wanted
    #define Sprintln(a) (Serial.println(a))         // macro as substitute for println
    #else
    #define Sprint(a)                   // enable if no print wanted -or- 
    #define Sprintln(a)                   // enable if no print wanted
    #endif
    
    
    // MySensors sensor
    #define COUNTER_CHILD 0
    
    // send constants and variables
    int messageCounter = 0 ;
    const int messageCounterMax = 100 ;           // maximum message counter value
    const unsigned counterUpdateDelay = 500 ;       // send every x ms and sleep in between
    
    // receive constants and variables
    boolean failStore[messageCounterMax] ;          // moving average stores & pointers
    int failStorePointer = 0 ;
    boolean missedStore[messageCounterMax] ;
    int missedStorePointer = 0 ;
    int newMessage = 0 ;
    int lastMessage = -1 ;
    int missedMessageCounter = 0 ;              // total number of messages in range (messageCounterMax)
    int failMessageCounter = 0 ;              // total number of messages in range (messageCounterMax)
    uint8_t parent = 0 ;                  // parent node-id
    
    // Loop delays
    const unsigned long displayInterval = 1000UL ;      // display update in ms
    unsigned long lastDisplayUpdate = 0 ;         // last update for loop timers
    
    // standard messages
    MyMessage counterMsg(COUNTER_CHILD, V_PERCENTAGE);   // Send value
    
    // ***** LCD
    #define LCD_COLS 16
    #define LCD_ROWS 2
    //LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
    //LiquidCrystal_I2C lcd(0x27, 16, 2);  // Set the LCD I2C address
    LiquidCrystal lcd(8, 7, 6, 5, 4, 3); // LCD with paralell interface
    
    #define CURRENT_PIN A5
    #define BUTTON1_PIN A1
    #define BUTTON2_PIN A2
    OneButton button1(BUTTON1_PIN, true); //PullUp, Activelow
    OneButton button2(BUTTON2_PIN, true); //PullUp, Activelow
    
    // Options
    #define EEPROM_FLAG 0
    #define EEPROM_PA_LEVEL 1
    #define EEPROM_SEND_REPEATS 2
    
    #define LEVEL_ITEMS 4
    const char *paLevelNames[LEVEL_ITEMS] = { "MIN", "LOW", "HIGH", "MAX" };
    uint8_t rf24palevel = MY_RF24_PA_LEVEL;
    
    #define MIN_REPEAT_DELAY 50
    #define MAX_REPEAT_DELAY 200
    uint8_t sendRepeats = 3;
    
    // Current measurement
    #define CORRECTION 9.285
    int currentMa;
    
    // Menu
    #define MENU_TIMEOUT 10000
    enum mode { STATE_RUN, STATE_RUN2, STATE_PALEVEL, STATE_RESEND};
    mode opState = STATE_RUN;
    unsigned long lastClickedMillis;
    boolean dspRefresh = true;
    
    void before() {
      pinMode(CURRENT_PIN, INPUT);
      analogReference(INTERNAL);
    
      //  Wire.begin();  // I2C
      // ** LCD display **
      lcd.begin(LCD_COLS, LCD_ROWS);
      //lcd.setBacklight(HIGH);
      lcd.home();
      lcd.setCursor(0, 0);
      lcd.print("AWIQuality nRF24");
      lcd.setCursor(0, 1);
      lcd.print("Connect...");
    
      initStore();
      delay(1000);
    
      button1.attachClick(onButton1Pressed);
      button1.attachLongPressStart(onButton1LongPressed);
      button2.attachClick(onButton2Pressed);
    
      if (loadState(EEPROM_FLAG) == 0xFF) {
        rf24palevel = loadState(EEPROM_PA_LEVEL);
        sendRepeats = loadState(EEPROM_SEND_REPEATS);
      } else {
        saveState(EEPROM_FLAG, 0xFF);
        saveState(EEPROM_PA_LEVEL, rf24palevel);
        saveState(EEPROM_SEND_REPEATS, sendRepeats);
      }
    }
    
    void presentation() {
      present(COUNTER_CHILD, S_DIMMER, NODE_TXT) ;  // counter uses percentage from dimmer value
    }
    
    void loop() {
      button1.tick();
      button2.tick();
      if (opState != STATE_RUN && opState != STATE_RUN2 && millis() - lastClickedMillis > MENU_TIMEOUT) {
        Sprintln("Timeout");
        setRFLevel(rf24palevel);
        saveState(EEPROM_PA_LEVEL, rf24palevel);
        saveState(EEPROM_SEND_REPEATS, sendRepeats);
        opState = STATE_RUN;
      }
    
      if (dspRefresh) LCD_local_display();
    
      if ( opState == STATE_RUN ) {
        Sprint("count:") ; Sprintln(messageCounter++) ;
        missedStore[failStorePointer] = false  ;      // set slot to false (ack message needs to set) ;
        boolean success = failStore[failStorePointer] = resend(counterMsg.setDestination(DESTINATION_NODE).set(failStorePointer), sendRepeats);  // send to destination with ack
        currentMa = analogRead(CURRENT_PIN) / CORRECTION;
        if (!success) {
          failMessageCounter++ ;
          Sprint("Fail on message: ") ; Sprint(failStorePointer) ;
          Sprint(" # ") ; Sprintln(failMessageCounter);
        }
        failStorePointer++ ;
        if (failStorePointer >= messageCounterMax) {
          failStorePointer =  0 ;           // wrap counter
        }
        parent = getParentNodeId();             // get the parent node (0 = gateway)
    
        wait(counterUpdateDelay) ;              // wait for things to settle and ack's to arrive
        dspRefresh = true;
      }
    }
    
    void receive(const MyMessage &message) {          // Expect few types of messages from controller
      newMessage = message.getInt();            // get received value
      switch (message.type) {
        case V_PERCENTAGE:
          missedStore[newMessage] = true ;      // set corresponding flag to received.
          if (newMessage > lastMessage) {       // number of messages missed from lastMessage (kind of, faulty at wrap)
            Sprint("Missed messages: ") ; Sprintln( newMessage - lastMessage - 1) ;
            missedMessageCounter += newMessage - lastMessage - 1 ;
          }
          lastMessage = newMessage ;
          break ;
        default: break ;
      }
    }
    
    
    // calculate number of false values in array
    // takes a lot of time, but who cares...
    int getCount(boolean countArray[], int size) {
      int falseCount = 0 ;
      for (int i = 0 ; i < size ; i++) {
        falseCount += countArray[i] ? 0 : 1 ;
      }
      return falseCount ;
    }
    
    
    void initStore() {
      for (int i = 0 ; i <  messageCounterMax ; i++) { // init stores for moving averages
        failStore[i] = true ;
        missedStore[i] = true ;
      }
      missedMessageCounter = failMessageCounter = 0;
    }
    
    void setRFLevel(uint8_t rfLevel) {
      Sprint("Set RF Level to "); Sprintln(rf24palevel);
      uint8_t rfsetup = (((MY_RF24_DATARATE) & 0b10 ) << 4) | (((MY_RF24_DATARATE) & 0b01 ) << 3) | (((rfLevel << 1))) + 1; // +1 for Si24R1;
      RF24_setRFSetup(rfsetup);
    }
    
    boolean resend(MyMessage &msg, int repeats) {
      int repeat = 0;
      int repeatdelay = 0;
      boolean sendOK = false;
    
      while ((sendOK == false) and (repeat < repeats)) {
        if (send(msg, true)) { //send
          sendOK = true;
        } else {
          sendOK = false;
          repeatdelay += random(MIN_REPEAT_DELAY, MAX_REPEAT_DELAY);
        }
        repeat++;
        delay(repeatdelay);
      }
      return sendOK;
    }
    
    void onButton1Pressed() {
      dspRefresh = true;
      lcd.clear(); lcd.home();
      switch (opState) {
        case STATE_RUN:
          opState = STATE_PALEVEL;
          break;
        case STATE_RUN2:
          opState = STATE_RUN;
          break;
        case STATE_PALEVEL:
          opState = STATE_RESEND;
          break;
        case STATE_RESEND:
          setRFLevel(rf24palevel);
          saveState(EEPROM_PA_LEVEL, rf24palevel);
          saveState(EEPROM_SEND_REPEATS, sendRepeats);
          opState = STATE_RUN;
          break;
      }
      lastClickedMillis = millis();
    }
    
    void onButton2Pressed() {
      dspRefresh = true;
      lcd.clear(); lcd.home();
      switch (opState) {
        case STATE_RUN:
          opState = STATE_RUN2;
          break;
        case STATE_RUN2:
          opState = STATE_RUN;
          break;
        case STATE_PALEVEL:
          rf24palevel++; if (rf24palevel > 3) rf24palevel = 0;
          break;
        case STATE_RESEND:
          sendRepeats++; if (sendRepeats > 3) sendRepeats = 1;
          break;
      }
      lastClickedMillis = millis();
    }
    
    void onButton1LongPressed() {
      initStore();
    }
    
    
    void LCD_local_display(void) {
      dspRefresh = false;
      char buf[LCD_COLS + 1];                     // buffer for max 16 char display
    
      switch (opState) {
        case STATE_RUN:
          lcd.setCursor(0, 0);
          snprintf(buf, sizeof buf, "P%-3dFail%4d%3d%%", parent, failMessageCounter, getCount(failStore, messageCounterMax));
          lcd.print(buf);
          lcd.setCursor(0, 1);
          snprintf(buf, sizeof buf, "D%-3dMiss%4d%3d%%", DESTINATION_NODE , missedMessageCounter, getCount(missedStore, messageCounterMax));
          lcd.print(buf);
          break;
        case STATE_RUN2:
          lcd.setCursor(0, 0);
          snprintf(buf, sizeof buf, "PA Level = %s", paLevelNames[rf24palevel]);
          lcd.print(buf);
          lcd.setCursor(0, 1);
          snprintf(buf, sizeof buf, "Current = %dmA", currentMa);
          lcd.print(buf);
          break;
        case STATE_PALEVEL:
          lcd.setCursor(0, 0);
          snprintf(buf, sizeof buf, "PA Level = %s", paLevelNames[rf24palevel]);
          lcd.print(buf);
          break;
        case STATE_RESEND:
          lcd.setCursor(0, 0);
          snprintf(buf, sizeof buf, "Send repeats = %d", sendRepeats);
          lcd.print(buf);
          break;
      }
    }
    
    
    My Project

  • repeater node with sensor
    H Heizelmann

    ... and to give the DHT sensor a chance on reading errors to retry and not to wait until next cycle which might be very long:

        for (unsigned int i = 0; i < DHT_MAX_TRIES; i ++) {
          float temperature = dht.getTemperature();
          if (isnan(temperature)) {
            Serial.println("Failed reading temperature from DHT");
            gw.wait(dht.getMinimumSamplingPeriod());
          } else if (temperature != lastTemp) {
            lastTemp = temperature;
            if (!metric) {
              temperature = dht.toFahrenheit(temperature);
            }
            gw.send(msgTemp.set(temperature, 1));
            Serial.print("T: ");
            Serial.println(temperature);
            break;
          }
        }
    

    Repeat the same for humidity of cause.

    General Discussion

  • Doorbell node
    H Heizelmann

    Something like that:

    long ringSendtAt;
    boolean isRinging;
    void setup() {
      ringSendtAt = millis() - 10000;
      ...
    }
    
    
    void loop() {
      ...
      if ( isRinging && millis()- ringSendtAt > 10000)
        sendRingingMessage();
        ringSendtAt = millis();
      }
      ...
    
    Development

  • How to get longest battery life
    H Heizelmann

    Here you find a sketch including battery report which I found best. Works also with your PIR I think. For a advanced sketch you can ckeck this.

    I use an arduino pro mini 3.3V with 2 AA batteries at 8 MHZ CPU speed.

    Most important is to remove the voltage regulator on the PIR and supply it directly with 3V. My battery lasts over month with this combination.

    There are different solutions for this. Most powersaving is to remove the regulator.
    The solution n the picture above has the advantage that the electrolytic capacitor downright is still in use. The additional blue capacitor 100nF is optional, should serve as noise filter.
    PIR modification

    Troubleshooting

  • Node communication without gateway
    H Heizelmann

    @sigolhi I have a similar problem and started a thread about this a while ago. See here https://forum.mysensors.org/topic/6413/node-to-node-communication. It is still unclear how to do a node-to-node communication without a gateway. Even a repeater node will not help.

    General Discussion

  • Doorbell node
    H Heizelmann

    Some optimization to check:

    • ringerdelay needs to be defined with a type
    • if condition in setup() not necessary initialize buttonpushed and ringSendAt unconditioned
    • normalize logic in if (timenu > buttonpushed && timenu > buttonpushed + ringerdelay) to if (timenu > buttonpushed + ringerdelay), it is the same
    • variable timenu not necessary use millis() directly: if (millis() > buttonpushed + ringerdelay)
    • on relay initialisation the two comments are wrong
    Development

  • How to get longest battery life
    H Heizelmann

    @dbemowsk The picture shows the modified PIR. The right circle shows the place where the diode was. It is also removed and the contacts are bridged by soldering. The regulator was on position marked with the left circle. it is removed and the two upper contacts are bridged. The adde blue capacitor is contected from this point ( now 3.3V) input to the lower pad which is Ground. It is a 100nF ceramic capacitor.

    Troubleshooting

  • Is there a way to check presence of a MySensors network, and proceed without if not found ?
    H Heizelmann

    @dbemowsk Search for node to node communication, you will find e.g.
    https://forum.mysensors.org/topic/8716/direct-pairing-of-two-nodes-implementation
    https://forum.mysensors.org/topic/826/node-to-node-communication and maybe some more.

    Development

  • How to get longest battery life
    H Heizelmann

    @dbemosk
    Look for a datasheet for the PIR e.g.here.
    In the diagram you can find the regulator IC1 on the topright as well as the diode D1 below of it.

    Troubleshooting

  • How to get longest battery life
    H Heizelmann

    @NeverDie My Multimeter is not very good, but I tried to measure the total current. I got 3 values: 0.03mA when sleeping, 0.16mA when PIR triggered and about 18mA when RF is sending. Last is very short an cannot measured with my digital multimeter directly. I measured this value on startup the node when the registration process is longer and I guess it is a similar value when sending.

    Troubleshooting

  • How to get longest battery life
    H Heizelmann

    Here are some measured values (not very precise):

    The unmodified HC-SR50: Supply 5.0V, Standby 0.05mA, Tripped: 0.19mA

    Regulator and diode removed: Supply 3.0V, Standby 0.03mA, Tripped 0.15mA
    Regulator and diode removed: Supply 2.4V, Standby 0.02mA, Tripped 0.11mA

    Below 2.4 V the Sensor doesn't work reliable.
    The voltage drop of the diode depends on the current and is minimum 0.5V.
    So if you would like to operate with 3 AA-Batteries it is recommended to remove/shortcut the diode.

    Troubleshooting

  • [solved] requestTime() does not work with serial gateway and Pimatic controller
    H Heizelmann

    Sorry, my fault. The receiveTime function is called. The problem was that I had an error in the Serial.println() statement so it doesn't appear in the log.

    Troubleshooting

  • How to get time a sensor has slept
    H Heizelmann

    @mfalkvidd said in How to get time a sensor has slept:

    There are a few tricks though. See these threads and see if any of the suggested solutions would work for you.
    https://forum.mysensors.org/post/71715

    That is exact the same issue .Thanks for pointing to this. I didn't found this.

    Troubleshooting

  • Help me build a 6-light-sensor & 2 ch relay node.
    H Heizelmann

    Only if you send a correct message from the controller to the node
    the receive function is called. I don't see a receive in your log.

    I think in your case the receive-function is not called (or called with a wrong message type or node id). Put a

     serial.print("receive() is called with type "); serial.println(message.getType());
    

    on top of the receive function to see if the receive function is called and which type is handed over..

    Troubleshooting
  • Login

  • Don't have an account? Register

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