nRF24 / RF24Mesh

OSI Layer 7 Mesh Networking for RF24Network & nrf24L01+ & nrf52x devices
http://nrf24.github.io/RF24Mesh
GNU General Public License v2.0
422 stars 154 forks source link

ATTiny85 + nRF24L01+ - Resetting during mesh.begin() #200

Closed pprakash closed 2 years ago

pprakash commented 2 years ago

First of all, thank you for this wonderful suite of libraries to support RF24. I have been experimenting with this setup using Pi Zero + Uno successfully. I was able to establish a Mesh Network between 2 UNO boards and Pi.

I wanted to try out the ATTiny85 with 3 Pin configuration and hence wrote below script. I noticed that the ATTiny85 is resetting itself during the mesh.begin() section. If I remove the module its looping in the while loop, I could guess this with all those flash codes between the sections. Due to limited space on flash couldn't add SoftwareSerial for additional messages on this error.

RF24Network example works fine.

Versions of Libraries Used:

Using library RF24 at version 1.4.2 in folder: C:\Users\lenovo\Documents\Arduino\libraries\RF24 Using library SPI at version 2.0.0 in folder: C:\Users\lenovo\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.5.2\libraries\SPI Using library RF24Network at version 1.0.16 in folder: C:\Users\lenovo\Documents\Arduino\libraries\RF24Network Using library RF24Mesh at version 1.1.6 in folder: C:\Users\lenovo\Documents\Arduino\libraries\RF24Mesh

/*
   RF24Mesh On ATTiny85
   3 Pin configuration

   Arduino Pin <--> Physical Pin
   0 <--> 5 / PB0 (MISO)
   1 <--> 6 / PB1 (MOSI)
   2 <--> 7 / PB2 (SCK)
   3 <--> 2 / PB3
   4 <--> 3 / PB4
   5 <--> 1 / PB5 / Reset

*/

#include "RF24.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
//#include <SPI.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
//#include <printf.h>

#define nodeID 29 // Should be unique. These pins are part of PCI0 interrupt group
#define deviceID 210 // Should be unique. Values 1 - 254 Only.
#define Ch_Num 29 // Channel Number

bool radioOn = false;
#define CE_PIN 3
#define CS_PIN 3 // if 4 it will be physical pin

RF24 radio(CE_PIN, CS_PIN);
RF24Network network(radio);
RF24Mesh mesh(radio, network);

void flash(byte repeat, byte gap) {

  for ( int i = 0; i < repeat; i++) {
    digitalWrite(4, HIGH);
    delay(gap);
    digitalWrite(4, LOW);
    delay(gap);
  }
  delay(250);
}

void setup() {
  pinMode(4, OUTPUT);

  mesh.setNodeID(nodeID);
  flash(2, 50);
  while (!mesh.begin(Ch_Num, RF24_250KBPS)) {
    flash(1, 500);
  }
  flash(2, 250);
  radioOn = true;

}

byte Value = 0; // Let's start with Cancel mode. RESET Button is cancel.
byte lastValue = 3;

void chk_mesh_connect() {
  if ( ! mesh.checkConnection() ) {
    //refresh the network address

    if (!mesh.renewAddress()) {
      //If address renewal fails, reconfigure the radio and restart the mesh
      //This allows recovery from most if not all radio errors
      //if (!mesh.begin(Ch_Num, RF24_250KBPS)) {
      mesh.begin(Ch_Num, RF24_250KBPS);
    }
  }
}

void loop() {
  //dataBuff.sequence = count;
  byte btnValue = 0;
  if ( lastValue != Value ) {
    if (radioOn) {
      chk_mesh_connect();
    } else {
      radio.powerUp();
      radioOn = true;
      chk_mesh_connect();
    }
    mesh.update();
    if (!mesh.write(deviceID, &Value, sizeof(deviceID))) {
      // If a write fails, check connectivity to the mesh network
      flash(4, 250);
    } else {
      flash(2, 100);
    }

  }
}
TMRh20 commented 2 years ago

Have you double checked your wiring? It may be work trying 4-pin mode and double checking your pin connections because 3-pin mode can be a bit finicky to get working. Afaik 3 pin mode still works although I don't have the ability to test it right now...

2bndy5 commented 2 years ago

IIRC, 3 pin approach might need to tweak the CSN delay value used in RF24::csn(). We have an example sketch in the RF24/examples/rf24_ATTiny/timingSearch3pin folder that does test incremented intervals (in microseconds). The resulting values should be used in RF24/utility/ATTiny/RF24_arch_config.h under RF24_CSN_SETTLE_HIGH_DELAY and RF24_CSN_SETTLE_LOW_DELAY macros.

pprakash commented 2 years ago

Have you double checked your wiring? It may be work trying 4-pin mode and double checking your pin connections because 3-pin mode can be a bit finicky to get working. Afaik 3 pin mode still works although I don't have the ability to test it right now...

RF24Network works fine with the same configuration. Below is the sample sketch from the same.

