jeelabs / jeelib

JeeLib for Arduino IDE: Ports, RF12, and RF69 drivers from JeeLabs
https://jeelabs.org/202x/sw/jeelib/
The Unlicense
490 stars 215 forks source link

There's a way to reset the rf module? #92

Open marcolettieri opened 8 years ago

marcolettieri commented 8 years ago

When the rf module is high stressed and/or far from other nodes the checkmessagereceived return ever false and i can not send on my rf module. But if turn off and on the device it start work again. I've debugged carefully my sketch but it seems to be the library/hardware no responding. There's so a way to reset the rf module without reboot the device?

glynhudson commented 8 years ago

I have also noticed this issue. Calling rf12_initialize resets the module. We do this every 60s:

    if ((now - last_rf_rest) > RF_RESET_PERIOD) {
      rf12_initialize(nodeID, RF_freq, networkGroup);                             // Periodically reset RFM69CW to keep it alive :-( 
    }

https://github.com/openenergymonitor/emonpi/blob/rf_hang/Atmega328/emonPi_RFM69CW_RF12Demo_DiscreteSampling/emonPi_RFM69CW_RF12Demo_DiscreteSampling.ino#L250

I would love to get to the bottom of why such drastic action is required :-( However resetting does not take a long time and seems to have not detrimental effects on receiving or transmitting periodic RF data

marcolettieri commented 8 years ago

60s??? wow... the issue happens to us after a long time, randomly, but, if happens, usually after 2-3 days of continuous use. often after a few minutes / hours / day it back to work or is definitelly frozen. Reinitializing every 60 seconds has resolved the issue? how frequently do you send RF data?

I tried to do the rf12_initialize if i don't receive messages from minutes. On your experience try to do rf12_initalize when the device is in this undefined status is useless?

I tried the following without success..

   if(lastMessageTime>0 && millis()-lastMessageTime>10000){
       uint16_t spi_control = rf12_control(0x0000);
       if(spi_control==65535 || spi_control==0){
         Serial.println("Reitializing RF Module...");
        rf12_initialize(NODEID, RF12_433MHZ, NETWORKID, 0x0640);
        rf12_control(0xC623);
        rf12_control(0x9820);
        rf12_control(getChannelByID(channelID)); 
     }
   }
   if((lastMessageTime>0 && millis()-lastMessageTime>30000) || (lastMessageSentTime>0 && millis()-lastMessageSentTime>30000)){
       lastMessageTime=millis()-10000;
       lastMessageSentTime=millis()-10000;
       lastReceivedMessageID=0;
       Serial.println("RESTORE RF");
       rf12_recvDone();
       rf12_sleep(RF12_SLEEP);
       delay(500);
       rf12_sleep(RF12_WAKEUP);
       delay(100);
       rf12_recvDone();
       rf12_initialize(NODEID, RF12_433MHZ, NETWORKID, 0x0640);
       rf12_control(0xC623);
       rf12_control(0x9820);
       rf12_control(getChannelByID(channelID));
       rf12_recvDone();
   }
jcw commented 8 years ago

I would love to get to the bottom of why such drastic action is required :-(

Same here - that's the RF12 driver in native ("classic") mode? I've never seen this before...

glynhudson commented 8 years ago

It's running in RFM69CW mode:

# define RF69_COMPAT 1

60's is probably an overkill, issue only occurs occasionally every few days.

marcolettieri commented 8 years ago

So the only solution for you is a reinitialize every x seconds/minutes?

JohnOH commented 8 years ago

@lettierimarco would you be willing to give my test code a spin. It is derived from jeelib and a full git replacement: https://github.com/jcw/jeelib/tree/RFxConsole

marcolettieri commented 8 years ago

@JohnOH sure, but i repeat, the issue is quietly randomly, so difficult to reproduce. I've tryied to use your derived, unfortunately my RF module seems not initializing... tomorrow i'll try a merge for vital params

JohnOH commented 8 years ago

I may have incorrectly assumed you were having this problem with RFM69CW hardware. My adjustments in the RFM69 code are quite extensive. My tweaks for the RFM12B are indeed trivial.

FWIW I have not seen anything to concern me while operating RFM12B devices.

glynhudson commented 8 years ago

Hi John,

Have you got a summary of changes you have made to the default jeelib in your branch?

I may have incorrectly assumed you were having this problem with RFM69CW hardware. My tweaks for the RFM12B are indeed trivial. I have not seen anything to concern me while operating RFM12B devices.

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/jcw/jeelib/issues/92#issuecomment-202981103

JohnOH commented 8 years ago

I'm afraid I don't have a summary the changes evolved or quite a long period. A diff of the five RF69* files will show them.

marcolettieri commented 8 years ago

I've compiled your rfm12.cpp without # define RF69_COMPAT 1, my RF works but i don't know if my issue will reproduce again... Any idea why for my RFM12B ? Can i test something for a thoroughly investigate ? Has sense to reinitialize the rf12 module every 60seconds?

marcolettieri commented 8 years ago

I've forked jeelib and commit some little change i've done: https://github.com/lettierimarco/jeelib

jcw commented 8 years ago

I'd like to look into this issue - is there any more info which might help narrow this down?

PS. Strictly speaking, the answer to this issue is "yes": call rf12_initialize, but that's a workaround.

jcw commented 8 years ago

@glynhudson @lettierimarco - are we mixing RF69 and RF12 issues in this discussion by any chance? if so, please consider splitting off a separate one - I really want to help get to the bottom of this, but I'm going to have a very hard time if two problems are being mixed up...

marcolettieri commented 8 years ago

My issue happens using rf12.

jcw commented 8 years ago

I have just checked in two changes to the RF69 compat mode driver, i.e. inter-operating with an RF12 driver at the other end, which should substantially improve bad packet rejection and reduce dead-time - i.e. better noise rejection and fewer missed packets - with a huge thank-you to Martyn and John.

This change does not affect the RF12 driver side of things.

JohnOH commented 8 years ago

@lettierimarco can you post your full sketch with an indication as to where the code is returning permanent false (checkmessagereceived).

marcolettieri commented 8 years ago

@JohnOH I only supposed this... I can't reproduce the issue programmatically but it happens. I don't know if it could be connected to RF69 issue or not. Now I'm trying to detect in rf12_interrupt the FIFO Overflow bit and the power reset bit. I hope this can explain why my RF stop receive and sending until I restart my device. Sadly no one of them verified since I started the test (a week ago).

JohnOH commented 8 years ago

I don't think your issue is connected with the RF69 issue. Do you use rf12_canSend in your sketch? Are you unable to post a link to your sketch here?

glynhudson commented 8 years ago

@jcw I am using RFM69CW with # define RF69_COMPAT 1. Sounds good, I will setup a test including your latest commits 6f1af25695a51910d2bb8ca0e796a7edda028848

marcolettieri commented 8 years ago
void setup() {
  cli();  
  wdt_enable(WDTO_8S); 
  sei();
  wdt_reset();
  Serial.begin(SERIAL_BAUD);
  Serial.println("---> SETUP BEGIN");
  rst.debounceTime = 10;
  rst.heldDownTime = DEFAULT_HOLD_BUTTON_TIME;
  rst.multiclickTime = 50;
  send_buffer.init(200);
  send_buffer.clear();
  banList.init(32);
  banList.clear();
  pinMode(LINK_LED, OUTPUT);
  pinMode(TX_RX_LED, OUTPUT);
  pinMode(IDENTIFY_LED, OUTPUT);
  pinMode(RELAY_ON_LED, OUTPUT);
  pinMode(RELAYPIN, OUTPUT);
  pinMode(A6, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);

  digitalWrite(LINK_LED, LOW);
  digitalWrite(TX_RX_LED, LOW);
  digitalWrite(IDENTIFY_LED, LOW);
  digitalWrite(RELAY_ON_LED, LOW);

  Serial.println("Initializing threads...");

  PT_INIT(&powerMetering_pt);
  PT_INIT(&linkCheckVerifier_pt);
  PT_INIT(&configManager_pt);

  wdt_reset();

  Serial.println("Initializing RF Module...");
  rfReinitliazing =millis();
  //RFM12 initialization
  uint16_t channel = getChannelByID(channelID);
  rf12_initialize(NODEID, RF12_433MHZ, NETWORKID, channel);
  Serial.print("----> Setting RF Frequency ");Serial.print("(");Serial.print(channelID);Serial.print(") :");Serial.println(getChannelByID(channelID),HEX);
  wdt_reset();
  Serial.println("SETUP DONE! Firmware version: "__DATE__" "__TIME__);
  bootTime = millis(); 
}

void loop(){
  wdt_reset();

  //Verifica la pressione del pulsante di reset/accensione
  rst.Update();
  if(waitingConfiguration){
    setupConfiguration();
  }else {
        //Controlla il LINK LED in base al successo di validazione
        if(mainRoute.verified) {
          digitalWrite(LINK_LED,HIGH);
        } else {
          digitalWrite(LINK_LED,LOW);
        }
        wdt_reset();

        //check if a message arrived...
        checkMessageReceived();

        //Send RF Commands
        checkMessageToSend();

       wdt_reset();  
       if(lastMessageTime>0 && millis()-lastMessageTime>10000){
           //Serial.print("SERIAL :");
           //Serial.println(rf12_control(0x0000),DEC);
           uint16_t spi_control = rf12_control(0x0000);
           if(spi_control==65535 || spi_control==0){
            //RFM12 initialization
            uint16_t channel = getChannelByID(channelID);
            rf12_initialize(NODEID, RF12_433MHZ, NETWORKID, 0x0640);
         }
       }
    }
}

static void checkMessageReceived(){
  if(rf12_recvDone()) {
    if(rf12_crc == 0) {
        //manage packet
    }
  }
}

static void checkMessageToSend() {
  boolean ableToSend = false;
  ableToSend = (mainRoute.verified && tokenAcquired) || (!mainRoute.verified);

  if(send_buffer.getSize() > 0 && ableToSend) { 
    if(rf12_canSend()) {
      //populate buffer to send
      delay(10);
      rf12_sendStart(toSend.jeeDest, toSend.bytes, totLen);
      rf12_sendWait(0);
    }
  }
}

in rf12.cpp i'm trying this without success until now:

static void rf12_interrupt () {
       uint16_t r = rf12_xferSlow(cmd);
       if(r&0x2000)
           //manage Fifo Overflow occured
       else if(r&0x4000)
          //manage Power Reset occured

...

JohnOH commented 8 years ago

Might you try adding an } else { error-message } to the

if(rf12_canSend()) {
  //populate buffer to send
  delay(10);
  rf12_sendStart(toSend.jeeDest, toSend.bytes, totLen);
  rf12_sendWait(0);
} else {
    print an informative message
}
marcolettieri commented 8 years ago

I've already done this debug in past. I've a TDM of about 200 ms so is probably that canSend is false sometimes but is not a problem. Like i told in first post the problem is that when the issue happens i can't receive and send but the firmware is running. My first idea was that there is a interference on the RF but the issue happens, in a environment of 5 devices, only to one. After the issue happens sometimes the device can restore the RF in some minutes, hours or never more. So after depth check on my hardware and sketch i'm now analyzing the rf12 library. I've tested if there is some FIFO or Power issue with the improvment i've posted before since the rf12 library doesn't check this interrupt bit.

JohnOH commented 8 years ago

I am sorry to have covered old ground for you. I thought you may be locking up where rf12_canSend never returns true. In my case this has been an issue whereby the RF noise floor was never quiet enough for rf12_canSend to return true. I don't have any further ideas for you at this point.

glynhudson commented 8 years ago

So far so good 3 days and counting....

I have setup a test using latest JeeLib. If anyone is interested I have experimented with git submodules this has allowed me to associate the github libs (at a specific point) used in my project within the project repo itself without loosing association with the original lib repo.

Using this method of lib management has been fantastic for this example: I created a new dev branch 'rf-test' and in that branch fast-forwarded jeelib to the latest version and made the changes to code required for the test.

https://github.com/openenergymonitor/emonpi/commit/e96cb04ba8d4999a8381dd8cf620ff18fbd66afe

I have documented using sub modules here:

https://github.com/openenergymonitor/emonpi/tree/master/firmware/libraries

glynhudson commented 8 years ago

Still looking good :+1:

jcw commented 8 years ago

Great - declare victory before it decides to change its mind! :)