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.7k Views 33 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.
  • AWIA AWI

    @dakipro It would take a resistor and analog power reading to include basic power measurement. Current would vary between ~3mA and 70mA (with amplified radio).

    H Offline
    H Offline
    Heizelmann
    wrote on last edited by
    #41

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

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

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

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

      See further advanced project nRF24Doctor. Great thanks to @Technovation

      T 1 Reply Last reply
      0
      • H Heizelmann

        See further advanced project nRF24Doctor. Great thanks to @Technovation

        T Offline
        T Offline
        Technovation
        wrote on last edited by
        #43

        @heizelmann I'm happy to see that you can appreciate my work as a continuation of the nice job you already did on this thread.

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