nRF24 / RF24

OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
https://nrf24.github.io/RF24
GNU General Public License v2.0
2.19k stars 1.01k forks source link

[Request] Simplify Examples #658

Closed 2bndy5 closed 3 years ago

2bndy5 commented 3 years ago

Complex = overwhelming

Most people getting started with the nRF24L01 just need it to send data from 1 endpoint to another. The most basic GettingStarted.ino example does it both ways despite what the role variable is set to. This quickly leads to confusion about how the library should be used and how the transceiver actually works (especially since ACK payloads could be used to do the same exact thing only simpler).

Names are a guessing game

PingPair is not the most descriptive prefix to use in the example names. The first time I read it, I thought: "'pair' like in Bluetooth?" -- nope, its 'pair' like 2 devices used for 1 sketch. In fact, the most identifying part of the examples' names are abridged suffixes that require more intimate knowledge of the nRF24L01 features. e.g. "dyn" for dynamic payloads, "int"/"irq" for interrupt requests, "ack" for acknowledgment payloads... The names should be changed so that anyone can accurately guess what they're clicking on in Arduino IDE's example menu. e.g. "pingpair_dyn" to "RF24_dynamic_payloads", "pingpair_ack" to "RF24_acknowledgment_payloads"...

Laziness over physical interaction

Some examples use a digital input pin to manipulate the role variable (or even a specific feature like multicasting). Most programmers would rather be lazy (myself included). Getting up and walking over to a breadboard that's connected to the computer just to plug or unplug a wire connected to the role_pin is counterproductive. We should stick to adjusting a variable in code (or via a Serial Monitor applet) rather than using a physical GPIO pin. I understand Arduino IDE doesn't allow saving changes to examples, but it does instantly offer the option to save any modifications to an example in the default "sketches" folder (which actually helps the end-user start adapting examples to fit their desired application).

Quantity is harder to maintain

There's soooo many examples. I tried to start formatting them according to this repo's contributing guidelines, but it is overwhelming how much work needs to be done. I think there are actual duplicate examples (and even outdated file formats like *.pde files) that could be deprecated or consolidated. I can appreciate the separate folder for Linux examples, but the same problems discussed above still apply.

Inconsistencies

I found an example with different pin numbers used (as compared to most of the others). Obviously, it would be easier to upload/try different examples without having to change the wiring.

Avamander commented 3 years ago

I understand Arduino IDE doesn't allow saving changes to examples, but it does instantly offer the option to save any modifications to an example in the default "sketches" folder (which actually helps the end-user start adapting examples to fit their desired application).

There's always serial communication that can be used for on-the-fly configuration. If written well, it's very nice to use.

2bndy5 commented 3 years ago

Yes. I agree entirely. I just mentioned that as the IDE hasn't always offered to save the modifications to the sketches folder

2bndy5 commented 3 years ago

Big thanks to @per1234 for leading me to a GitHub workflow we can use to compile all the examples for multiple boards. I made a preliminary attempt to test most of the boards in the AVR architecture, and here are the results. All boards failed compiling some examples while they succeeded compiling most of the examples. I will create another issue to discuss the development of the workflow(s), but I'm posting the first results here to show which examples need attention.

per1234 commented 3 years ago

I'm glad if it is able to be of use!

This type of failed compilation: https://github.com/2bndy5/RF24/runs/1279647104#step:4:51

  Error during build: opening sketch: no valid sketch found in /github/workspace/examples/Usage/led_remote: missing led_remote.ino

Is caused by a bug in Arduino CLI. Evidently there was a regression that caused support for the .pde sketch extension to be lost. I've submitted a bug report about that. Until the bug is fixed, you could work around it by specifying the 0.12.1 Arduino CLI version via the arduino/compile-sketches action's cli-version input (Arduino CLI 0.12.1 was the last version that supported the .pde sketch extension).

- name: Compile examples
  uses: arduino/compile-sketches@main
  with:
    fqbn: ${{ matrix.fqbn }}
    cli-version: 0.12.1

