Closed fireghostea closed 6 months ago
Hey, were you able to find a solution to this problem?
No idea on this one still.
Is this in any way connected with the problem I have?
If I am running more than 5 nodes in a mesh with an RPi as the master and Arduino as the slaves restarting everything I will have one of the nodes struggling to connect. It may occasionally get in but soon drops out again and then can't reconnect. Deleting dhcplist.txt on the RPi fixes the problem. Subsequent restarts and the problem comes back, but maybe not immeadiatly.
I have seriously considered having the code delete dhcplist.txt on startup, but felt it was a retrograde step. The dhcplist is there for a reason.
Pete
Do you know if the node struggles on net level 1 more than a higher level? I don't think the problem is with the dhcplist.txt.
BTW, @Doubletop12 you should open a new issue. Based on what you describe, I don't think this issue is actually related. It might also help to know the exact hardware used (eg RPi variant, Arduino variant, if radio module is PA/LNA or not, etc).
Debugging when the controller is up
Debugging when requesting a new address, without initializing the controller.
This is a memory overflow into network.frame_buffer . When the controller goes up there is no problem, then when running garbage enters this memory cell. I am looking for a solution to the problem and will update.
update: When I ignore the byte in the 9th place (network.frame_buffer[9] ), everything works out, but I understand that this is not the final solution, we need to find out why the addresses smaller than 1 BYTE are garbage.
@naty6458 Hey there, I'm a little confused on exactly how you are encountering this issue, can you explain a bit more or provide steps to recreate it?
When I boot to the microcontroller, getting the addresses works fine. And when entering the requestAddress function without initializing the controller, entering the BYTE ARRAY type variable named network.frame_buffer in the 9th place is garbage. This causes obtaining an address that is one BYTE in size (for example 04 01 044 ....) to insert another address that is invalid.
Thats what I don't understand, if you haven't initialized the controller, the code should never get to that point...
But the fact is that it does get there, there must be some kind of bug. I specifically use the library with STM32 so there may be some adjustment that I didn't do properly, but there is an example where someone initially uploaded the thread that he uses with ARDUINO and the problem also appears with him.(https://youtu.be/uxRRYpss-Ew)
In the video I would suggest simple hardware problems or something like that, I don't see it returning bad values.
In commenting out the setNodeID, the OP is simply creating two master nodes on the same channel which may communicate, but is unsupported. Are you also commenting out setNodeID() to get it functioning?
If sending the message fails + checkConnection = fasle = , I perform SETUP again. And regarding your question about the setNodeID() I tried with calling it in SETUP and also tried without. no change .
Only when I skip this BYTE everything works fine
And regarding your question about the setNodeID() I tried with calling it in SETUP and also tried without. no change .
Hmm, there should be a change, regardless of this issue. The code will not work properly without a valid nodeID. Are you able to test with one of the included examples and see if you can reproduce the issue because I'm kind of lost in recreating an issue?
I used the example here in GIT .
https://github.com/nRF24/RF24Mesh/blob/master/examples/RF24Mesh_Example/RF24Mesh_Example.ino
The syntax is slightly different but the logic is exactly the same, so it can be seen in DEBUGING that an unwanted value enters the address. (I have attached a photo)
I'm also having trouble understanding the issue posed by @naty6458. It would have been better to create a new issue because I fail to see how the original issue and @naty6458 issue are related.
@naty6458 Your issue might be due to byte alignment differences in the various MCUs that you are using. Are all nodes running from a STM32? BTW, STM32 is a vague description. Which exact STM32 chip(s) are you using (ie STM32F103C8 for blue pill, STM32F411CEU6 for black pill)?
First, sorry for the rush. Here is the board I use.
https://stm32-base.org/boards/STM32F407VET6-STM32-F4VE-V2.0.html
for all nodes? Or are you using an RPi for another node?
My network setup is like this.
Between the RPI everything works fine. (And this is after I lowered the speed of the SPI to 4MHZ)
And this is after I lowered the speed of the SPI to 4MHZ
for all nodes? Sorry, I'm still trying to extract the steps to reproduce. I don't have a STM32F407 to test.
This line solved the problem. I check the new address level. If it is one level above the NODE address that offered the address. I get the address. If not (it's illegal) I ignore the BYTE in the 9th position of the BUFFER.
And this is after I lowered the speed of the SPI to 4MHZ
for all nodes? Sorry, I'm still trying to extract the steps to reproduce. I don't have a STM32F407 to test.
for both RPI , i change the spi speed to 4MHZ
I'm curious to see if what master is sending back as the assigned address is the same address received.
Do you have debugging enabled on master? You would have to build pyRF24 from source. See the hint in "Using a Specific RF24 driver".
You are absolutely right, it is very interesting to see what the MASTER really sends. I will try to compile it with DEBUG enabled and update.
But in my opinion it is not related to him because when I restart the STM I get 0X00 in this BYTE. That's why it indicated to me the problem with the controller.
Nevertheless, I will try to match it with the MASTER
Just so you understand how it works for me now nicely, I lowered the TIMEOUT to 25 ms.. :-)
I fear that your fix introduces a regression for nodes requesting an address directly from net level 1. But I need to see real code (not some pictures of snippet that leave out other modifications).
But in my opinion it is not related to him
My concern is that the RPi is sending a byte-aligned structure and the STM32 is not using a byte-aligned struct to receive it.
I'm curious to see if what master is sending back as the assigned address is the same address received.
Do you have debugging enabled on master? You would have to build pyRF24 from source. See the hint in "Using a Specific RF24 driver".
Indeed, as we thought, I do not receive it from the MASTER, I printed everything that came in from the SPI.
Indeed, as we thought, I do not receive it from the MASTER
Just so I understand perfectly, does this mean that the address sent in byte 8 and 9 (by RPi master) is not the same address received in byte 8 and 9 (by STM32)?
Very true, I found the problem from the root about you. What I received from the SPI did not pass accurately to the functions that called the basic function, RF24::read_payload, I fixed it and now everything works.
after fix
Now I run the original RF24Mesh.cpp file without changes and everything works. Thank you very much!
If it is interesting and you want to add support for ST. I shared the files that work for me now with MESH. Thank you very much indeed.
I remembered a very important thing that I added to RPI...
ON MASTER LOOP:
time.sleep(sys.float_info.min)
try:
while True:
mesh.update()
mesh.dhcp()
while network.available():
header, payload = network.read()
print(f"Received message {header.to_string()}")
time.sleep(sys.float_info.min)
except KeyboardInterrupt:
print("powering down radio and exiting.")
radio.power = False
ON NODE LOOP:
time.sleep(sys.float_info.min)
try:
while True:
# Call mesh.update to keep the network updated
mesh.update()
if (millis() - TIMER) >= 1000:
TIMER = millis()
if not mesh.write(struct.pack("L", TIMER), ord("M")):
# If a write fails, check connectivity to the mesh network
if not mesh.check_connection():
# The address could be refreshed per a specified time frame
# or only when sequential writes fail, etc.
print("Send fail. Renewing Address...")
while mesh.renew_address() == MESH_DEFAULT_ADDRESS:
print("Renewing Address...")
else:
print("Send fail, Test OK")
else:
print("Send OK:", TIMER)
time.sleep(sys.float_info.min)
except KeyboardInterrupt:
print("powering down radio and exiting.")
radio.power = False
If it is interesting and you want to add support for ST. I shared the files that work for me now with MESH.
We already do support STM32 platforms https://github.com/nRF24/RF24Mesh/blob/e0d390c5c463a1d225bbd74f24f883091188add1/library.json#L45 But we are restricted to functionality in the Arduino framework.
Given the zip file you posted, I don't see a meaningful fix in the RF24Mesh sources
```diff diff --git a/RF24Mesh.h b/RF24Mesh.h index a1223ea..87ffced 100644 --- a/RF24Mesh.h +++ b/RF24Mesh.h @@ -26,7 +26,7 @@ #define MESH_ADDR_RELEASE 197 #define MESH_ID_LOOKUP 198 -#define MESH_BLANK_ID 65535 +#define MESH_BLANK_ID 0xffff #if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny84__) #define RF24_TINY diff --git a/RF24Mesh_config.h b/RF24Mesh_config.h index 303746e..c163272 100644 --- a/RF24Mesh_config.h +++ b/RF24Mesh_config.h @@ -21,7 +21,7 @@ #endif // un-comment for non-master nodes not running on ATTiny MCUs -//#define MESH_NOMASTER +#define MESH_NOMASTER /***Advanced User Config***/ /** @@ -38,7 +38,7 @@ * @see RF24Mesh::renewAddress() */ #ifndef MESH_RENEWAL_TIMEOUT - #define MESH_RENEWAL_TIMEOUT 7500 + #define MESH_RENEWAL_TIMEOUT 30 #endif // MESH_RENEWAL_TIMEOUT /** @@ -57,7 +57,7 @@ /**************************/ /*** Debug ***/ //#define MESH_DEBUG_MINIMAL /** Uncomment for the Master Node to print out address assignments as they are assigned */ -//#define MESH_DEBUG /** Uncomment to enable debug output to serial **/ +#define MESH_DEBUG /** Uncomment to enable debug output to serial **/ /**************************/ /*** Other Configuration ***/ ```
The only changes you made to RF24Network are mostly superfluous except removing the radio.isValid()
call in RF24Network::begin()
(not a good idea)
```diff
diff --git a/RF24Network.cpp b/RF24Network.cpp
index d6edab8..d0c5d8d 100644
--- a/RF24Network.cpp
+++ b/RF24Network.cpp
@@ -7,6 +7,7 @@
*/
#include "RF24Network_config.h"
+
#if defined(RF24_LINUX)
#include
There is A LOT of dirty hacking going on in the RF24 lib sources. Adding code that is specific to STM32 chips is not as easy as you might think. The HAL libs provided by ST are not the best cross-compatible set of API; the HAL API for STM32F1xx chips is not completely identical as the HAL API for the STM32F4xx chips.
```diff
diff --git a/RF24.cpp b/RF24.cpp
index 9e5b4a8..a7d8c69 100644
--- a/RF24.cpp
+++ b/RF24.cpp
@@ -12,121 +12,24 @@
/****************************************************************************/
-void RF24::csn(bool mode)
+void RF24::csn(GPIO_PinState mode)
{
-#if defined(RF24_TINY)
- if (ce_pin != csn_pin) {
- digitalWrite(csn_pin, mode);
- }
- else {
- if (mode == HIGH) {
- PORTB |= (1 << PINB2); // SCK->CSN HIGH
- delayMicroseconds(RF24_CSN_SETTLE_HIGH_DELAY); // allow csn to settle.
- }
- else {
- PORTB &= ~(1 << PINB2); // SCK->CSN LOW
- delayMicroseconds(RF24_CSN_SETTLE_LOW_DELAY); // allow csn to settle
- }
- }
- // Return, CSN toggle complete
- return;
-
-#elif defined(ARDUINO) && !defined(RF24_SPI_TRANSACTIONS)
- // Minimum ideal SPI bus speed is 2x data rate
- // If we assume 2Mbs data rate and 16Mhz clock, a
- // divider of 4 is the minimum we want.
- // CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz
-
- #if !defined(SOFTSPI)
- // applies to SPI_UART and inherent hardware SPI
- #if defined(RF24_SPI_PTR)
- _spi->setBitOrder(MSBFIRST);
- _spi->setDataMode(SPI_MODE0);
-
- #if !defined(F_CPU) || F_CPU < 20000000
- _spi->setClockDivider(SPI_CLOCK_DIV2);
- #elif F_CPU < 40000000
- _spi->setClockDivider(SPI_CLOCK_DIV4);
- #elif F_CPU < 80000000
- _spi->setClockDivider(SPI_CLOCK_DIV8);
- #elif F_CPU < 160000000
- _spi->setClockDivider(SPI_CLOCK_DIV16);
- #elif F_CPU < 320000000
- _spi->setClockDivider(SPI_CLOCK_DIV32);
- #elif F_CPU < 640000000
- _spi->setClockDivider(SPI_CLOCK_DIV64);
- #elif F_CPU < 1280000000
- _spi->setClockDivider(SPI_CLOCK_DIV128);
- #else // F_CPU >= 1280000000
- #error "Unsupported CPU frequency. Please set correct SPI divider."
- #endif // F_CPU to SPI_CLOCK_DIV translation
-
- #else // !defined(RF24_SPI_PTR)
- _SPI.setBitOrder(MSBFIRST);
- _SPI.setDataMode(SPI_MODE0);
-
- #if !defined(F_CPU) || F_CPU < 20000000
- _SPI.setClockDivider(SPI_CLOCK_DIV2);
- #elif F_CPU < 40000000
- _SPI.setClockDivider(SPI_CLOCK_DIV4);
- #elif F_CPU < 80000000
- _SPI.setClockDivider(SPI_CLOCK_DIV8);
- #elif F_CPU < 160000000
- _SPI.setClockDivider(SPI_CLOCK_DIV16);
- #elif F_CPU < 320000000
- _SPI.setClockDivider(SPI_CLOCK_DIV32);
- #elif F_CPU < 640000000
- _SPI.setClockDivider(SPI_CLOCK_DIV64);
- #elif F_CPU < 1280000000
- _SPI.setClockDivider(SPI_CLOCK_DIV128);
- #else // F_CPU >= 1280000000
- #error "Unsupported CPU frequency. Please set correct SPI divider."
- #endif // F_CPU to SPI_CLOCK_DIV translation
- #endif // !defined(RF24_SPI_PTR)
- #endif // !defined(SOFTSPI)
-
-#elif defined(RF24_RPi)
- if (!mode)
- _SPI.chipSelect(csn_pin);
-#endif // defined(RF24_RPi)
-
-#if !defined(RF24_LINUX)
- digitalWrite(csn_pin, mode);
- delayMicroseconds(csDelay);
-#else
- static_cast
What you've basically done is add support for STM32Cube IDE specific to your board. See nRF24/RF24#872 for the reason why we stopped developing a solution toward STM32Cube support.
I remembered a very important thing that I added to RPI... ...
time.sleep(sys.float_info.min)
I don't think adding time.sleep(sys.float_info.min)
to the pyrf24 examples would be a meaningful contribution.
>>> import sys
>>> sys.float_info.min # for Windows 11
2.2250738585072014e-308
>>> help(sys.float_info)
| float_info(iterable=(), /)
|
| sys.float_info
|
| A named tuple holding information about the float type. It contains low level
| information about the precision and internal representation. Please study
| your system's :file:`float.h` for more information.
Given that sys.float_info
is platform specific, I don't see how waiting for ~2 seconds fixes anything. IMHO, adding delays to buggy source code is the sign of a beginner trying to hide an unknown problem.
Hi, thanks for the reply. That's right, I'm talking about STM CUBE and not Arduino IDE. The reason I downloaded the
bool RF24::isValid()
{
return ce_pin != RF24_PIN_INVALID && csn_pin != RF24_PIN_INVALID;
}
Because it is not relevant when you use STM CUBE. You configure the SPI pins through the STM interface. Therefore there is no reason to correct the ID of the pins.
Regarding the RPI delay, I added the smallest value possible in FLOAT so that there is as fast an update to the network as possible.
It is clear to me that in order to release a version that is suitable for all types of users, there is still a lot of work to be done. But the files I shared can be a nice start to support STM CUBE. And by the way, this can be for any STM board, not specific to mine. All you have to do is set the pins in RF24_config.h
Given that sys.float_info is platform specific, I don't see how waiting for ~2 seconds fixes anything. IMHO, adding delays to buggy source code is the sign of a beginner trying to hide an unknown problem.
It's not 2 seconds, it's 2 seconds to the power of e minus 308. This is the smallest number of the Python on the RPI The point I was trying to convey is that a small delay should be put there. If not it simply does not work or works really badly, at least in my case of the RPI3
@TMRh20 I think we need to close this 6 year old issue. This is the second time it was hijacked by someone with an unrelated problem. Now it is just a misleading dead end for anyone trying troubleshoot their specific problem. If someone comes across with a seemingly similar problem, then they can open a new issue and just reference it using "#137".
@naty6458 I'm glad you got it working you you.
But the files I shared can be a nice start to support STM CUBE
If you would like to contribute towards STM Cube IDE support then please use nRF24/RF24#872. We already have a branch setup to experiment with STM Cube IDE support.
Because it is not relevant when you use STM CUBE. You configure the SPI pins through the STM interface. Therefore there is no reason to correct the ID of the pins.
Maybe this makes sense to you because your board doesn't require you to use jumper cables. But radio.isValid()
was added as a convenience for those who spent too much time troubleshooting software when all they did was connect the wrong pins with jumper cables.
The point I was trying to convey is that a small delay should be put there. If not it simply does not work or works really badly, at least in my case of the RPI3
I stand by the fact that adding a delay only hides a real problem, which might have been fixed (this morning) in nRF24/RF24#952 but not released in pyRF24 yet.
Hey ,
If you would like to contribute towards STM Cube IDE support then please use https://github.com/nRF24/RF24/issues/872. We already have a branch setup to experiment with STM Cube IDE support.
Thanks for sharing, I didn't know there was such a branch for STM CUBE. It looks much more professional than what I did. I'll try it in a hurry.
Maybe this makes sense to you because your board doesn't require you to use jumper cables. But radio.isValid() was added as a convenience for those who spent too much time troubleshooting software when all they did was connect the wrong pins with jumper cables.
You are absolutely right about this.
I stand by the fact that adding a delay only hides a real problem, which might have been fixed (this morning) in https://github.com/nRF24/RF24/pull/952 but not released in pyRF24 yet.
I can't wait for this version to be released.
Thank you very much for the guidance and consideration.
I can't wait for this version to be released.
You can test it out by installing pyrf24 from source, but you have to update the RF24 submodule first. There's also some preliminary support for RPi5 in RF24 master branch.
cd pyRF24/RF24
git checkout master
git pull
cd ../
pip install -v .
i explain my problem completely in this video https://youtu.be/uxRRYpss-Ew