Pages: 1 [2] 3   Go Down
Author Topic: How to know when serial has finished sending  (Read 2513 times)
0 Members and 1 Guest are viewing this topic.
Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
A robust flush() solution has to handle all conditions when called.
- A character in the transmit shift register and no character in TXB.
- A character in TXB and in the transmit shift register
- No characters in TXB or the shift register.

What I found is that some potential solutions didn't handle all of the
above situations or couldn't handle them more than once.

Well many of us use to complain that the serial transmitting function was a simple blocking command so I guess the lesson is to be very careful what you ask for as you may get it.  smiley-wink
« Last Edit: August 18, 2012, 11:25:55 am by retrolefty » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 127
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@bperrybap so there isn't a solution? You said "I had to modify the UDRE0 ISR routine and the flush() routine to make flush() work correctly and reliably
in my testing.", so how can I do the same?
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 127
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@retrolefty if it's going to send serial in the background, there needs to be a way to know when it has finished. If there isn't a solution that supports the current implementation, then perhaps I will bit-bang the output.
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@retrolefty if it's going to send serial in the background, there needs to be a way to know when it has finished. If there isn't a solution that supports the current implementation, then perhaps I will bit-bang the output.

And perhaps that will work for you. I think what Bill was trying to convey is that one really needs to understand the AVR hardware functions at the basic register level (serial hardware in this case) and even then be careful of what is possible at this level via what one's actual real world application requirements are. Sometimes there is no 'perfect' match or solution and the best compromise possible is what one has to live with. I don't know it that is the case with this issue or not, but I've worked with serial communications sense the mid 60s and it is amazing how unsimple and error prone asynchronous communications can be, especially when dealing with mixed vendors implementation, both in software and hardware.

Lefty
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 626
Posts: 34122
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Most processors do not implement this function. Therefore things like changing the transmit / receive flags on RS485 bi directional buffers is difficult. The common solution is to look for the buffer empty flag and then implement a delay such that when it times out your buffer will be empty. This of course depends on the baud rate you are using.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 127
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Grumpy_Mike that is exactly what I'm trying to do (communicate with RS485), and also exactly how I am currently doing it (flush and then delay) smiley-wink
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 626
Posts: 34122
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I thought as much. Delay too long and the other end can reply and you miss the first byte, delay too short and you screw the last byte. When my engineers have tackled this in the past we found it best to have a packet format that was tolerant of loosing the first and last bytes. But then we were in control of the packet format.
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I thought as much. Delay too long and the other end can reply and you miss the first byte, delay too short and you screw the last byte. When my engineers have tackled this in the past we found it best to have a packet format that was tolerant of loosing the first and last bytes. But then we were in control of the packet format.

Or go to two twisted pair full duplex RS485 where you don't have to deal with controlling a direction driver/converter chip?

Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 127
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Grumpy_Mike I'm using 115200 baud, so 1ms delay is enough for 14 bytes. If I use a 1ms delay after I use flush, then it should be at least 7-14 times longer than necessary (which is okay, because the other device on the bus won't start transmitting until a minimum of 1ms after the last byte has been received from the Arduino). I do have complete data format control, as I am writing the software for both ends.

@retrolefty that's not an option, due to the HW setup of the other controller (Lego NXT). I also want to be able to have more than 2 devices on the bus.
« Last Edit: August 18, 2012, 01:12:39 pm by mattallen37 » Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Grumpy_Mike I'm using 115200 baud, so 1ms delay is enough for 14 bytes. If I use a 1ms delay after I use flush, then it should be at least 7-14 times longer than necessary (which is okay, because the other device on the bus won't start transmitting until a minimum of 1ms after the last byte has been received from the Arduino). I do have complete data format control, as I am writing the software for both ends.

@retrolefty that's not an option, due to the HW setup of the other controller (Lego NXT). I also want to be able to have more than 2 devices on the bus.

There is of course delayMicroseconds() if you want to cut it closer then 7-14 bytes.

Lefty
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 127
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Good point.

Thanks everyone for your help and ideas. I really appreciate it!
Logged

Chile
Offline Offline
Edison Member
*
Karma: 35
Posts: 1251
Arduino rocks?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Good point.

Thanks everyone for your help and ideas. I really appreciate it!

Ops, sorry! I didn't noticed your second message, but now I understand it was from arduino not receiving smiley
Logged

My website: http://ried.cl

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18767
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@Nick Gammon, the compiler complains that some of the variables are undeclared (as if maybe I need to #include something).

Perhaps if you posted your test code, and your error message? This code compiles without errors for me:

Code:
void setup ()
{
  Serial.begin (115200);
 
  // empty output buffer
  Serial.flush ();
  // wait for transmit buffer to empty
  while ((UCSR0A & _BV (TXC0)) == 0)
    {}
   
}
void loop () {}
Logged


0
Offline Offline
Full Member
***
Karma: 0
Posts: 127
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, I had the board set to SparkFun Pro Micro, so most likely the registers are called something else (since it uses the AtMega32U4 instead of the AtMega328). Setting the board to Uno, it compiles fine. Thanks!
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, I had the board set to SparkFun Pro Micro, so most likely the registers are called something else (since it uses the AtMega32U4 instead of the AtMega328). Setting the board to Uno, it compiles fine. Thanks!

That doesn't make sense? Could you link to the SparkFun pro board you are talking about, I would think they all use a 328 micro.

Lefty
Logged

Pages: 1 [2] 3   Go Up
Jump to: