Pages: [1]   Go Down
Author Topic: Serial Communication Help Needed.  (Read 848 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So i need some help...

I need to send in 6 variables through the serial port in the Mega.
The variables are 4 ints and 2 floats. The ints are between -180 and +180, the floats are Latitude and Longitude from GPS, both are 7 digit numbers.
Now i've set up everything and everything works like a charm. But, i want to get my program to execute at least 200Hz, and the bottleneck is the serial communication. Without it , my program runs near 500Hz, but with the serial i can only get 100Hz.

It takes about 3-4ms for the Serial to send everything i want, while my program executes about 1-1.5ms. Is there a way i can make the serial much faster, at least twice as fast? My baudrate is already at 115200.

I would like to only send only 6 (no more than 6) variables as well, so i am clueless how to go about increasing the speed.

The program on the computer side, reads the serial buffer 6 times and stores the values. Then i do some graphical stuff with the data, "real time". So every time i am sending data it must be 6 variables, no less no more.

I am thinking of sending the data through I2C to another Arduino that then sends its to my computer. Acting something like a Register (pipeline). That way my mega can continue to run. Not sure if it work they way i think it would...
So while i am working on that, i thought that i would ask for help.


Some things i've tried, but failed:
Sending the GPS data only when it was available ( 1 Hz). It works until the gps data needs to be send. I am using a timer interrupt, so for 200 Hz, the timer interrupt is set at 5ms. As soon I send the GPS data , the thing farts and crashes...
Converting the floats to a long, but the converted long takes longer to send so not really an improvement.

 
Summary of my problem: Takes too long to send what i want. Goal is to have the program execute at least at 200Hz, and sending everything (the 6 variables mentioned above). Is it realistically possible? If so do you guys have any ideas how?

Please help. smiley
« Last Edit: September 05, 2010, 03:35:58 am by BalkanLion » Logged

0
Offline Offline
Edison Member
*
Karma: 0
Posts: 1103
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I read twice through your question. I still do not understand why you want to  send the same data 200 times to the PC? There is no change to the GPS data!

So it needs to find why your program crashed....
There is no need for a timer at all.  How is the GPS connected? NewSoftwareSerial? So you haveto check when the 80 NMEA bytes arrive. you are ready after the CR/NL arrives and can send the data to the PC....
« Last Edit: September 05, 2010, 06:52:10 am by mpeuser » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I read twice through your question. I still do not understand why you want to  send the same data 200 times to the PC? There is no change to the GPS data!

So it needs to find why your program crashed....
There is no need for a timer at all.  How is the GPS connected? NewSoftwareSerial? So you haveto check when the 80 NMEA bytes arrive. you are ready after the CR/NL arrives and can send the data to the PC....

I know there is no change in the GPS, but i have some other sensors that can update at 200Hz or faster, ( accelerometer,Gyro scope and later a Magnetometer)
I am using the timer interrupt to precisely get the other sensor data.
The program crashes because the interrupt is triggered before everything is executed.
 
Quote
WHY?  Nothing you can attach this to moves fast enough to warrant that update speed. And no GPS updates that fast, either.

I've set up the program to stabilize a quadrotor helicopter. 200Hz would be enough to stabilize it, but i am not sure if 100Hz is good enough. Reason i want it faster is because i will be adding more functions.

So any ideas?

Currently i can get everything to execute faster than 200Hz, but i need the data. The quadrotor will be controlled from "distance",( Joystick on the PC). Everything is displayed on my PC. Attitude ( roll,pitch,yaw) as well its current heading and possition. Later on i will add altitude to ground, but for now i just want to get it as fast as possible with just the 6 variables .
(Roll,Pitch,Yaw,Latitude,Longitude,Other)
Roll and Pitch is in between +-180 ( hopefully it will never get near +- 50 degrees though)

Yaw is +-180

Latitude is the floating point in degrees dd.dddd
Longitude is again the floating point number in degrees ddd.ddddd

The Other will be an int, probably the Altitude to group.

So do you guys have any idea who i can get the Serial Faster?
« Last Edit: September 05, 2010, 12:47:21 pm by BalkanLion » Logged

0
Offline Offline
Edison Member
*
Karma: 0
Posts: 1103
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The usual approch to such problems is to send the deltas only.

This however would need a little bit intelligence at the PC side (it should have enough...)

This will eliminate the GPS immediately, also all the other values are unlikely to change so rapidly. A low pass filter to eliminate the obvious noise from ADC is recommended anyway...
« Last Edit: September 05, 2010, 01:12:13 pm by mpeuser » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will be maintaining  eye contract with the thing itself, but i want to be able to see its Attitude and everything i mentioned above on my PC, (sort of like a cockpit). Later on, maybe for my undergrad project i was thinking of making it a completed UAV...

Quote
Relying on off-board computing to keep the helicopter flying is a guaranteed way of crashing it.

No, everything is computed on the arduino ( on board) no calculations are done on the PC.

But now the only thing slowing me down is the Serial. Everything else works great. Without the Serial it would fly like a charm, but i want Serial Communication (obviously wireless smiley )  for my project.

deSilva:
I calculate the angles on the Arduino with no noise i then pass them along to the PC, i am not sending the ADC values. Same with the GPS, i get the GPS NMEA line and covert the Lat and Long to degrees. Then i send it. I am avoiding floating math until the last steps so it all executes quite fast ( under 1.5ms).

 By deltas do you mean just sending the data that changes? I've tried that, but i am using a timer interrupt to trigger my sampling, so when i am sending more data, the loop that is supposed to execute in less then say 5ms, (200Hz) would take longer and the interrupt interrupts smiley and all the date goes down the drain.

« Last Edit: September 05, 2010, 01:38:45 pm by BalkanLion » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26487
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is your problem caused by the Arduino blocking whilst sending serial?
What about interrupt-driven serial?

I'd turn this around and ask how much data you could send at 200Hz at 11520 bytes per second. (57 bytes per frame)
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is your problem caused by the Arduino blocking whilst sending serial?
What about interrupt-driven serial?

I'd turn this around and ask how much data you could send at 200Hz at 11520 bytes per second. (57 bytes per frame)

Problem is i am spending 55-60% of the time sending the data.

Breakdown of my program: us=microseconds

Sampling=712us
Attitude Calculations= 580 us ( both angles smaller than -130 degrees, worst case)
GPS = 364us ( every second. Otherwise 34us)
Control Algorithm = extremely worst case 1-1.5 ms
Serial Comm = 3928 us.
 
I just need ideas on how to better send in the data.
« Last Edit: September 05, 2010, 02:33:09 pm by BalkanLion » Logged

0
Offline Offline
Edison Member
*
Karma: 0
Posts: 1103
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I try again:
(1) There is no need for interrupts in your application. In fact I have NEVER seen an issues here brought to the forum, where interrupt was needed, and - if used - had not made the situation even worse..
(2) You might have a THROUGHPUT problem. The bottleneck I see is attitude and control =2ms. Is this "control" really needed at high frequency?
(3) Serial communication for HardwareSerial should not need processor time.. You could avoid the waiting involved in multicharacter sending by sending on a character by character basis with activities in between. This needs some coding of course...
(4) There is also some hidden waiting in the analogRead() routine, which can be re-claimed by direct accessing the ADC..
(5) By detats I mean: Just the differences! So you have 6 values (A,B,C,D,E,F) the old values already sent were (a,b,c,d,e,f)
Now you send this:
if (a-A !=0) "A" (a-A)
if (b-B !=0) "B" (b-B)
if (c-C !=0) "C" (c-C)
if (d-D !=0) "D" (d-D)
if (e-E !=0) "E" (e-E)
if (f-F !=0) "F" (f-F)


« Last Edit: September 05, 2010, 02:50:29 pm by mpeuser » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26487
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Problem is i am spending 55-60% of the time sending the data
As deSilva has pointed out, you're spending all that time blocking waiting on sending the data.

The way serial writes work is that the library routines take, say, a string and write it one character at a time, waiting for the serial transmit register to become empty before writing another character.
In this time, the processor does nothing except read and test a UART status register
As soon as the last character is written to the transmit register, the write routine routine returns.
At 115200 bps, each character takes about 87us to transmit, and you're sending (I estimate) about 46 characters.
So, don't send strings, send one character at a time, and use the 86 or so microseconds you gain not waiting for the tx register to become empty to do something more productive.

(PS pretty much the same story for the "analogRead"s)
« Last Edit: September 05, 2010, 03:01:16 pm by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Posted by: deSilva      Posted on: Today at 21:49:45
I try again:
(1) There is no need for interrupts in your application. In fact I have NEVER seen an issues here brought to the forum, where interrupt was needed, and - if used - had not made the situation even worse..
(2) You might have a THROUGHPUT problem. The bottleneck I see is attitude and control =2ms. Is this "control" really needed at high frequency?
(3) Serial communication for HardwareSerial should not need processor time.. You could avoid the waiting involved in multicharacter sending by sending on a character by character basis with activities in between. This needs some coding of course...
(4) There is also some hidden waiting in the analogRead() routine, which can be re-claimed by direct accessing the ADC..
(5) By detats I mean: Just the differences! So you have 6 values (A,B,C,D,E,F) the old values already sent were (a,b,c,d,e,f)
Now you send this:
if (a-A !=0) "A" (a-A)
if (b-B !=0) "B" (b-B)
if (c-C !=0) "C" (c-C)
if (d-D !=0) "D" (d-D)
if (e-E !=0) "E" (e-E)
if (f-F !=0) "F" (f-F)

Thank you. I will try it. I feel stupid for not thinking of doing it like that smiley. I will see if the interrupt is really needed

I've actually not timed the control algorithm, just put a extremely worst case scenario, might never occur. A more accurate estimate would be around 500-700 us.

I will give your method a shot, as it doesn't require changing much of the PC program.

Again thank you smiley .


Quote
As deSilva has pointed out, you're spending all that time blocking waiting on sending the data.

The way serial writes work is that the library routines take, say, a string and write it one character at a time, waiting for the serial transmit register to become empty before writing another character.
In this time, the processor does nothing except read and test a UART status register
As soon as the last character is written to the transmit register, the write routine routine returns.
At 115200 bps, each character takes about 87us to transmit, and you're sending (I estimate) about 46 characters.
So, don't send strings, send one character at a time, and use the 86 or so microseconds you gain not waiting for the tx register to become empty to do something more productive.

(PS pretty much the same story for the "analogRead"s)

Can you explain that a bit more?
if i have variable  int i=180 and do
Serial.print(i); Serial.print(",");

i am sending 4 characters in total ?I lack a lot of knowledge about Serial Communication...

Thank you.


Problem solved:
So i tried something different before i read DeSilva's reply and it worked, no need to change the PC program as well.
here is what i did.

Easier explained in code:
Quote
void loop()
{
    ...
    //last lines
    Serial.print(DataTelemetry[dataToBeSent]);Serial.print(",");
    dataToBeSent++;
    if ( dataToBeSent>=5) {
      dataToBeSent=0;
      Serial.println(dt);
    waitToSample=true;
    }
}

Thank you guys.

I've yet to give deSilva idea a shot.
« Last Edit: September 05, 2010, 03:54:08 pm by BalkanLion » Logged

Pages: [1]   Go Up
Jump to: