Arduino Forum

Using Arduino => Programming Questions => Topic started by: jlefevre1 on Jan 07, 2013, 07:17 pm

Title: need to move 1 unsigned long serially really quick
Post by: jlefevre1 on Jan 07, 2013, 07:17 pm
I need to move 1 unsigned long integer over the serial port from one arduino to another , over and over, without stopping, as fast as I can. Basically I will encode the bits of the integer in one arduino and then send that unsigned long integer to another arduino to decode them. I will do this over the serial port at 9600 baud. This is to control christmas lights next year so it has to happen really fast to keep the lights up with the music. I am currently doing this with a string of 6 integers, comma delimited and ending the string with a ;   It works but I have to put a 300 ms delay on the transmitter or the decoding fails on the other end. And the data rate is to slow. I have read all of the libriaries and find the definitions for the serial stuff very confusing. I can get the serial print statement to work nicely at all speeds even with the delay between print statements eliminated. But getting the receiver to decode it without the delay of at least 300 ms between transmissions falls flat on its face. I came up with the idea of just using the single 32 bit unsigned integer instead of the 6, 16 bit integers withe the comma delimiter because I thought that should be more simple to speed up. But I am unsure how to proceed.
Title: Re: need to move 1 unsigned long serially really quick
Post by: KeithRB on Jan 07, 2013, 07:19 pm
Are you sending ASCII or binary?
Title: Re: need to move 1 unsigned long serially really quick
Post by: PaulS on Jan 07, 2013, 07:21 pm
Quote
I will do this over the serial port at 9600 baud. This is to control christmas lights next year so it has to happen really fast to keep the lights up with the music.

Really fast and 9600 baud rate do not belong together.
Title: Re: need to move 1 unsigned long serially really quick
Post by: retrolefty on Jan 07, 2013, 07:24 pm
300 millisec delay required! I suspect you are doing something wrong in the receiver sketch such as using delay commands or other blocking commands that is causing your serial receiver buffer to lose characters. Post your code if you really want help.

Lefty
Title: Re: need to move 1 unsigned long serially really quick
Post by: Grumpy_Mike on Jan 07, 2013, 07:25 pm
Quote
from one arduino to another , over and over, without stopping, as fast as I can.

Is there any point in this as there is no time to do anything with the number if you do.

Quote
This is to control christmas lights next year so it has to happen really fast to keep the lights up with the music.

Ah I see your idea of fast is not the same as mine. Music changes quite slowly compared to the speed that a controller will work at.

Quote
It works but I have to put a 300 ms delay on the transmitter or the decoding fails on the other end.

That suggests you are writing the code incorrectly.

Quote
And the data rate is to slow

Well 9600Baud is quite slow, try changing it to 115200 baud that is a lot faster.

Quote
But getting the receiver to decode it without the delay of at least 300 ms between transmissions falls flat on its face.

Again you are writing the code incorrectly. You are probably using the delay function somewhere.
Title: Re: need to move 1 unsigned long serially really quick
Post by: robtillaart on Jan 07, 2013, 07:31 pm
Quote
Really fast and 9600 baud rate do not belong together.

For snails they do ;)

Quote
try changing it to 115200 baud that is a lot faster.

between 2 Arduino's you can even use higher like 230400 or 345600 baud over hardware serial.

Can you post your code?
Title: Re: need to move 1 unsigned long serially really quick
Post by: PeterH on Jan 07, 2013, 07:58 pm

I need to move 1 unsigned long integer over the serial port from one arduino to another , over and over, without stopping, as fast as I can.


That sounds like the solution to some problem, and not a very smart solution at that. You're trying to turn lots of LEDs on and off individually? How many - and what sort of latency do you want to achieve? Where are the LED commands coming from?
Title: Re: need to move 1 unsigned long serially really quick
Post by: retrolefty on Jan 07, 2013, 08:12 pm

Quote
I will do this over the serial port at 9600 baud. This is to control christmas lights next year so it has to happen really fast to keep the lights up with the music.

Really fast and 9600 baud rate do not belong together.


You insensitive clod, my first communications link was at 300 baud using an acoustically coupled modem. 9600 baud will always seem fast to me. :D

Lefty
Title: Re: need to move 1 unsigned long serially really quick
Post by: robtillaart on Jan 07, 2013, 08:22 pm

@ 9600 baud continuous mode one can send about 2000 longs (binary = 4 bytes) of 32 bits enough to switch on/off 64000 leds Or 64 leds 1000 times.
in text mode one need max 11 bytes to send one long(+ separator) so that makes 32000 leds.

phrased more seriously:
How many LEDS's are there?
How often do the need to be refreshed?
Title: Re: need to move 1 unsigned long serially really quick
Post by: PaulS on Jan 07, 2013, 09:16 pm
Quote
You insensitive clod

Yep, that's me.  8)
Title: Re: need to move 1 unsigned long serially really quick
Post by: robtillaart on Jan 07, 2013, 09:31 pm
I always thought PaulS was an anagram of "A plus" because of the many quality contributions ;)

The "you ...clod" has many many anagrams - http://www.wordsmith.org/anagram/advanced.html -

(and yes robtillaart == Ill Abort Rat)
OK time to move to bar sport ...
Title: Re: need to move 1 unsigned long serially really quick
Post by: jlefevre1 on Jan 07, 2013, 10:54 pm
9600 baud is a necessity. I will be sending from one Arduino as the transmitter to multiple Arduinos as recievers. And this will be done using 900 Mhz RS232 wireless serial radios. They top out at 9600 baud. Without the delay in the transmitter program and using the serial monitor on the software to see what the transmitter is putting out with the present 6 integer, comma delimited stream, the speed ismore than quick enough. But the receiver cannot read it and stuff it back into 6 sets of integers.  Right now for testing I am just connecting the Tx out of the transmitting Arduino to the Rx of the reicever on my workbench. I will put the radios in later but they are not part of the equation now. I will be using the 32 bits of the single long integer in various ways. 5 groups of 4 bits will be scaled from a binary 0-15 to a integer of 0 - 255 to drive 5 PWM outputs. 7 bits will directly control 7  outputs of the Arduino directly. Either on or off.  One of the bits will be a system on - off bit. When off all of the outputs and the PWM values will be set to 0 . The rest of the 32 bits are spares for now.


Title: Re: need to move 1 unsigned long serially really quick
Post by: PaulS on Jan 07, 2013, 11:44 pm
Quote
And this will be done using 900 Mhz RS232 wireless serial radios. They top out at 9600 baud.

You've got 11 months to get better radios.

Quote
But the receiver cannot read it and stuff it back into 6 sets of integers.

At 9600 baud, it has an eternity to parse and convert the data.

We need to see some code to see why you are having problems.
Title: Re: need to move 1 unsigned long serially really quick
Post by: dhenry on Jan 07, 2013, 11:58 pm
Use the hardware spi or uart, plus interrupts: configure the modules to trigger an isr when the data register is empty (or the transmission is done). In the isr, load up the next byte, until all four bytes / string have been done.

The speed will be blindingly fast, and it is a send-and-forget type.
Title: Re: need to move 1 unsigned long serially really quick
Post by: PeterH on Jan 08, 2013, 12:17 am

Use the hardware spi or uart, plus interrupts: configure the modules to trigger an isr when the data register is empty (or the transmission is done). In the isr, load up the next byte, until all four bytes / string have been done.



In other words, call Serial.write()?
Title: Re: need to move 1 unsigned long serially really quick
Post by: Jack Christensen on Jan 08, 2013, 01:26 am

You insensitive clod, my first communications link was at 300 baud using an acoustically coupled modem. 9600 baud will always seem fast to me. :D


LOL, we thought we were hot stuff when we got 1200 baud! :D
Title: Re: need to move 1 unsigned long serially really quick
Post by: retrolefty on Jan 08, 2013, 01:45 am


You insensitive clod, my first communications link was at 300 baud using an acoustically coupled modem. 9600 baud will always seem fast to me. :D


LOL, we thought we were hot stuff when we got 1200 baud! :D


Very true, and the first 1200 baud modems retailed for like $795 at the time.

Lefty
Title: Re: need to move 1 unsigned long serially really quick
Post by: jlefevre1 on Jan 08, 2013, 02:58 am
Here is the receiver code

Code: [Select]
int  redpin = 3;
int  greenpin = 5;
int  bluepin = 6;
int  amberpin = 9;
int  pinkpin = 10;
int  outA = 2;
int  outB = 4;
int  outC = 7;
int  outD = 8;
int  outE = 11;
int  outF = 12;
int  outG = 13;
int  red = 0;
int  green = 0;
int  blue = 0;
int  amber = 0;
int  pink = 0;
int  valuecmd = 0;

void setup ()
{
Serial.begin(9600); 
pinMode (redpin, OUTPUT);
pinMode (greenpin, OUTPUT);
pinMode (bluepin, OUTPUT);
pinMode (amberpin, OUTPUT);
pinMode (pinkpin, OUTPUT);
pinMode (outA, OUTPUT);
pinMode (outB, OUTPUT);
pinMode (outC, OUTPUT);
pinMode (outD, OUTPUT);
pinMode (outE, OUTPUT);
pinMode (outF, OUTPUT);
}

void loop ()
{
readserial ();
}

void  readserial ()
{
  while (Serial.available() > 0)
  {
    red = Serial.parseInt();
    green = Serial.parseInt();
    blue = Serial.parseInt();
    amber = Serial.parseInt();
    pink = Serial.parseInt();
    valuecmd = Serial.parseInt();
    if (Serial.read() == ';')
    {
      output128 ();
      output64 ();
      output32 ();
      output16 ();
      output8 ();
      output4 ();
      output2 ();
      output1 ();
    }
  }
}

void output128 ()
{
  if (valuecmd > 128)
  {
    valuecmd = valuecmd - 128;
    digitalWrite (outA, HIGH);
  }
  else
  {
    digitalWrite (outA, LOW);
  }
}

void output64 ()
{
  if (valuecmd > 64)
  {
    valuecmd = valuecmd - 64;
    digitalWrite (outB, HIGH);
  }
  else
  {
    digitalWrite (outB, LOW);
  }
}

void output32 ()
{
  if (valuecmd > 32)
  {
    valuecmd = valuecmd - 32;
    digitalWrite (outC, HIGH);
  }
  else
  {
    digitalWrite (outC, LOW);
  } 
}

void output16 ()
{
  if (valuecmd > 16)
  {
    valuecmd = valuecmd - 16;
    digitalWrite (outD, HIGH);
  }
  else
  {
    digitalWrite (outD, LOW);
  }
}

void output8 ()
{
  if (valuecmd > 8)
  {
    valuecmd = valuecmd - 8;
    digitalWrite (outE, HIGH);
  }
  else
  {
    digitalWrite (outE, LOW);
  }
}

void output4 ()
{
  if (valuecmd > 4)
  {
    valuecmd = valuecmd - 4;
    digitalWrite (outF, HIGH);
  }
  else
  {
    digitalWrite (outF, LOW);
  }
}

void output2 ()
{
  if (valuecmd > 2)
  {
    valuecmd = valuecmd - 2;
    digitalWrite (outF, HIGH);
  }
  else
  {
    digitalWrite (outF, LOW);
  }
}

void output1 ()
{
  if (valuecmd > 0)
  {
    red = red /  4;
    red = constrain (red, 0, 255);
    analogWrite (redpin, red);
    green = green / 4;
    green = constrain (green, 0, 255);
    analogWrite (greenpin, green);
    blue = blue / 4;
    blue = constrain (blue, 0, 255);
    analogWrite (bluepin, blue);
    amber = amber / 4;
    amber = constrain (amber, 0, 255);
    analogWrite (amberpin, amber);
    pink = pink / 4;
    pink = constrain (pink, 0, 255);
    analogWrite (pinkpin, pink);
  }
  else
  {
    analogWrite (redpin, 0);
    analogWrite (greenpin, 0);
    analogWrite (bluepin, 0);
    analogWrite (amberpin, 0);
    analogWrite (pinkpin, 0);
  }
}


   and here is the transmitter code