/*
   RF24Mesh On ATTiny85
   3 Pin configuration

   Arduino Pin <--> Physical Pin
   0 <--> 5 / PB0 (MISO)
   1 <--> 6 / PB1 (MOSI)
   2 <--> 7 / PB2 (SCK)
   3 <--> 2 / PB3
   4 <--> 3 / PB4
   5 <--> 1 / PB5 / Reset

*/

#include "RF24.h"
#include "RF24Network.h"
#include "RF24Mesh.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>

#define nodeID 29 // Should be unique. These pins are part of PCI0 interrupt group
#define deviceID 210 // Should be unique. Values 1 - 254 Only.
#define Ch_Num 29 // Channel Number

bool radioOn = false;
#define CE_PIN 3
#define CS_PIN 3 // if 4 it will be physical pin

RF24 radio(CE_PIN, CS_PIN);
RF24Network network(radio);

const uint16_t this_node = 01;       // Address of our node in Octal format
const uint16_t other_node = 00;      // Address of the other node in Octal format

const unsigned long interval = 2000; // How often (in ms) to send 'hello world' to the other unit

unsigned long last_sent;             // When did we last send?
unsigned long packets_sent;          // How many have we sent already

struct payload_t {                   // Structure of our payload
  unsigned long ms;
  unsigned long counter;
};

void flash(byte repeat, byte gap) {

  for ( int i = 0; i < repeat; i++) {
    digitalWrite(4, HIGH);
    delay(gap);
    digitalWrite(4, LOW);
    delay(gap);
  }
  delay(250);
}

void setup() {
  pinMode(4, OUTPUT);

  flash(2, 50);
  while (!radio.begin()) {
    flash(1, 500);
  }
  flash(2, 250);
  radio.setChannel(Ch_Num);
  delay(1000);
    flash(2, 250);
    delay(1000);
    flash(2, 250);
  radioOn = true;
    network.begin(this_node);
    flash(1, 500);
}

byte Value = 0; // Let's start with Cancel mode. RESET Button is cancel.
byte lastValue = 3;

void loop() {
  byte btnValue = 0;
    network.update();
    payload_t payload = { millis(), Value };
    RF24NetworkHeader header(/*to node*/ other_node);
    if(!network.write(header, &payload, sizeof(payload))){
      flash(4, 250);
    } else {
      flash(2, 100);
    }
  delay(1000);
  }

Edit: cleaned up the commented out lines.

pprakash commented 2 years ago

IIRC, 3 pin approach might need to tweak the CSN delay value used in RF24::csn(). We have an example sketch in the RF24/examples/rf24_ATTiny/timingSearch3pin folder that does test incremented intervals (in microseconds). The resulting values should be used in RF24/utility/ATTiny/RF24_arch_config.h under RF24_CSN_SETTLE_HIGH_DELAY and RF24_CSN_SETTLE_LOW_DELAY macros.

I followed this step and setup an UNO as Master, as I couldn't get the mesh.addrListTop & mesh.addrListworking in Python to print the assigned addresses in Master.

I could see that ATTiny85 is getting the node address but only if there is another node (pi in my case as a node) joining the mesh else its not getting the address. Post getting the node address, still I think the exit status of mesh.begin() is non-Zero.

18:26:29.364 ->  
18:26:29.364 -> ********Assigned Addresses********
18:26:29.411 -> **********************************
18:26:34.395 ->  
18:26:34.395 -> ********Assigned Addresses********
18:26:34.435 -> NodeID: 10 RF24Network Address: 05
18:26:34.475 -> NodeID: 29 RF24Network Address: 04
18:26:34.515 -> **********************************

ATTiny85(NodeID:29) was On at 18:26:29 but it didn't report any address. Pi(NodeID:10) was activated as a Node at 18:26:34, both Pi and ATTiny85 have been allocated Network addresses. But ATTiny85 is not transmitting any data after that.

18:32:28.960 -> ********Assigned Addresses********
18:32:29.007 -> NodeID: 10 RF24Network Address: 05
18:32:29.054 -> NodeID: 29 RF24Network Address: 04
18:32:29.101 -> **********************************
18:32:33.966 ->  
18:32:33.966 -> ********Assigned Addresses********
18:32:34.013 -> NodeID: 10 RF24Network Address: 05
18:32:34.060 -> NodeID: 29 RF24Network Address: 045
18:32:34.107 -> **********************************

Network Address of ATTiny85 changes, but Pi remains constant during multiple restart of Pi.

TMRh20 commented 2 years ago

Hmmm, there seems to be similar issue here: https://github.com/nRF24/RF24Mesh/issues/138 and as you can see, nothing has been done in a while to address the issue. This one could be a bit difficult to solve since dealing with ATTinys and limited debugging output. Very interesting that it works with RF24Network too. I just tested an ATTiny with 4-pin mode and it seems to need another node active in order to join the mesh. This is a weird one...

TMRh20 commented 2 years ago

Adding #define SLOW_ADDR_POLL_RESPONSE 150 to RF24Network_config.h on the master node and recompiling everything seems to do the trick on my end. Could you test this on your end?

2bndy5 commented 2 years ago

Adding #define SLOW_ADDR_POLL_RESPONSE 150 to RF24Network_config.h on the master node

This seems like an eternity. If this works to solve the issue, then we might want to bump the wait time for POLL responses during the handshake process because I'm afraid this eternity might break compatibility with faster devices.

