Data transmitted doesn't match data received for NRF24L01+

Radio Modules:
Power Supply: which I have measured to output 300 mA while only dropping to 3.24V.
Code: Running on Arduino Uno, but I also ran on a Nano with no change.
Relevant Images:

The first image is taken when I have unommented the "printPrettyDetails" line. As far as I can tell there, everything is up to scruff. I do see that the SPI lines are at 0MHz, but I have told them to run at 100kHz because I thought slowing it down might help with the fact that I am using jumper wires at the moment. (I have shortened them and straightened them and lined them up as nicely as I can, but it's not a great solution for high speed. I just can't really invest in anything better until I know I can make this work.

The second image is essentially the problem. I did modify the code slightly from normal so that it wouldn't try to work its way through the state machine. All it's doing is having one of the radio modules transmit the same 4 bytes 3 times over, then doing a different 4 bytes 3 times over, and repeat. You can see that there is a 1-to-1 correspondence between messages sent and messages received. The code even checks to make sure 4 bytes were transmitted. And there seems to be no randomness to the mistranslation as the values are completely repeatable. Even when my code wraps around to run the first 4 bytes again, it gets the same response the first time around.

The last image is closer to what my final code is, except because all the data is garbled, I had to comment out all error checking and just take all values as if they are correct. I also shifted the printing around a bit to make sure each put out the same number of lines to make it easier to read what's happening. And just in the first interaction for visual aid, I highlighted values that are supposed to be the same. Values that were transmitted by one module and received by the other, but with value distorted.

each of the images showing the incorrectly transmitted (or incorrectly received, not sure which) data has a comment in Imgur with the commit hash (they're just the two most recent commits). (Also, please don't judge me by my commit history, it's a personal project. I'm not going to put in the same effort I do when I code for work to make things neat and tidy and have useful messages or distinguish which changes were for what reason.)

A quick overview of how the code is intended to work:

  1. The transmitter sends a known code (RUN_LEFT, RUN_RIGHT, or RUN_BOTH). Eventually, a button will trigger this, but for now, it just loops through the commands with a 5 second delay between interactions
  2. The receiver will (if it recognizes the command) generate a prompt (using millis) and send that prompt to the transmitter. It also runs that prompt through a digital woodchipper (it's nothing fancy, I wrote it myself, it's not super high security or anything, just think of it like using the prompt as the seed for an RNG. The function is called calculate_response and it exists in the garble module (not included in the repo)
  3. The transmitter gets the prompt, runs it through the same woodchipper, and sends the response back.
  4. If the response from the transmitter matches the one expected by the receiver, the receiver will enact the command from step 1, and blindly blast back a few copies of an acknowledgement (CMD_SUCCESS).

I had been fiddling with this code for over a month before I finally had it basically working. Except it was jam packed with dozens of ugly debug messages and in desperate need of a refactor. Like an IDIOT, I didn't commit, and forged on because I didn't think I was actually changing anything. I cleaned it all up, got back to a state that was pretty close to what I was hoping would be the final product, and suddenly, all the data is messed up again, and I can't get it back to where it was. I'm relatively confident it's not hardware because I didn't even physically touch them between it working and it not working. Plus, I can't imagine I'd even get this much responsiveness with bad hardware. Any tips?

Welcome to the forum

Please post your full sketches, using code tags when you do

Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

It is also helpful to post error messages in code tags as it makes it easier to scroll through them and copy them for examination

You mention images, but I don't see any

To post images etc. you need trust level 1, you can get there by:

  • Entering at least 5 topics
  • Reading at least 30 posts
  • Spend a total of 10 minutes reading posts

Users at trust level 1 can...

  • Use all core Discourse functions; all new user restrictions are removed
  • Send PMs
  • Upload images and attachments

you may have power supply problems - have a look at post unable-to-initialize-nrf24l01-using-attiny84

Check the blue links at the top of the post. I put everything in there.

Sorry, but I and many other forum users will not bother to look at inadequate images on another web site so by posting such links you do yourself no favours

I assume that you have read How to get the best out of this forum but perhaps not

Could it be here? :

static void radio_send_data(unsigned long data)
{
  radio.stopListening(car_addr_bytes);
  delay(5);
  Serial.print("sending 0x");
  Serial.println(data, HEX);
  bool report = radio.write(data, PAYLOAD_SIZE);
  delay(5);
  radio.startListening();
}

The write() method expects a pointer to a buffer but you are giving it a value. See Optimized high speed nRF24L01+ driver class documentation: RF24 Class Reference

Probably you want bool report = radio.write(&data, PAYLOAD_SIZE);

Anyway, if you are still having problems then reduce your sketches to the simplest case of transferring a uint32_t data item between the transmitter and the receiver and try again.

I certainly won't reject it out of hand. A refactor should be easy (tonight after work). The reason I'm not enthusiastic is because this part has been there from the beginning. I had it working with the unsigned long just fine 2 days ago... before I messed it all up *sigh. I'll definitely see what I can do about a simpler version too.

We have a saying for these kinds of problems: KISS. I suspect the problem is in a totally different place than what you think.

It will not have worked as you currently have it because you are passing an incorrect data type to the RF24 write() method which has the signature bool RF24::write( const void * buf, uint8_t len)

However, if you are adamant that this statement: bool report = radio.write(data, PAYLOAD_SIZE); worked before then it is possible that, previously, the signature of what is currently radio_send_data(unsigned long data) was radio_send_data(unsigned long * data). But, you can't just change that unless you make matching changes to the calling routine(s) and prototype.

If you simply asked an AI bot to do the refactoring then it may well have ignored subtleties like '&' or '*' qualifiers and discarded them. In your TX code you are sometimes passing an unsigned long as an argument and sometimes a pointer to an unsigned long and this inconsistency and has possibly led to the error.

The OP has not returned but, from looking at the code Github repository GitHub - DimoniumAnonimo/Garage-Door-Remote mentioned in post #1, he has solved this by using the address of a variable instead of its value as was suggested to him:

image