I didn't take a close look at the other failed compilations. If you discover any issues, please let me know. I am also happy to provide some advice on how to configure workflows if you need to exclude some sketches from compilation from some boards. I seem to run into that challenge in most of the workflows I've set up.

2bndy5 commented 3 years ago

If you discover any issues, please let me know. I am also happy to provide some advice on how to configure workflows if you need to exclude some sketches from compilation from some boards.

@per1234 It was a tremendous lead! I'll try my best not to abuse you on that offer (definitely going to check the applicable docs first).

2bndy5 commented 3 years ago

Ok, I fixed all the build errors, but I had to move the "rf24tiny" folder out of the examples into the root (renamed it "examples_attiny"). I also had to move the "pingpair_maple" into its own folder named "examples_maple" (also located at root directory). I also changed the pde file types to ino instead of rolling back the version for the Arduino CLI per @per1234 suggestion (these now compile successfully).

Time to start actually addressing this issue...

EDIT: I found a way to specify certain examples within the arduino build job's compile-sketches action. So, I reverted the structure to what it was originally, but pde files are still ino files. The only examples having trouble compiling are still maniacBug's "pingpair_maple" & tong67's "timingSearch3pin" which are both board-dependent anyway.

2bndy5 commented 3 years ago

here is what I'd like to reduce the numerous examples to:

All examples' TX nodes should print a transmission time result (when successful), except for InterruptConfigure & MulticeiverDemo example.

All library-specific code gets explanatory comments as terse as necessary -- loops, global functions, and if statements also get a brief description if not painfully obvious from scoped comments or typical program structure (like setup() & loop()).

A link to the docs should always be provided as a general reference, but only following copyright/author/license info.

~### Less is More In the introductory comment block that explains the example purpose, each example should pose a [singular] challenge for the user to solve. As programmers, we should all be familiar with this method of learning (either through school/work assignments or insatiable curiosity).~

2bndy5 commented 3 years ago

@Avamander you still interested in that BLE example? Just thought about it while I'm writing the new ones. Remember the payloads are limited to 18 bytes max.

Your broadcast options are:

  1. A URL (6 bytes + URL length). Eddystone protocol is typically used to reduce some URL parts to 1 byte. e.g. http://www.google.com gets reduced to 0x00google0x07
  2. A battery service (5 bytes)
  3. A temperature service (8 bytes)
  4. A device name (2 bytes + name length)
  5. The nRF24L01's PA level (3 bytes) -- only useful for BLE scanner apps to calculate proximity

If you find a GATT service that doesn't need to be claimed by a GATT property and doesn't require GATT characteristics, let me know. I'm ruling out location/navigation because the service data won't fit. And I've already tried the Time service (needs to be claimed by a GATT property).

Please don't say "all of the above"; that would require a full fledged class. I'm not supporting receiving BLE payloads either.

Avamander commented 3 years ago

Implementing one is good enough as an example.

2bndy5 commented 3 years ago

Ok, a name of "nRF" with a battery and temperature data should max out the payload's size. This would also be the most useful configuration for those "copy-and-paste kings/queens" out there.

2bndy5 commented 3 years ago

@Avamander I am at my wit's end with the CRC24 calculation for the BLE example. The result doesn't match with what I'm expecting (comparing to my python's crc24_ble() output which does work). I've literally copied from the article posted by Dmitri and also tried copying the code from BTLE library. But, no joy with either. I think I'm fighting an endianness problem, and I'm not above asking for help (this was the toughest part when implementing fake BLE in circuitpython). If you want to look at it, I can give you the code. Otherwise, I'm putting the BLE example on the backburner for a while...

2bndy5 commented 3 years ago

ok I've added another example called ManualAcknowledgements in which it uses a call-and-respond paradigm without using ACK payloads. This new example and the MulticeiverDemo demonstrate the use of different addresses on different pipes.

I'm ready to call this issue satisfied... PR is coming soon.

2bndy5 commented 3 years ago

Damn I forgot about the Linux examples. I should test that my changes still work on the RPi (just received an RPi4 -- so I may have to bug hunt some of the issues for that hardware) before the PR. I'm assuming there's no objection to re-writing the python and other examples in the Linux folder.