https://github.com/nRF24/RF24Mesh/blob/6f8091e1e0f63f68ea8b7b516ded4c6ebcca904f/RF24Mesh.cpp#L322

All of this seems like a workaround for the real point-of-failure: not using auto-ack during handshake process on network level 0. This PoF is why I had to add the SLOW_ADDR_POLL_RESPONSE macro to begin with.

TMRh20 commented 2 years ago

I don't see how we could use auto-ack for polling etc, since it pretty much needs to be multicast as far as I am aware. I don't think 150ms is quite necessary, but as a starting point, I figured it should be enough.

2bndy5 commented 2 years ago

I should open a new thread to discuss my concern and not distract from this issue. @pprakash please let us know if using

// in RF24Network_config.h for mesh master node
#define SLOW_ADDR_POLL_RESPONSE 150

works with the 3-pin approach.

@TMRh20 did this negatively affect other non-ATTiny nodes (when connecting to mesh via direct_to master node without a middle-man node)?

TMRh20 commented 2 years ago

Not really, my other nodes were all able to connect fine once I re-enabled them after testing.

pprakash commented 2 years ago

Adding #define SLOW_ADDR_POLL_RESPONSE 150 to RF24Network_config.h on the master node and recompiling everything seems to do the trick on my end. Could you test this on your end?

Thanks, this solution works.

Tested with One Master (UNO) and ATTiny85 in 3Pin Configuration. Will test more with 2 Nodes ( ATTiny85 and Pi) as well tonight.

Having a query, can you guide me on defining for Python in Raspberry Pi as Master?

2bndy5 commented 2 years ago

Having a query, can you guide me on defining for Python in Raspberry Pi as Master?

You might need to only re-install the C++ driver for RF24Network - the python wrapper is linked to whatever is installed from the C++ side. I put in an option to do this for those using CMake.

cd RF24Network
mkdir build
cd build
cmake .. -DSLOW_ADDR_POLL_RESPONSE=150
make
sudo make install

You should see a message from the cmake .. cmd saying

SLOW_ADDR_POLL_RESPONSE set to 150

If installing cmake isn't possible, then it might be possible to use the traditional Makefile (cmake support is new for us here). I have not tried this:

cd RF24Network
make -DSLOW_ADDR_POLL_RESPONSE=150
sudo make install

I think that the CCFLAGS env var is appropriated in the old Makefile for RF24Network, so that approach might not work.

pprakash commented 2 years ago

Having a query, can you guide me on defining for Python in Raspberry Pi as Master?

You might need to only re-install the C++ driver for RF24Network - the python wrapper is linked to whatever is installed from the C++ side. I put in an option to do this for those using CMake.

cd RF24Network
mkdir build
cd build
cmake .. -DSLOW_ADDR_POLL_RESPONSE=150
make
sudo make install

You should see a message from the cmake .. cmd saying

SLOW_ADDR_POLL_RESPONSE set to 150

Followed the above steps, started getting dependency errors, hence did below steps

  1. manually update RF24Network_config.h in RF24Network/ directory
  2. Removed librf24* files from /usr/local/lib
  3. ran the install.sh script to install the libraries again.

After above steps, ATTiny85 is connecting and sending messages to Pi(Python), but its pretty unstable. When it connects to UNO Master the things are stable. with Pi it drops almost 30 - 40 % of transmissions.

2bndy5 commented 2 years ago

You might have to play with the value for SLOW_ADDR_POLL_RESPONSE. When testing that feature in Linux, I was using a value of 15 to get a pretty stable master node (20 started getting flaky for me though). Although I wasn't trying to compensate for an ATTiny child node when I was playing with the value, so...

Try something a bit smaller than 150. If that makes it worse, then try something larger than 150... Keep playing with it.

This suggestion only focuses on mesh.begin() problem. If normal transmissions from ATTiny are being dropped, then SLOW_ADDR_POLL_RESPONSE won't help that.

TMRh20 commented 2 years ago

Another variable to be cognizant about is the radio.txDelay variable. This can be modified on-the-fly without recompiling. It controls the switching speed of devices when switching to transmit mode, so it might be worth playing around with this variable too, to see which timing modifications result in the best performance.

pprakash commented 2 years ago

Thanks @2bndy5 @TMRh20 ... will keep trying different settings and share the result in couple of days.

2bndy5 commented 2 years ago

I should mention that radio.txDelay is auto-configured by the setDataRate() function, so call that first before changing the txDelay.

pprakash commented 2 years ago

Finally I could have a stable connection to both UNO and Pi Masters. Below are my experience.

  1. ATTiny85 - Have to be running at least at 8MHz, 1MHz is a big NO.
  2. When set at 8MHz, works fine without #define SLOW_ADDR_POLL_RESPONSE 150 in RF24Network_config.h
  3. 3 PIN Mode works for sure, except that it has slightly higher power consumption during sleep modes
  4. RC value used is 22K and 10pF with supply of 3V.
  5. Try to avoid delay() in the code.

Once again, Thanks @TMRh20 @2bndy5 for the wonderful library and excellent support.