NodeManager: hookon example needed



  • Hi, I am just making my first steps with the NodeManager. To get a simple sensor running is very easy, but how do I get custom code on the sketch?
    I have a distance sensor, that is monitoring the water level in a water tank.
    But I want the node also to present the level in percent and volume in liter. The should be done by hookon- code and be presented as well.
    Can someone give me some hints or give an example?



  • Is there a particular reason you do NOT want to do this at the Node?
    Although using Domoticz here, the pre-calculated values are handled with ease..



  • @zboblamont Maybe I expressed myself not clearly. I want to make the calculations on the node (the arduino). The distance, that the sensor is measuring should be transmitted, the fill rate in percent should be transmitted as well and the "liter available" should be transmitted also.

    MyMessage msgdistance(CHILD_ID_DISTANCE, V_DISTANCE); //distance from sensor to watersurface
    MyMessage msgVolume(CHILD_ID_WATER, V_LEVEL); //water availble in liters
    MyMessage msgPercent(CHILD_ID_PERCENT, V_LEVEL); // water percentsge available

    Sorry, but I am just learning 😉



  • @rpunkt Ok, never heard of "hook-on code", if you mean an example sketch, here is my water tank node to butcher.

    #include <T2WhisperNode.h>
    
    #include <Wire.h>
    #include <RTClibExtended.h>
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG //Comment out once all working saving memory
    
    // Enable and select radio type attached
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY RFM69_433MHZ  // Define for frequency setting. Needed if you're radio module isn't 868Mhz (868Mhz is default in lib)
    #define MY_RFM69_NETWORKID 101  // Default is 100 in lib. Uncomment it and set your preferred network id if needed
    #define MY_NODE_ID 7  //Manually set the node ID here. Comment out to auto assign
    //A define should be added to provide minimum power output to provide decent RSSI to the Gateway if ATC not available
    #include <MyConfig.h>
    #include <SPI.h>
    #include <MySensors.h>
    #define SN "Node7water3vWNfinalRTC"
    #define SV "4"
    #define FIRST_CHILD_ID 1
    #define SECOND_CHILD_ID 2
    #define THIRD_CHILD_ID 3
    #define REED_PIN 3   // Arduino Digital I/O pin for button/reed switch
    #define BatteryOn 14
    #define BatteryIn A6
    #define RelayOn 6
    #define RelayOff 9
    #define Trigpin 17
    #define Echopin 16
    
    int halfday=12;
    int tankdepth, tankpercent,tankvolume,distance,test,test2,counter;
    long duration;
    volatile int ultrasonic;
    RTC_DS3231 RTC;      //we are using the DS3231 RTC
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msg1(FIRST_CHILD_ID, V_LEVEL);
    MyMessage msg2(SECOND_CHILD_ID, V_LEVEL);
    MyMessage msg3(THIRD_CHILD_ID, V_VOLTAGE);
    unsigned long SLEEP_TIME = 0;//1800000; Sleep time between reports (in milliseconds)
    
    void setup ()
      {
       pinMode(REED_PIN, INPUT_PULLUP);//Output of DS3231 INT pin is connected to D3 INT1 for RTC wake-up
       pinMode(BatteryOn, OUTPUT);//WN battery sample activation
       pinMode(BatteryIn, INPUT);//WN ADC for battery read
       pinMode(Trigpin, OUTPUT);
       pinMode(Echopin,INPUT);
       pinMode(RelayOn, OUTPUT);//US on
       pinMode(RelayOff, OUTPUT);//US off
       analogReference(INTERNAL);//All voltage reads are to 1.1 internal datum
       VOFF();
       sleep(100);//Allow things to settle was 1000
       Wire.begin ();
       RTC.begin();
       RTC.adjust(DateTime(__DATE__, __TIME__));   //set RTC date and time to COMPILE time
    
    //clear any pending alarms
       RTC.armAlarm(1, false);
       RTC.clearAlarm(1);
       RTC.alarmInterrupt(1, false);
       RTC.armAlarm(2, false);
       RTC.clearAlarm(2);
       RTC.alarmInterrupt(2, false);
    
      //Set SQW pin to OFF
       RTC.writeSqwPinMode(DS3231_OFF);
    
      //Set alarm1 every hour at XX:50
       RTC.setAlarm(ALM1_MATCH_MINUTES, 0, 50, 0, 0);//set wake-up time here
       RTC.alarmInterrupt(1, true);//Alarm on
      }
      
     void presentation(){
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
    
      // Register binary input sensor to sensor_node (they will be created as child devices)
      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      present(FIRST_CHILD_ID, S_DUST);
      present(SECOND_CHILD_ID, S_DUST);
      present(THIRD_CHILD_ID, S_MULTIMETER);
    }
    
    void loop(){
    // Power up US
        VON();
       sleep(500);//Delay to let the 5v kit stabilise
       digitalWrite(Trigpin,HIGH);
       sleep (100); 
       digitalWrite(Trigpin,LOW);
       sleep(100);/// Allow decay of pulse
       int voltread;
       counter=0;
       tankdepth=0;
       while ((tankdepth<350||tankdepth>1000)&&counter<=10){//10 attempts to get proper range
       READULTRASONIC();
       counter++;
       } 
    //Normal range should be 363 to 989, completely empty 1520, //First overnight runs got depth full as 363mm so formula revise
    //   float tankpercent=100-((989-ultrasonic)/6);
      float tankpercent=100-((989-tankdepth)/6.26);//626 effective range
       int tankvolume=(989-tankdepth)*2.3727;//Set to low level cut off
       if(tankdepth>350&&tankdepth<1000){//Don't report if value is outwith known range
       VOFF();
       sleep(100);
       send(msg1.set(tankvolume));//This is actual volume
       sleep(100);
       send(msg2.set(tankpercent,1));//This is remainder to start of 39cm Freeboard
       sleep(100);  
       }
    //   }
       VOFF();//If there are 2 yellow flashes it reported and switched off 1 if it failed to read
    // Call for battery reading, send in every 12th RTC call?
       if(halfday==12){
       digitalWrite(BatteryOn, HIGH);
       voltread = analogRead(BatteryIn);
       float voltage = (7.272 * voltread) / 1024;
       sleep(5);
       digitalWrite(BatteryOn, LOW);
       send(msg3.set(voltage,2));
       sleep(50);
       voltread=0;
       sleep(50);
       halfday=0;//Reset for 12 hourly cycle
    }
       halfday++;//Increment hourly cycle
    
    // Rearm alarm
       Wire.begin();
       RTC.begin();
       RTC.alarmInterrupt(1, true);
       sleep(50);
       Wire.end();
       sleep(50);
    //Go deep sleep until RTC interrups
       sleep(digitalPinToInterrupt(REED_PIN),FALLING, SLEEP_TIME);
    sleep(100);///Time to recover
    //First clear the alarm
       Wire.begin();
       RTC.begin();
       RTC.armAlarm(1, false);
       RTC.clearAlarm(1);
       RTC.alarmInterrupt(1, false);
      }  // end of loop
    
    void VON(){
      digitalWrite(RelayOn, HIGH);
      sleep (10);
      digitalWrite(RelayOn,LOW);
    }
    
    void VOFF(){
      digitalWrite(RelayOff, HIGH);
      sleep (10);
      digitalWrite(RelayOff,LOW);
    }
    
      void READULTRASONIC(){//JSN-SR04-2.0
    //Main loop checks valid range on a defined number of readings
      tankdepth=0;
      duration=0;
      distance=0;
      test=1;
      test2=3;
    // Normal range should lie between 389 and 989 absolutely empty is 1520
    while (test!=test2){// Get two consecutive readings
      digitalWrite(Trigpin, LOW);
      delayMicroseconds(100);
      digitalWrite(Trigpin, HIGH);
      delayMicroseconds(150);
      digitalWrite(Trigpin, LOW);
      duration = pulseIn(Echopin, HIGH);
      distance = duration/5.82;//This is in mm
     if (test!=distance){
        test=distance;
        distance=0;
       }
       else{
        test2=distance;
      }
      delay(100);///// 500 originally but why???????
      }
      tankdepth=distance;
     }
    

    All specific to this setup of course, but it should point you in the right direction.
    It returns the volume available from the tank and the %age used. Since the actual volume can potentially overshoot the electrode (turning off the fill pump) it calculates the absolute volume above the supply pump cut-off, the %age used operates from the theoretical full mark.
    I see no reason for sending the actual level, but you may have your reasons.
    😉



  • @zboblamont My question is related to:
    https://github.com/mysensors/NodeManager
    This should be an easy way to get sensors running. It should be nice, if You have a battery- powered node as well.
    But for me it is not clear what to to, if You want some extra information to be transmitted.
    So I thought, that would be as easy as setting up a node.

    Only playing a little with:
    "NODEMANAGER_HOOKING OFF allow custom code to be hooked in the out of the box sensors"

    As far as I understand, Your way is the conventional approach.
    That will work for sure, but than power saving is an issue.
    I want that stuff be powered by solar or battery. So it should be very power efficient. That is the reason to try the NodeManager.



  • Ah, so that is where "hook-on" reference comes from, still no idea what it means but presumably you do....
    No worries, good luck, I'll stick with "conventional" 😉


  • Contest Winner

    @rpunkt sorry for replying to late...hooks are pretty simple to use in Nodemanager once you enable them. Just define your custom function and pass it to the hook. In the example below I'm activating a buzzer every time my fingerprint sensor is successful. The function will be executed every time (e.g. in this case after every loop() of fingerprint), up to you to implement your logic in the hook function.

    void bip(Sensor* sensor) {
      if (fingerprint.success) buzzer.setStatus(ON);
    }
    
    fingerprint.setPostLoopHook(&bip);
    

 

222
Online

8.9k
Users

9.7k
Topics

101.2k
Posts