SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By QuantumKid
#183253
I'm using an Uno to control an analog ADC/ DAC shield which talks to the arduino via ISP (Shield manual here - https://www.digilentinc.com/Data/Produc ... m_rev3.pdf) and then transmit some acquired data via a pair of XBees (which use the arduino's UART) on the sparkfun xbee shield to another Uno with DAC shield which then writes the data back out.

The problem I am having, in short, is this. When I test latency between the Xbees stacked onto the Uno board I get one value, say ~10ms, and when I test the latency with the analog shield stacked onto the Uno I get another value, say ~50us. When I combine the tests (and associated code) and stack both shields together and run the test, my latency jumps up to over 100ms. Also, I noticed the looping time was roughly 50-100 times slower. The only thing I can think would be holding things up is that now the arduino has to communicate via the ISP lines and the serial UART lines, which takes more clock cycles and thus slows everything down.

Details of tests:

First, I had one arduino write a value to 3 digital lines, create a serial string of data (values of each line) and send the string via serial with the Xbee. The second Uno/ Xbee setup read the string and parsed out the data values, then wrote those values to three digital channels. I turned off Xbee serial headers and ACKs and cranked up the baud rate until I could just barely not miss any bits (from overflowing the serial buffer). The latency I measured between 1st digital channel on the send setup and the 3rd digital channel on the receive setup (meas'd on oscilloscope) was around 5-10ms.

Second, using the analog shields stacked on the Unos, I had one write two of its DAC channels with a rolling analog value (a linear ramp), the second of these written values was wired to the other Analog shield/ Uno setup which read the value, stored the value in a variable, and re-wrote the value to one of its DAC channels. I then measured the latency between the 1st DAC on the send setup and the 1st DAC on the receive setup, and it was about 50us. Again highest baud rate without missing info.

Finally, I setup Analog/ Xbee/ Uno all together. I had the sender write to an analog channel (same linear ramp loop, which I noticed was 50-100 times slower than before), create a string with the current data point, and send it via the Xbee. The receiver read the serial string, then wrote the data to one of its DAC channels. The lag, or latency, between these two DAC writes was over 100ms. Actually, it would start around 50ms and steadily increase till about 120ms. I played with lots of baud, buffering, and other settings on the Xbees here and nothing improved that speed.

So why is using both at the same time drastically slower than using either separately? Is it just taking too much of the arduino CPU?

I've attached the Arduino code for the writing and reading in the last test. The former tests are functionally the exact same, and if anything were only bulkier and more complicated.


Write Code:

#include <analogShield.h> //Include to use analog shield.
#include <SPI.h>

unsigned int ramp = 0;
//String serialString = "";
const int stepSize = 45; //voltage resolution = 10V*stepSize/65536

void setup()
{
Serial.begin(57600);
}

void loop()
{
analog.write(0,ramp);
if(ramp+stepSize>65535)
{
ramp = 0;
}
else
{
ramp+=stepSize;
}
Serial.print("A");
Serial.print(ramp);
Serial.print("\n");
}




Read code:

#include <analogShield.h> //Include to use analog shield.
#include <SPI.h>

int incomingByte;
char aChar;
int Aindex = -1;
String AdataString = "0";
int Adata = 0;

String inData = "";
byte index = 0;

void setup() {
Serial.begin(57600);
}

void loop() {

if(Serial.available() > 0)
{
aChar = Serial.read();
if(aChar == '\n')
{
// End of record detected. Time to parse
Aindex = inData.indexOf('A');
if(Aindex != -1)
{
AdataString = inData.substring(Aindex+1);
Adata = AdataString.toInt();
analog.write(0,Adata);
}
inData = "";
}
else
{
inData += aChar;
}
}
}
#183268
Well, you are making heavy use of the String class object in your read code. Behind the scenes the Arduino is executing a fair bit of extra code. Maybe you can simplify your code a bit by simply waiting for the sequence '\n','A' in the serial stream, and then analog.write the next serial.read value? It's a bit more complex, you are sending int values, so you need to reform them together again into an int.

p.s. Try to use the Code button in the full message editor to insert your code in the windows it creates. That reduces the length of the message, and makes the code more readable.
#183269
Instead of Serial.print(ramp); in the write-code:
Code: Select all
Serial.write(ramp / 256);
Serial.write(ramp % 256);
and in the read-code:
Code: Select all
void loop()
{

  if(Serial.available() > 0)
    {
      aChar = Serial.read();
      if(aChar == '\n')
        {
          // End of (previous) record detected. Time to parse the next one
		  if (Serial.read()=='A')
			{
				incomingByte=Serial.read();
				Adata=incomingByte * 256 + Serial.read();
				analog.write(0,Adata);
			}
		  else
            {
              // Received garbage byte. Ignore! Wait for next '/n'.
			}
        }
	}
}
I'm not entirely sure how it responds to out-of-sequence or garbage-bytes. It might skip a sample. This is just a crude more time efficient solution I think.