Code: [Select]
int  bcd1 = 2;
int  bcd2 = 3;
int  bcd4 = 4;
int  bcd8 = 5;
int  analogpinred = 0;
int  analogpingreen = 1;
int  analogpinblue = 2;
int  analogpinamber = 3;
int  analogpinpink = 4;
int  red = 0;
int  green = 0;
int  blue = 0;
int  amber = 0;
int  pink = 0;
int  valuecmd = 0;

void setup ()
{
Serial.begin(9600); 
pinMode  (bcd1, INPUT);
digitalWrite (bcd1, HIGH);
pinMode  (bcd2, INPUT);
digitalWrite  (bcd2, HIGH);
pinMode  (bcd4, INPUT);
digitalWrite (bcd4, HIGH);
pinMode  (bcd8, INPUT);
digitalWrite (bcd8, HIGH);
}

void loop ()
{
readanalog ();
buildbcd ();
serialoutput ();
}

void  readanalog ()
{
  red = analogRead(analogpinred);
  green = analogRead(analogpingreen);
  blue = analogRead(analogpinblue);
  amber = analogRead(analogpinamber);
  pink = analogRead(analogpinpink);
}


void  buildbcd ()
{
  valuecmd = 0;
  if (digitalRead(bcd1) == LOW)
  {
    valuecmd = valuecmd + 1;
  }
  if (digitalRead(bcd2) == LOW)
  {
    valuecmd = valuecmd + 2;
  }
  if (digitalRead(bcd4) == LOW)
  {
    valuecmd = valuecmd + 4;
  }
  if (digitalRead(bcd8) == LOW)
  {
    valuecmd = valuecmd + 8;
  }
}

void serialoutput ()
{
  Serial.print(red);
  Serial.print(",");
  Serial.print(green);
  Serial.print(",");
  Serial.print(blue);
  Serial.print(",");
  Serial.print(amber);
  Serial.print(",");
  Serial.print(pink);
  Serial.print(",");
  Serial.print(valuecmd);
  Serial.print(";");
  delay (300);
}


Notice the delay 300. It I decrease it to 200 the receiver no longer works.  


For the uninformed, 9600 baud using FSK for data transmission is the limit at 900 Mhz since you must modulate the carrier wave. Going up to 2.4 Ghz radios will not work because while the data rate can go up considerably, the range falls apart becasue 2.4 Ghz will not penetrate more than 1 wall reliably. I need to transmit from inside the house to receivers in the yard ( several receivers actually ).

I am going to go to the single long integer. I will use 5 groups of 4 bits to run 5 outputs in PWM which will give 16 steps of dimming to those outputs. Then I will use 7 more bits to control the remaining outputs as on and off only.

I am going to try the example at the Arduino web site    http://arduino.cc/en/Tutorial/Dimmer

Do you all hate that example also.


Moderator edit: [code] [/code] tags added.
Title: Re: need to move 1 unsigned long serially really quick
Post by: retrolefty on Jan 08, 2013, 03:32 am
Your serial receiver code is all wrong. You are assuming you can read many many characters that have not yet arrived based on using only one serial.available command, plus I'm sure you have other faults in the receiver logic but the first one above is a show stopper. Serial.available returns the amount of characters you can read and are avalible for your use, you can read no more characters unless you know for sure they have arrived and are waiting in the software buffer holding them. The way you are using serial.available will trigger when the very first character arrives, yet you go ahead and assume many other characters have arrived and read bogus characters into a bunch of variables.

This needs a rewrite once you get a better handle on how serial works and the need to deal with each individual serial character when it indeed has arrived.

Lefty

Title: Re: need to move 1 unsigned long serially really quick
Post by: retrolefty on Jan 08, 2013, 06:22 am
You know that there is a library available that will do your transfer of variables from arduino to ardino via serial all automatically. Just a matter of putting the required variables into a single structure on both ends and using the easy transfer library. Good stuff, give it a try.

http://www.billporter.info/2011/05/30/easytransfer-arduino-library/

Lefty