@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)
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.
Grumpy_Mike:
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?
@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.
mattallen37:
@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
Good point.
Thanks everyone for your help and ideas. I really appreciate it!
mattallen37:
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
mattallen37:
@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:
void setup ()
{
Serial.begin (115200);
// empty output buffer
Serial.flush ();
// wait for transmit buffer to empty
while ((UCSR0A & _BV (TXC0)) == 0)
{}
}
void loop () {}
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!
mattallen37:
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
Here. It's basically a Leonardo, not an Uno.
Waiting for Serial to finish on the Leonardo is a different kettle of fish, as that goes through the USB interface. Serial1 would be similar to Serial on the Uno, although I don't know about the register names on the Leonardo as it is a different chip.
Matt, your RS485 transceiver should detail the time it takes to clock out a bit in the datasheet. For very fast communication, you would need to know this (it's easy to wait too long). For doing the same thing, I have (generally):
#include <util/delay.h>
...
#define SER_BPS 57600.0
// serial clear time in uS (how long it takes to punch one bit
// out through the RS485 transceiver at the current bitrate).
// the transceiver adds 0.07uS delay in punching out a bit
#define SER_CLEAR_TM 1000000.0 / SER_BPS + 0.07
...
void write(uint8_t p_dat) {
// TODO: Abstract for non Atmega328P platforms
while (!(UCSR0A & _BV(UDRE0)));
// set xmit pin high
PORTD |= _BV(PORTD5);
// clear tx complete flag before write, just incase serial object doesn't
UCSR0A |= _BV(TXC0);
UDR0 = p_dat;
while(!(UCSR0A & _BV(TXC0)) );
_delay_us(SER_CLEAR_TM);
PORTD &= ~_BV(PORTD5);
}
I am using the HW UART, which is called Serial1.
Using flush and then waiting 1ms is fine.