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

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Development
  3. NodeManager
  4. NodeManager: hookon example needed

NodeManager: hookon example needed

Scheduled Pinned Locked Moved NodeManager
7 Posts 3 Posters 938 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • RPunktR Offline
    RPunktR Offline
    RPunkt
    wrote on last edited by
    #1

    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?

    1 Reply Last reply
    0
    • zboblamontZ Offline
      zboblamontZ Offline
      zboblamont
      wrote on last edited by
      #2

      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..

      1 Reply Last reply
      0
      • RPunktR Offline
        RPunktR Offline
        RPunkt
        wrote on last edited by RPunkt
        #3

        @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 ;-)

        zboblamontZ 1 Reply Last reply
        0
        • RPunktR RPunkt

          @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 ;-)

          zboblamontZ Offline
          zboblamontZ Offline
          zboblamont
          wrote on last edited by
          #4

          @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.
          ;)

          RPunktR 1 Reply Last reply
          1
          • zboblamontZ zboblamont

            @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.
            ;)

            RPunktR Offline
            RPunktR Offline
            RPunkt
            wrote on last edited by
            #5

            @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.

            U 1 Reply Last reply
            1
            • zboblamontZ Offline
              zboblamontZ Offline
              zboblamont
              wrote on last edited by
              #6

              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" ;)

              1 Reply Last reply
              1
              • RPunktR RPunkt

                @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.

                U Offline
                U Offline
                user2684
                Contest Winner
                wrote on last edited by
                #7

                @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);
                
                1 Reply Last reply
                1
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                20

                Online

                11.7k

                Users

                11.2k

                Topics

                113.1k

                Posts


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

                • Don't have an account? Register

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