TMRh20 commented 3 years ago

I can test on RPi2 model b and RPi3b just post the code when ready

On Oct 28, 2020, at 5:13 PM, Brendan notifications@github.com wrote:

 Damn I forgot about the Linux examples. I should test that my changes still work on the RPi (just received an RPi4 -- so I may have to bug hunt some of the issues for that hardware) before the PR. I'm assuming there's no objection to re-writing the python and other examples in the Linux folder.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

2bndy5 commented 3 years ago

Sounds great. I also have a RPi2 (why I updated), but the radio is hardwired to different pins. 1 reason I don't like this library on Linux is the requirement to use one of the CE pins for the nRF CSN pins...

TMRh20 commented 3 years ago

That’s mostly done for speed, but it can be modified to support any pin, just a matter of deciding how much stuff to support in various drivers.

On Oct 28, 2020, at 6:08 PM, Brendan notifications@github.com wrote:

 Sounds great. Ialso have a RPi2 (why I updated), buyt the radio is hardwired to different pins. 1 reason I don't like this library on linux is the requirement to use one of the CE pins for the nRF CSN pins...

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

2bndy5 commented 3 years ago

ok, let me say that I'm just now realizing that I've never actually written a C++ program for linux. The main reason I got drawn to this project is so I could use my knowledge about the nRF24L01 to brush up on my C++ skills (assuming that wasn't obvious 😟 ).

I added a micros() function to the "compatibility.h" & "compatibility.c" files for several drivers that already offered millis(). I'm doing some preliminary testing on the RPi4 using the SPIDEV driver, and it compiles and executes without complaints. However, I noticed that the github workflow that builds the library (& also Linux examples now 😄 ) is complaining about my micros() call. It suggests micros (without parenthesis) as an alternative, so I think I'm just not #includeing the right source file(s) to "scope" the new micros() function. Is there something I'm missing? I don't see where millis() is declared in the "utility//RF24_arch_config.h" file (the ATXMegaD3, MRAA, SPIDEV, & template drivers now have a micros() defined).

p.s. I needed the micros() function to adequately measure the transmission time in my new gettingstarted.cpp example for linux; otherwise transmission times would report 0-2 ms (which is so much less accurate than the Arduino GettingStarted example). I looked into hardcoding a micros() based on "sys/time.h" for Linux, so I guess I could try that. But I just thought micros() would be a good idea to provide via the build process; I'm not against undo-ing the micros() addition in this regard as it is only needed for the exeample(s).

Avamander commented 3 years ago

You declare only long __micros(); in compatibility.h when you're calling micros(), that's why.

2bndy5 commented 3 years ago

but I've got #define micros() __micros() in "RF24_arch_config.h" or does that not matter?

Avamander commented 3 years ago

Depends on the order you include files. It's the reason why it's usually not a fun idea to rename functions like that.

2bndy5 commented 3 years ago

usually not a fun idea to rename functions like that.

you ain't kidding.

just to clarify, I haven't renamed anything. I just copied the millis() definitions and adjusted them to output microseconds instead. Notice that the old linux example gettingstarted_call_response.cpp also called millis() and that has no problems.

Should I start tracing the include order or just custom define micros() within the examples?

Avamander commented 3 years ago

Should I start tracing the include order or just custom define micros() within the examples?

Option B is more reasonable assuming you can't just define micros() in the compatibility file. If micros() is a taken name, you could use rf24_micros() and be done with it.

2bndy5 commented 3 years ago

thanks (as always). As a side note, it turns out the delay() call in the old gettingstarted.cpp example was what was throwing errors in the build_linux workflow for wiringPi. As I'm re-writing the examples for linux, I can probably close #669 as it no longer applies with the new examples 😄

Avamander commented 3 years ago

Yeah, just write "Fixes https://github.com/nRF24/RF24/issues/669" in your PR and when it gets merged, the issue gets closed.

Avamander commented 3 years ago

I'm currently on my phone and can't check, but this is also a perfect moment to fix any -Wall -Wpedantic errors.

2bndy5 commented 3 years ago

?? in the makefile? or the configure file? are you trying to reference #642? I am so bad when it comes to the gcc flags (why I fell completely silent in #642 )

Avamander commented 3 years ago

?? in the makefile? or the configure file?

In the Makefile that builds the examples, yes.

2bndy5 commented 3 years ago

nevermind, I defined the micros() functionality in the gettingstarted.cpp example and wiringPi is failing to compile it for a different reason now

2bndy5 commented 3 years ago

@TMRh20 the example files are almost ready (developing from my fork's master branch now), I just want to iron out as much as possible before inviting other people for testing. So far, I feel the following are pretty solid:

  1. gettingStarted.cpp (getting_started.py)
  2. streamingData.cpp (streaming_data.py)
  3. multceiverDemo.cpp (multiceiver_demo.py)

The following are examples I'm focusing on right now.

I am thinking of re-writing interruptConfigure.cpp (interrupt_configure.py) to use attachInterrupt() while the Arduino version (of InterruptConfigure.ino) doesn't use attachInterrupt(), rather I have left a link to the Arduino docs in the "challenge to learn new skills" section of the introductory comment block. I'm getting GPIO::Exception "can't access gpio" error on Linux (using pinmode() & digitalRead() -- oh yeah, I added a digitalRead() for Linux).

TMRh20 commented 3 years ago

I’m getting a digitalRead not declared error compiling the interruptConfigure example. Will take a closer look though.

On Nov 2, 2020, at 11:10 PM, Brendan notifications@github.com wrote:

 @TMRh20 the example files are almost ready (developing from my fork's master branch now), I just want to iron out as much as possible before inviting other people for testing. So far, I feel the following are pretty solid:

gettingStarted.cpp (getting_started.py) streamingData.cpp (streaming_data.py) multceiverDemo.cpp (multiceiver_demo.py) The following are examples I'm focusing on right now.

acknowledgementPayloads.cpp (acknowledgement_payloads.py) manualAcknowledgements.cpp (manual_acknowledgements.py) I am thinking of re-writing interruptConfigure.cpp (interrupt_configure.py) to use attachInterrupt() while the Arduino version (of InterruptConfigure.ino) doesn't use attachInterrupt(), rather I have left a link to the Arduino docs in the "challenge to learn new skills" section of the introductory comment block. I'm getting GPIO::Exception "can't access gpio" error on Linux (using pinmode() & digitalRead() -- oh yeah, I added a digitalRead() for Linux).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

TMRh20 commented 3 years ago

Nevermind the prev comment, I forgot to install RF24...

I'm still having some problems getting examples working with Arduino, but I'll assume its on my end, since things are mostly working with tests on the RPis.

One main point I don't like is the reversion to using a single address for both devices. While OK in a simple test example, it demonstrates addressing which cannot be extended, as each device should technically have a separate address. I think this is a bad move, since the only situation it is suitable is in a multicast scenario. In all other scenarios, proper addressing needs to be handled accordingly.

I'll continue to play around with these over the next few days or so as long as I get a chance. Nice work though!

TMRh20 commented 3 years ago

Ok, the first three examples are testing mostly good on Linux & Arduino, but I'm having problems with the Arduino multiceiver example. I'm not sure what the problem is, but dynamic payload size is reporting mostly 0s. Again I'll see if I can figure it out over the next few days.

I noticed in your repo, you also enable Dynamic Payloads and Dynamic Ack by default. This could be an option, but with Dynamic Acks, the feature is not supported on all devices, so for a (somewhat generic) driver, I would strongly suggest against enabling and/or using the dynamic ack feature in any examples or code. It may be suitable to use a defined radio pipe for multicast/no-ack payloads.

2bndy5 commented 3 years ago

Love the feedback. I can't see how enabling dynamic acks (by default) would hurt because if the feature is supported it only affects the multicast parameter. If it isn't supported, then asserting that flag in the FEATURE register should be inconsequential, but I'm curious which devices you're referring to that don't support it. I noticed a similar comment in RF24Network.h about dynamic payloads. I have no problem keeping the dynamic payloads feature disabled by default. Although, it is a common default setting for many other nRF24L01 libraries.

I anticipated that address comment. You'll see a couple of lines commented out in the Serial.available() blocks of the examples that use the same address. This means I could simply change a few lines to make them use different addresses.

I had an idea that the examples for Linux and Arduino could be consolidated using @wmarkow work on RF24Log, but I don't know if that's been tested on Linux (also needs docs -- or at least I do)

TMRh20 commented 3 years ago

Love the feedback. I can't see how enabling dynamic acks (by default) would hurt because if the feature is supported it only affects the multicast parameter. If it isn't supported, then asserting that flag in the FEATURE register should be inconsequential, but I'm curious which devices you're referring to that don't support it. I noticed a similar comment in RF24Network.h about dynamic payloads. I have no problem keeping the dynamic payloads feature disabled by default. Although, it is a common default setting for many other nRF24L01 libraries.

A quick check with RF24Network and higher layer libs seems to indicate that enabling the Dyn Ack feature results in a communication failure, meaning that all devices need to support it. I believe this affects the SI24R1 devices and some clones. I don't know about the rest, I'll leave it up to you to decide, just my $0.02.

2bndy5 commented 3 years ago

I'll leave it up to you to decide, just my $0.02

This is your (& other's) work I'm messing with here. I'll undo it.

There seems to be a heavy concern to support cheap Chinese imitations of the nRF24L01 in this library. I've been fighting the urge to say this, but after this this PR I think I'll go my own way because there are a quite a few things I keep finding in the source code that makes me think "fire the babysitter already the library is 10+ years old". i.e. the 6 write()-like functions (including both txStandBy() functions) to hide manipulating the IRQ status flags, and most recently that manual timeout using millis() in write(). After all, there are other libraries designed specifically for the imitation devices (they may not be as robust but you get what you paid for). Personally, I don't think the software should be expected to handle hardware faults (which is usually a mal-configured setup problem or incompatible imitation device). I am sorry if this sounds offensive; it's just how I feel (not meant to be offensive).

EDIT: tagging this comment for reference about the using the multicast parameter on Si24R1 chips

2bndy5 commented 3 years ago

Is it ok if I brute force a soft reset in begin()? This would ensure all RX pipes are closed on program start-up which would rectify artifact configurations from previous programs because a Power-on-Reset (PoR) condition is not invoked (for the radio) when re-uploading different programs to Arduino (or other MCU) boards. However, this might increase compile size a bit because I'd be setting all registers to PoR conditions (with the exception that pipes 0 & 1 are closed instead of open on initialization). I could also reset pipe addresses to avoid #496 (concerning pipe0_reading_address), but that would be a little too over-corrective (needs 6 additional write_register() calls).

Furthermore, the datasheet states that a (hard) PoR is completed after 100 milliseconds; begin() (or c'tor) does not account for this when users are deploying applications that may actually be invoking a PoR condition based on power supply implementation.

TMRh20 commented 3 years ago

Rough deal, too bad I didn’t have a clue how to program when I started work on rf24, it would have turned out much cleaner. In any case feel free to make or suggest changes in the future.

On Nov 3, 2020, at 4:56 PM, Brendan notifications@github.com wrote:

 I'll leave it up to you to decide, just my $0.02

This is your (& other's) work I'm messing with here. I'll undo it.

There seems to be a heavy concern to support cheap Chinese imitations of the nRF24L01 in this library. I've been fighting the urge to say this, but after this this PR I think I'll go my own way because there are a quite a few things I keep finding in the source code that makes me think "fire the babysitter already the library is 10+ years old". i.e. the 6 write()-like functions (including both txStandBy() functions) to hide manipulating the IRQ status flags, and most recently that manual timeout using millis() in write(). After all, there are other libraries designed specifically for the imitation devices (they may not be as robust but you get what you paid for). Personally, I don't think the software should be expected to handle hardware faults (which is usually a mal-configured setup problem or incompatible imitation device). I am sorry if this sounds offensive; it's just how I feel (not meant to be offensive).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

2bndy5 commented 3 years ago

For what its worth, I barely knew python when I started the CircuitPython library for the nRF24L01... Adafruit kindly put me in my place and got me up to speed (I read A LOT more docs now though).

I'm always around to help troubleshoot, and my familiarity with this library may also help.

2bndy5 commented 3 years ago

One main point I don't like is the reversion to using a single address for both devices. While OK in a simple test example, it demonstrates addressing which cannot be extended, as each device should technically have a separate address. I think this is a bad move, since the only situation it is suitable is in a multicast scenario. In all other scenarios, proper addressing needs to be handled accordingly.

This may be hard to read if you're coming from a networking mentality, but nRF24L01 addresses aren't actual destinations, they're OTA paths. I've been trying to add the use of a second address in gettingStarted and ackPayloads examples, but I've come to the conclusion that only 1 address would ever get used because the examples are so simple.

Please bare with me in the following analogy about addresses (the [explicit interpretation] about the radio is in square brackets):

Hopefully, you can see my dilemma now. If I add a second address to be used, I complicate the gettingStarted & ackPyaloads examples (which incites the "complex = overwhelming" problem stated in the OP on this thread). I could get rid of the multiceiverDemo and make all examples use that paradigm, but again its not very simple for noobs to pick up and test their new hardware (what I call "toys")

TMRh20 commented 3 years ago

I like your analogy, but lets look at it a little differently:

Lets say the pipes are parking spaces, my parking space is slot 1 at address 15 someStreet. I want to send a packet, and need to park somewhere, but now I'm sending it to slot 1 at 15someStreet...the same address. This analogy works in examples because the slot is empty as soon as I leave the space, but in a real-life scenario, with more than 2 devices, it is just confusing to explain.

IMHO, it may simplify the code, but trying to explain that the examples only work in theory, and need modifications to operate normally is a painful experience.

2bndy5 commented 3 years ago

trying to explain that the examples only work in theory, and need modifications to operate normally is a painful experience.

Too true. The analogy was only meant to emphasis that nrf24 addresses aren't like IP addresses. Rather they define a OTA specific path despite where it leads. Meaning destinations like 15 SomeStreet is inconsequential, the address is how the packet finds SomeStreet to begin with; the pipe at 15 SomeStreet is reserved for packets coming from Astreet only, all those coming from anywhere else will have to reserve their own pipe. The fact that SomeStreet can be found via Atreet, Bstreet... is because the pipe is open to the same channel the packet is traveling on.

Its not a theory, this is how addresses are actually treated by the radio (matching configurations is part of the packet validation). I wish Nordic Semi chose a better name as the term "address" is misleading. I'll add the radioNumber variable to the gettingStarted & ackPayloads examples, even though the separate addresses would be identical OTA paths (like parallel one-way streets with different names & equal length).

2bndy5 commented 3 years ago

I'm in the process of adding CLI args -r/--role & -n/--node to the Linux examples (C++ & Python).

Question: Do we want to exit example after specified role is complete?

If unanswered, I'll assume the answer is "yes", but the startup time for the examples is significant (> 100 ms). BTW, if only the -n/--node arg option is specified, then the example simply skips the "Which radio is this?" prompt and goes straight to setRole().

2bndy5 commented 3 years ago

ok I'm think my fork's master branch is ready for a PR. All examples seem to be working on arduino, python, and Linux. I just want to test on more devices. So far I've been developing on an arduino nano & RPi4. I want to try the Digispark ATTiny85 (examples for the rf24_ATTiny folder now compile for the SpenceKonde ATTinyCore), Adafruit Feather M0, and my RPi2B+.

HINT: Use -h or --help to see the manpage for examples. All examples use the same arguments (-n/--node & -r/--role) except the MulticeiverDemo (which only takes a -n/--node arg). The manpage should be explanatory enough, but I'm open to expanding on details if needed.

TMRh20 commented 3 years ago

Just running the c++ gettingstarted sketch on Arduino and RPi3 and am noticing a few issues:

  1. Over SSH, (only when receiving) the call to radio.powerDown(); seems to cause the call to exit(0); to hang? Removing it clears up the problem. No idea why.
  2. The output on RPi seems messed up, shouldn't it be 4-bytes and the payload value?:
Received 6 bytes on pipe 1: 0
Received 6 bytes on pipe 1: 0
Received 6 bytes on pipe 1: 0.175778
Received 6 bytes on pipe 1: 0.476555
Received 6 bytes on pipe 1: 0.499785
Received 6 bytes on pipe 1: 0.703111
Received 6 bytes on pipe 1: 0.933333
Received 6 bytes on pipe 1: 0.99957
Received 6 bytes on pipe 1: 1.62104

Arduino:

21:11:51.970 -> *** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK
21:12:07.071 -> Received 4 bytes on pipe 1: 0.00
21:12:08.062 -> Received 4 bytes on pipe 1: 0.01
21:12:09.101 -> Received 4 bytes on pipe 1: 0.02
21:12:10.088 -> Received 4 bytes on pipe 1: 0.03
21:12:11.111 -> Received 4 bytes on pipe 1: 0.04
21:12:12.102 -> Received 4 bytes on pipe 1: 0.05
  1. The RPi in RX mode was skipping ahead, receiving many payloads at once. I haven't diagnosed the problem, just going through some of the tests.
Received 2 bytes on pipe 3: 6.46721e+19
Received 2 bytes on pipe 3: 6.46721e+19
Received 2 bytes on pipe 3: 6.45998e+19
Received 6 bytes on pipe 3: 6.46721e+19
  1. I'm not so sure about the cli args, especially being used in the gettingstarted sketch. It kind of seems like a beautiful "hello world" sketch that is 1000 lines long. It seems neat enough in python, but in C it seems kind of ugly!?

I think there is still a bit of debugging and testing needed.

TMRh20 commented 3 years ago

Err, #s 2 and 3 appear due to a loose connection. Disregard. Will continue playing around with these examples.

2bndy5 commented 3 years ago

I was going to suggest trying a slower SPI speed on your RPi. I've seen a similar problem using jumper cables that were longer than 3 in (or > 76 mm) and resulted in receiving "ghost" bytes that were never sent.

Removing it clears up the problem. No idea why.

I don't get this problem on RPi4, so I'm totally reliant on your advice here. Does it still exit the program when you removed exit(0)? I'm also using SSH.

About problem 4: I looked into argp.h getopt(), and getopt_long(), but the code to use just 2 args was A LOT more. Python looks neat because its using a std python library to handle parsing the cmd args. Suggestions?

TMRh20 commented 3 years ago

I'm using a small adapter with no wires for the RPi3, (unplugged it to reset the radio) and I assumed it was on there tight.

Removing the powerDown command is waht does it... the SSH session keeps accepting input, but I can't CTRL+C out of it or anything, so I'm thinking something about unfinished tasks or something I read regarding the exit() command.

I don't know about problem 4. My original suggestion was to use args only for one example for testing purposes, kind of a single example that does everything depending on what commands it is given. That would leave the main examples a bit simpler, but alternately we could just use the args in the examples other than the main gettingstarted sketch too. Not sure, just that it definitely overcomplicates gettingstarted and we should leave at least one as simple as possible.

2bndy5 commented 3 years ago

If you look at multiceiverDemo.cpp, you'll see that it only takes 1 arg (which simplified the code a bit), but the expected -n/--node arg needs to be the first arg specified. I'm ok with removing cmd args from all but streamingData and multiceiverDemo examples. It would mean less maintenance that way also. Would you want me to remove args from corresponding python examples too?

2bndy5 commented 3 years ago

what SSH app are you using? I use the openSSH console app installed in windows (or maybe it was added with visual studio).

TMRh20 commented 3 years ago

I'm still going through the examples one at a time. I'd like to see how it all works together before trying to decide.

Using Putty. Still does it if I SSH in from another RPi:

*** PRESS 'T' to begin transmitting to the other node
*** PRESS 'R' to begin receiving from the other node
*** PRESS 'Q' to exit
r
^C Interrupt signal 2 detected. Exiting...
^CsrfasdfWTF OVER???