SPI problem with shorter wires? (25cm works, 5cm doesn't) - Page 1
Forum section: electronics / projects

author: hermankopinga
author_rank: Newbie
timestamp: July 03, 2015, 03:16:45 pm
content: Hi all,My first question on this forum, so far I've been appreciating the knowledge here in silence. Now I've run into an interesting (and frustrating) problem. I'm helping out trying to build 300 wireless nodes with apa102 led's for lighting on a summer music festival.Situation:The test RF24l01 modules we used in prototyping (purchased at local electronics store) work without problems on this layout.The RF24l01 300 modules we purchased through aliexpress have the following problem when used in this setup.(photo's of the two modules added for reference, they seem -very- similar)Problem:On PCB (layout attached) with long 20cm wires it works flawlesly.On PCB (layout attached) with +/-3cm long tracks it is flaky (see scope output, packages sent every 501ms). (about 20% loss)A case of breadboard prototyping worked, 'production' prototype has problems.Desired:- Homebrew PCB (we are building about 300)- Atmega328p 1MHz internal oscillator- NRF24l01 wireless communication module with hardware SPI- running Arduino bootloader and homebrew code based on Maniacbug RF24 library.Tested setups:SPI clockdiv 2 & 4 @ 1MhzSPI clockdiv 4 @ 8MhzAtmega328 1MHz internal oscillatorAtmega328 8MHz internal oscillatorChecked signal integrity with oscilloscope, doesn’t seem ‘weird’.So basically the question is, what could stop SPI with SHORT wires? Every piece of documentation I can find refers to longer wires being a problem.Any help is appreciated!Questions? don’t hesitate to ask!Greetings,Herman KopingaThe Netherlands, Groningen

author: hermankopinga
author_rank: Newbie
timestamp: July 03, 2015, 03:22:08 pm
content: Photo's comparing the modules we purchased.

author: hermankopinga
author_rank: Newbie
timestamp: July 03, 2015, 03:23:30 pm
content: In case anyone is interested, the code for the receiver in stripped down version. This also shows the configuration we use for the NRF24L01.Based on the example fromhttps://github.com/maniacbug/RF24Code:/*Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseversion 2 as published by the Free Software Foundation.*//*** Example for Getting Started with nRF24L01+ radios.** This is an example of how to use the RF24 class. Write this sketch to two* different nodes. Put one of the nodes into 'transmit' mode by connecting* with the serial monitor and sending a 'T'. The ping node sends the current* time to the pong node, which responds by sending the value back. The ping* node can then see how long the whole cycle took.*/#include <SPI.h>#include "nRF24L01.h"#include "RF24.h"#include <Adafruit_DotStar.h>//// Hardware configuration//const int ledPin = A0;const int buttonPin = A1;// Set up nRF24L01 radio on SPI bus plus pins 9 & 10RF24 radio(9,10);//// Topology//const uint64_t pipe = 0xF0F0F0F0E1LL;//// Role management//// Set up role. This sketch uses the same software for all the nodes// in this system. Doing so greatly simplifies testing.//// The various roles supported by this sketchtypedef enum { role_ping_out = 1, role_pong_back } role_e;// The debug-friendly names of those rolesconst char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};// The role of the current running sketchrole_e role = role_ping_out;void setup(void){pinMode(ledPin, OUTPUT);// Blink to welcome our new robot overloards.digitalWrite(ledPin, HIGH);pinMode(buttonPin, INPUT_PULLUP);//// Print preamble//Serial.begin(9600);Serial.println("\n\rRF24/examples/GettingStarted/");digitalWrite(ledPin, LOW);//// Setup and configure rf radio//radio.begin();// optionally, increase the delay between retries & # of retriesradio.setRetries(15,15);radio.setPALevel(RF24_PA_MIN);radio.setAutoAck(0);radio.setDataRate(RF24_250KBPS);// optionally, reduce the payload size. seems to// improve reliabilityradio.setPayloadSize(8);//// Open pipes to other nodes for communication//radio.openReadingPipe(0,pipe);radio.openWritingPipe(pipe);//// Start listening//radio.startListening();digitalWrite(ledPin, HIGH);//// Dump the configuration of the rf unit for debugging//radio.printDetails();// Blink to welcome our new robot overloards.digitalWrite(ledPin, LOW);}void loop(void){// if there is data readyif ( radio.available() ){// Dump the payloads until we've gotten everythingunsigned long got_time;bool done = false;digitalWrite(ledPin, HIGH);while (!done){// Fetch the payload, and see if this was the last one.done = radio.read(&got_time, sizeof(unsigned long) );// Spew itSerial.print("Got payload ");Serial.print(got_time);Serial.print(" ");// Delay just a little bit to let the other unit// make the transition to receiverdelay(20);}unsigned long waittime = got_time & 0xFFFF;Serial.println(waittime);//delay(50);digitalWrite(ledPin, LOW);// Send the final one back.// Now, resume listening so we catch the next packets.}}

author: janekm
author_rank: Unknown
timestamp: July 03, 2015, 03:40:42 pm
content: It could be noise from the other components on your PCB getting conducted to the relatively sensitive receiver part of the NRF24L01. The longer wire may have acted as a crude inductor / resistor reducing conducted noise passing to the radio module (not a recommended application, but could explain the weird behaviour).I think it's less likely to be an issue with the SPI bus as such.It looks like your code is polling the radio module for new packets rather than using the interrupt feature. In this case switching noise from the MCU (from clocking transactions over SPI) may be passing to the radio module. You could try using the interrupt pin instead.

author: janekm
author_rank: Unknown
timestamp: July 03, 2015, 03:42:57 pm
content: BTW a little warning about those types of modules, they are built by quite a few different small "factories" with varying levels of quality control. I have had a few with the incorrect load capacitors for the crystals they had been fitted with, leading to incorrect frequency tuning. Which works ok if you're using boards from the same batch but can lead to miserable performance with modules from different batches.

author: Kalvin
author_rank: Super Contributor
timestamp: July 03, 2015, 03:58:32 pm
content: Check the clock edge polarities at the master and slave. For example, if the master outputs the data at the 1->0 transition, the slave needs to read that data at the 0->1 transition.

author: slashguitar
author_rank: Contributor
timestamp: July 03, 2015, 04:35:35 pm
content: I had a batch of nRF modules which didn't work(or barely worked) until I added a 1uF decoupling right on the pin header.

author: miguelvp
author_rank: Super Contributor
timestamp: July 03, 2015, 09:24:36 pm
content: Don't you need some kind of termination resistors on the SPI bus to avoid reflections?What values and where, I don't know.

author: leblanc
author_rank: Regular Contributor
timestamp: July 04, 2015, 01:39:18 am
content: A 50MHz scope might not be adequate for measuring signal integrity on megahertz range signal.Did you check that your clock phase and polarity are correct for the devices (http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Clock_polarity_and_phase)? I've had problems with this before. I'd imagine you'd lose a lot more than 20% of your packets, but you never know.If it's a signal integrity issue, you could try putting a pulldown at the receiving end of the signal (try to match characteristic impedance of the cable), or a series resistor at the source of the signal. Note that the former loads your signal and reduces the magnitude. Both methods can significantly reduce reflections.If the issue is noise getting coupled on your lines, there are a number of options for shielding.If you need to run long distances, fibreoptics would be an option to consider for a next rev.

author: tggzzz
author_rank: Super Contributor
timestamp: July 04, 2015, 09:35:15 am
content: Since you've provided good information about your test setup, it is worth us having a go at making suggestions.The first thing I would do is look closely at the PSU level and AC-coupled disturbances at each end of the link, and compare what you see with the different length cables. It might be necessary to add extra PSU decoupling at either or both ends.The second thing I would do is to look at the relative positions of the clock and data, to verify the setup and hold times are being observed.The third thing I would do is look closely at theedgesof the signals at each end of the ribbon cable in each direction. Unfortunately a 50MHz (=>7ns risetime) scope probably won't show you the signal that is being interpreted by the logic. In an ideal world, I'd use a low-impedance Z0 probe to avoid the 20pF capacitative loading of "high impedance" scope probes.I'll note if it is to be used near high-powered lighting, any large current changesmightcause intermittent interference.

author: JuKu
author_rank: Frequent Contributor
timestamp: July 09, 2015, 01:18:05 pm
content: Quote from: Kalvin on July 03, 2015, 03:58:32 pmThis. Also, show us the scope image of a single bit so we can see the signal quality and edges.

author: hermankopinga
author_rank: Newbie
timestamp: July 09, 2015, 09:24:52 pm
content: I feel kind ofright now. It's been the cap all along.I was joking that it wasalways a capand we tested some caps right on the header. Unfortunately those tests weren't conclusive. Now with the suggestion from slashguitar (thanks!) this solved it. Added 4.7uF on the pcb next to the connector for the nrf24l01 and receiving works.Now of course we run into new challenges but at least this bug is gone.Why the longer wires have enough capacitance isn't clear to me (still a bit afraid of analog stuff, recently bought The Art of Electronics 3rd Edition to help remedy that).Thanks a lot for your suggestions!