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. My Project
  3. nRf24L01+ connection quality meter

nRf24L01+ connection quality meter

Scheduled Pinned Locked Moved My Project
43 Posts 18 Posters 20.4k Views 32 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.
  • mfalkviddM mfalkvidd

    @AWI is that hardware ack or software ack? (The MySensors ack confusion is driving me insane)

    AWIA Offline
    AWIA Offline
    AWI
    Hero Member
    wrote on last edited by AWI
    #5

    @mfalkvidd my interpretation and based on experience:

    • fail (hardware ack..) is the node to node acknowledgement. (i.e. from node to repeater or gateway). Can not be switched on/off from the API. This is the return value from the send() function (or gw.send()). If a fail occurs the node tries multiple times to resend (this can take quitte a lot of time..) This acknowledgement is only from the next node in line.
    • missed (software ack) is the node to destination acknowledgement (i.e. node - repeater - gateway) . Can (and should) be enabled in the send() function. The acknowledgement is send automatically by the destination node in the form of an "echo" of the message sent. No automatic resend happens. Eventual action should be taken by the sender (controller / sketch in node).

    The "connection quality meter" measures the number of fails and averages this for 100 samples (percentate) and similar for not acknowledged "software ack's".

    Ik will post the sketch later today..

    1 Reply Last reply
    1
    • AWIA Offline
      AWIA Offline
      AWI
      Hero Member
      wrote on last edited by
      #6

      The sketch for the connection quality meter.

      /*
       PROJECT: MySensors / Quality of radio transmission 
       PROGRAMMER: AWI (MySensors libraries)
       DATE: 20160529/ last update: 20160530
       FILE: AWI_Send.ino
       LICENSE: Public domain
      
       Hardware: ATMega328p board w/ NRF24l01
      	and MySensors 2.0 (Development)
      	
      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 
      */
      
      
      //****  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
      
      #define MY_NODE_ID 250
      #define NODE_TXT "Q 250"								// Text to add to sensor name
      
      // #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)
      
      #include <SPI.h>
      #include <MySensor.h>  
      
      // display
      #include <Wire.h>											// I2C
      #include <LiquidCrystal_I2C.h>								// LCD display with I2C interface
      
      
      // 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 counterChild 0
      
      // send constants and variables
      int messageCounter = 0 ; 
      const int messageCounterMax = 100 ; 					// maximum message counter value 
      const unsigned counterUpdateDelay = 100 ;				// 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)
      
      // Loop delays
      const unsigned long displayInterval = 1000UL ;			// display update in ms
      unsigned long lastDisplayUpdate = 0 ;					// last update for loop timers
      
      // standard messages
      MyMessage counterMsg(counterChild, V_PERCENTAGE);		// Send value
      
      // ***** LCD
      LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
      
      void setup() {
      	Wire.begin();  // I2C
          // ** LCD display **
          // LCD 2 lines * 16 char.
          lcd.begin(16, 2);
          lcd.setBacklight(HIGH);
          lcd.setCursor(0, 0);
      	lcd.print("AWI Quality nRF24");
      
      	for(int i= 0 ; i <  messageCounterMax ; i++){		// init stores for moving averages
      		failStore[i] = true ;
      		missedStore[i] = true ;
       	}
      	missedStorePointer = failStorePointer = 0 ;
          delay(1000);
      }
      
      void presentation(){
      // MySensors
      	present(counterChild, S_DIMMER, "Quality counter " NODE_TXT) ;  // counter uses percentage from dimmer value
      }
      
      
      void loop() {
      	// Sprint("count:") ; Sprintln(messageCounter) ;
      	LCD_local_display();
      	missedStore[failStorePointer] = false  ; 			// set slot to false (ack message needs to set) ; 
      	boolean succes = failStore[failStorePointer] = send(counterMsg.setDestination(DESTINATION_NODE).set(failStorePointer), true);  // send to destination with ack
      	if (!succes){
      		failMessageCounter++ ; 
      		Sprint("Fail on message: ") ; Sprint(failStorePointer) ;
      		Sprint(" # ") ; Sprintln(failMessageCounter);
      	}
      	failStorePointer++ ;
      	if(failStorePointer >= messageCounterMax){
      		failStorePointer =  0	;						// wrap counter
      	}
      	wait(counterUpdateDelay) ;							// wait for things to settle and ack's to arrive
      }
      
      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 LCD_local_display(void){
      /* prints all available variables on LCD display with units
      */
      	
          char buf[17]; 											// buffer for max 16 char display
          lcd.setCursor(0, 0);
          snprintf(buf, sizeof buf, "Failed:%4d %3d%%", failMessageCounter, getCount(failStore, messageCounterMax));
          lcd.print(buf);
          lcd.setCursor(0, 1);
          snprintf(buf, sizeof buf, "Missed:%4d %3d%%", missedMessageCounter, getCount(missedStore, messageCounterMax));
      	lcd.print(buf);
      }
      
      
      1 Reply Last reply
      7
      • B Offline
        B Offline
        boozz
        wrote on last edited by
        #7

        Thnx!

        :+1:

        1 Reply Last reply
        1
        • AWIA Offline
          AWIA Offline
          AWI
          Hero Member
          wrote on last edited by AWI
          #8

          I have been walking through and around the house with the meter to find the best radio solutions. So far I have the best reach with the nRF24L01+PA+LNA with the plastic/ aluminum foil (the ugly fix ;-), credits @Oitzu).
          0_1464961145010_upload-8716e90d-606f-4d9e-8dcb-697cb95fbbd6

          0_1464959045642_upload-85c16c8d-ac9f-40a9-a1cb-8464cc0bba0b

          b.t.w. I added "parent" and "destination" node to the display to show where the meter is connected to. Destination is fixed in the sketch but the "parent" will change if the meter connects to another node (i.e. repeater)

          To give you a real life impression . The transmitter (also nRF24L01+PA+LNA) is where the red arrow is behind two thick brick walls and a few trees. So, unless you live in a big mansion this should be sufficient range. Open field performance would be much better.
          0_1464961025398_upload-b1ddebfd-d124-433f-a00e-6296301a71f1

          For the rest of the tests I had a large variance in results. Some general observations:

          • nRF24L01+PA+LNA without the "shielding" is pretty similar (and sometimes even worse) than the standard radio with the pcb antenna.

          • all nRF24L01+ in SMD version have a comparable performance to the standard ones

          • The standard radio's I have tested with a silk screen (white lines) and pin designation print on the back seem to be fine.
            0_1464960195473_upload-9ff7ca2d-75e5-45b7-bea3-8824b6c19dd2

          • The (around 18) radio's is have tested without silk screen (3 different batches) are either "bad" performers (few meters) or don't perform at all. ( I noticed earlier and already put them apart. I was able to sort out 6 that can be used for short distance.).
            0_1464960320567_upload-b0a4caa9-7764-485b-a12e-8b9577dbe3e5

          • I don;t have any "blob" samples..

          I know this is far from scientific proof, but hope it gives you some guidance..

          YveauxY 1 Reply Last reply
          2
          • OitzuO Offline
            OitzuO Offline
            Oitzu
            wrote on last edited by Oitzu
            #9

            @AWI there also 2 versions of the PA/LNA Modules out there. Which one do you tested?

            AWIA 1 Reply Last reply
            0
            • AWIA AWI

              I have been walking through and around the house with the meter to find the best radio solutions. So far I have the best reach with the nRF24L01+PA+LNA with the plastic/ aluminum foil (the ugly fix ;-), credits @Oitzu).
              0_1464961145010_upload-8716e90d-606f-4d9e-8dcb-697cb95fbbd6

              0_1464959045642_upload-85c16c8d-ac9f-40a9-a1cb-8464cc0bba0b

              b.t.w. I added "parent" and "destination" node to the display to show where the meter is connected to. Destination is fixed in the sketch but the "parent" will change if the meter connects to another node (i.e. repeater)

              To give you a real life impression . The transmitter (also nRF24L01+PA+LNA) is where the red arrow is behind two thick brick walls and a few trees. So, unless you live in a big mansion this should be sufficient range. Open field performance would be much better.
              0_1464961025398_upload-b1ddebfd-d124-433f-a00e-6296301a71f1

              For the rest of the tests I had a large variance in results. Some general observations:

              • nRF24L01+PA+LNA without the "shielding" is pretty similar (and sometimes even worse) than the standard radio with the pcb antenna.

              • all nRF24L01+ in SMD version have a comparable performance to the standard ones

              • The standard radio's I have tested with a silk screen (white lines) and pin designation print on the back seem to be fine.
                0_1464960195473_upload-9ff7ca2d-75e5-45b7-bea3-8824b6c19dd2

              • The (around 18) radio's is have tested without silk screen (3 different batches) are either "bad" performers (few meters) or don't perform at all. ( I noticed earlier and already put them apart. I was able to sort out 6 that can be used for short distance.).
                0_1464960320567_upload-b0a4caa9-7764-485b-a12e-8b9577dbe3e5

              • I don;t have any "blob" samples..

              I know this is far from scientific proof, but hope it gives you some guidance..

              YveauxY Offline
              YveauxY Offline
              Yveaux
              Mod
              wrote on last edited by
              #10

              @AWI said:

              The standard radio's I have tested with a silk screen (white lines) and pin designation print on the back seem to be fine

              In the picture, these radios have the notorious 1242AF datecode on the chip (if you didn't take the pictures yourself, do you have the same date code?). I also have a batch of these and they perform very well!

              http://yveaux.blogspot.nl

              1 Reply Last reply
              0
              • D Offline
                D Offline
                drock1985
                wrote on last edited by
                #11

                Thanks @awi for this, might have to build one myself to test a potential bad batch of radios i have.

                Do you need the LCD for this or is the data also print in serial?

                Thanks,

                My Projects
                2 Door Chime Sensor
                Washing Machine Monitor

                AWIA 1 Reply Last reply
                0
                • D drock1985

                  Thanks @awi for this, might have to build one myself to test a potential bad batch of radios i have.

                  Do you need the LCD for this or is the data also print in serial?

                  Thanks,

                  AWIA Offline
                  AWIA Offline
                  AWI
                  Hero Member
                  wrote on last edited by
                  #12

                  @drock1985 It will print the data on serial but not very well formatted. You don't need the LCD but it is easy to carry around the house. (a laptop too :smiley: but be aware of disturbances coming from the laptop i.e. Wifi ) I thought off blinking led's also. You can easily change the sketch, there is not much to it..

                  1 Reply Last reply
                  0
                  • OitzuO Oitzu

                    @AWI there also 2 versions of the PA/LNA Modules out there. Which one do you tested?

                    AWIA Offline
                    AWIA Offline
                    AWI
                    Hero Member
                    wrote on last edited by
                    #13

                    @Oitzu which versions do you relate to? I also have some with ceramic antenna (smd connection)

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      boozz
                      wrote on last edited by
                      #14

                      @AWI

                      Kijken je buren niet gek op wanneer je met je meter rondloopt? :wink:

                      gr.

                      Boozz

                      AWIA 1 Reply Last reply
                      0
                      • B boozz

                        @AWI

                        Kijken je buren niet gek op wanneer je met je meter rondloopt? :wink:

                        gr.

                        Boozz

                        AWIA Offline
                        AWIA Offline
                        AWI
                        Hero Member
                        wrote on last edited by AWI
                        #15

                        @boozz my neighbors ask me every two weeks what I am doing and what all those strange looking things in my garden and on my roof are... :flushed:

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          boozz
                          wrote on last edited by
                          #16

                          @AWI

                          And when you start explaining they look somewhat odd don't they?

                          1 Reply Last reply
                          0
                          • mrc-coreM Offline
                            mrc-coreM Offline
                            mrc-core
                            wrote on last edited by
                            #17

                            I'm having a problem in this part off the code:
                            "present(counterChild, S_DIMMER, "Quality counter " NODE_TXT) ; // counter uses percentage from dimmer value"

                            I'm getting this error:
                            "exit status 1
                            'present' was not declared in this scope"

                            How can i fix this ?

                            mfalkviddM 1 Reply Last reply
                            0
                            • mrc-coreM mrc-core

                              I'm having a problem in this part off the code:
                              "present(counterChild, S_DIMMER, "Quality counter " NODE_TXT) ; // counter uses percentage from dimmer value"

                              I'm getting this error:
                              "exit status 1
                              'present' was not declared in this scope"

                              How can i fix this ?

                              mfalkviddM Offline
                              mfalkviddM Offline
                              mfalkvidd
                              Mod
                              wrote on last edited by
                              #18

                              @mrc-core sounds like you are using the stable (1.5.x) version of MySensors. This sketch requires the development version which is available on github

                              1 Reply Last reply
                              0
                              • mrc-coreM Offline
                                mrc-coreM Offline
                                mrc-core
                                wrote on last edited by
                                #19

                                Thanks for the quick reply.
                                i'm going to change the versions :)

                                1 Reply Last reply
                                1
                                • bjacobseB Offline
                                  bjacobseB Offline
                                  bjacobse
                                  wrote on last edited by
                                  #20

                                  Can this be extended to also measure NRF24l01 standby current? Maybe some "fake" modules have a high current consumption in stadnby mode, this could drain batteries quickly when used in battery operated devices

                                  1 Reply Last reply
                                  0
                                  • cjrpriestC Offline
                                    cjrpriestC Offline
                                    cjrpriest
                                    wrote on last edited by cjrpriest
                                    #21

                                    Hi @AWI, could you kindly post your updated version of the sketch that has the parent and destination node numbers on the display?

                                    AWIA 1 Reply Last reply
                                    0
                                    • cjrpriestC cjrpriest

                                      Hi @AWI, could you kindly post your updated version of the sketch that has the parent and destination node numbers on the display?

                                      AWIA Offline
                                      AWIA Offline
                                      AWI
                                      Hero Member
                                      wrote on last edited by
                                      #22

                                      @cjrpriest Here you go..

                                      /*
                                       PROJECT: MySensors / Quality of radio transmission 
                                       PROGRAMMER: AWI (MySensors libraries)
                                       DATE: 20160529/ last update: 20160530
                                       FILE: AWI_Send.ino
                                       LICENSE: Public domain
                                      
                                       Hardware: ATMega328p board w/ NRF24l01
                                      	and MySensors 2.0
                                      	
                                      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
                                      */
                                      
                                      
                                      //****  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
                                      
                                      #define MY_NODE_ID 250
                                      #define NODE_TXT "Q 250"								// Text to add to sensor name
                                      
                                      //#define MY_PARENT_NODE_ID 42							// fixed parent to controller when 0 (else comment out = AUTO)
                                      
                                      
                                      // #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)
                                      
                                      #include <SPI.h>
                                      #include <MySensors.h>  
                                      
                                      // display
                                      #include <Wire.h>											// I2C
                                      #include <LiquidCrystal_I2C.h>								// LCD display with I2C interface
                                      
                                      
                                      // 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 counterChild 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(counterChild, V_PERCENTAGE);		// Send value
                                      
                                      // ***** LCD
                                      //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
                                      
                                      void setup() {
                                      	Wire.begin();  // I2C
                                          // ** LCD display **
                                          // LCD 2 lines * 16 char.
                                          lcd.begin(16, 2);
                                          lcd.setBacklight(HIGH);
                                          lcd.setCursor(0, 0);
                                      	lcd.print("AWI Quality nRF24");
                                      
                                      	for(int i= 0 ; i <  messageCounterMax ; i++){		// init stores for moving averages
                                      		failStore[i] = true ;
                                      		missedStore[i] = true ;
                                       	}
                                      	missedStorePointer = failStorePointer = 0 ;
                                      	delay(1000);
                                      }
                                      
                                      void presentation(){
                                      // MySensors
                                      	present(counterChild, S_DIMMER, "Quality counter " NODE_TXT) ;  // counter uses percentage from dimmer value
                                      }
                                      
                                      
                                      void loop() {
                                      	// Sprint("count:") ; Sprintln(messageCounter) ;
                                      	LCD_local_display();
                                      	missedStore[failStorePointer] = false  ; 			// set slot to false (ack message needs to set) ; 
                                      	boolean succes = failStore[failStorePointer] = send(counterMsg.setDestination(DESTINATION_NODE).set(failStorePointer), true);  // send to destination with ack
                                      	if (!succes){
                                      		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
                                      }
                                      
                                      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 LCD_local_display(void){
                                      /* prints all available variables on LCD display with units
                                      */
                                      	
                                          char buf[17]; 											// buffer for max 16 char display
                                          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);
                                      }
                                      
                                      
                                      cjrpriestC karl261K 2 Replies Last reply
                                      1
                                      • AWIA AWI

                                        @cjrpriest Here you go..

                                        /*
                                         PROJECT: MySensors / Quality of radio transmission 
                                         PROGRAMMER: AWI (MySensors libraries)
                                         DATE: 20160529/ last update: 20160530
                                         FILE: AWI_Send.ino
                                         LICENSE: Public domain
                                        
                                         Hardware: ATMega328p board w/ NRF24l01
                                        	and MySensors 2.0
                                        	
                                        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
                                        */
                                        
                                        
                                        //****  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
                                        
                                        #define MY_NODE_ID 250
                                        #define NODE_TXT "Q 250"								// Text to add to sensor name
                                        
                                        //#define MY_PARENT_NODE_ID 42							// fixed parent to controller when 0 (else comment out = AUTO)
                                        
                                        
                                        // #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)
                                        
                                        #include <SPI.h>
                                        #include <MySensors.h>  
                                        
                                        // display
                                        #include <Wire.h>											// I2C
                                        #include <LiquidCrystal_I2C.h>								// LCD display with I2C interface
                                        
                                        
                                        // 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 counterChild 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(counterChild, V_PERCENTAGE);		// Send value
                                        
                                        // ***** LCD
                                        //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
                                        
                                        void setup() {
                                        	Wire.begin();  // I2C
                                            // ** LCD display **
                                            // LCD 2 lines * 16 char.
                                            lcd.begin(16, 2);
                                            lcd.setBacklight(HIGH);
                                            lcd.setCursor(0, 0);
                                        	lcd.print("AWI Quality nRF24");
                                        
                                        	for(int i= 0 ; i <  messageCounterMax ; i++){		// init stores for moving averages
                                        		failStore[i] = true ;
                                        		missedStore[i] = true ;
                                         	}
                                        	missedStorePointer = failStorePointer = 0 ;
                                        	delay(1000);
                                        }
                                        
                                        void presentation(){
                                        // MySensors
                                        	present(counterChild, S_DIMMER, "Quality counter " NODE_TXT) ;  // counter uses percentage from dimmer value
                                        }
                                        
                                        
                                        void loop() {
                                        	// Sprint("count:") ; Sprintln(messageCounter) ;
                                        	LCD_local_display();
                                        	missedStore[failStorePointer] = false  ; 			// set slot to false (ack message needs to set) ; 
                                        	boolean succes = failStore[failStorePointer] = send(counterMsg.setDestination(DESTINATION_NODE).set(failStorePointer), true);  // send to destination with ack
                                        	if (!succes){
                                        		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
                                        }
                                        
                                        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 LCD_local_display(void){
                                        /* prints all available variables on LCD display with units
                                        */
                                        	
                                            char buf[17]; 											// buffer for max 16 char display
                                            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);
                                        }
                                        
                                        
                                        cjrpriestC Offline
                                        cjrpriestC Offline
                                        cjrpriest
                                        wrote on last edited by
                                        #23

                                        Thanks very much @AWI 👍

                                        1 Reply Last reply
                                        0
                                        • AWIA AWI

                                          @cjrpriest Here you go..

                                          /*
                                           PROJECT: MySensors / Quality of radio transmission 
                                           PROGRAMMER: AWI (MySensors libraries)
                                           DATE: 20160529/ last update: 20160530
                                           FILE: AWI_Send.ino
                                           LICENSE: Public domain
                                          
                                           Hardware: ATMega328p board w/ NRF24l01
                                          	and MySensors 2.0
                                          	
                                          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
                                          */
                                          
                                          
                                          //****  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
                                          
                                          #define MY_NODE_ID 250
                                          #define NODE_TXT "Q 250"								// Text to add to sensor name
                                          
                                          //#define MY_PARENT_NODE_ID 42							// fixed parent to controller when 0 (else comment out = AUTO)
                                          
                                          
                                          // #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)
                                          
                                          #include <SPI.h>
                                          #include <MySensors.h>  
                                          
                                          // display
                                          #include <Wire.h>											// I2C
                                          #include <LiquidCrystal_I2C.h>								// LCD display with I2C interface
                                          
                                          
                                          // 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 counterChild 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(counterChild, V_PERCENTAGE);		// Send value
                                          
                                          // ***** LCD
                                          //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
                                          
                                          void setup() {
                                          	Wire.begin();  // I2C
                                              // ** LCD display **
                                              // LCD 2 lines * 16 char.
                                              lcd.begin(16, 2);
                                              lcd.setBacklight(HIGH);
                                              lcd.setCursor(0, 0);
                                          	lcd.print("AWI Quality nRF24");
                                          
                                          	for(int i= 0 ; i <  messageCounterMax ; i++){		// init stores for moving averages
                                          		failStore[i] = true ;
                                          		missedStore[i] = true ;
                                           	}
                                          	missedStorePointer = failStorePointer = 0 ;
                                          	delay(1000);
                                          }
                                          
                                          void presentation(){
                                          // MySensors
                                          	present(counterChild, S_DIMMER, "Quality counter " NODE_TXT) ;  // counter uses percentage from dimmer value
                                          }
                                          
                                          
                                          void loop() {
                                          	// Sprint("count:") ; Sprintln(messageCounter) ;
                                          	LCD_local_display();
                                          	missedStore[failStorePointer] = false  ; 			// set slot to false (ack message needs to set) ; 
                                          	boolean succes = failStore[failStorePointer] = send(counterMsg.setDestination(DESTINATION_NODE).set(failStorePointer), true);  // send to destination with ack
                                          	if (!succes){
                                          		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
                                          }
                                          
                                          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 LCD_local_display(void){
                                          /* prints all available variables on LCD display with units
                                          */
                                          	
                                              char buf[17]; 											// buffer for max 16 char display
                                              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);
                                          }
                                          
                                          
                                          karl261K Offline
                                          karl261K Offline
                                          karl261
                                          wrote on last edited by karl261
                                          #24

                                          @AWI Strange, with the latest sketch I get

                                          nrf-quality-meter.ino:88:34: error: invalid conversion from 'int' to 't_backlighPol' [-fpermissive]
                                          In file included from nrf-quality-meter.ino:45:0:
                                          C:\Dokumente und Einstellungen\Philipp\Eigene Dateien\Arduino\libraries\LiquidCrystal/LiquidCrystal_I2C.h:53:4: error: initializing argument 3 of 'LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t, uint8_t, t_backlighPol)' [-fpermissive]
                                          LiquidCrystal_I2C (uint8_t lcd_Addr, uint8_t backlighPin, t_backlighPol pol);
                                          ^
                                          invalid conversion from 'int' to 't_backlighPol' [-fpermissive]

                                          compiling...

                                          It works using the other line...

                                          // ***** LCD
                                          //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
                                          
                                          AWIA 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          10

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.0k

                                          Posts


                                          Copyright 2019 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