I am reprogramming an AAG weather station which has a MAX485 style transceiver for serial interface. The microcontroller is an Atmega8. PD2 is used to control the data direction.
I would like to modify the existing HardwareSerial routines rather than write new ones. I've read through the library and it looks pretty straightforward to add control of the data direction to the transmit and receive routines. Is there anything in particular I should look out for?
The original weather station firmware used a packetized communication protocol with a header string, packet length, address, data, and checksum. While this worked pretty well, I am considering using a 9-bit data word and the Multi-processor Communication mode (MPCM) supported by the Atmega8. Does anyone see that this will unnecessarily complicate re-writing the serial library?
I realize that the answers depend largely on my programming skills. I have some decades of experience programming in assembler and while my knowledge of C/C++ is relatively limited, I take direction real well.
I would like to modify the existing HardwareSerial routines rather than write new ones. I've read through the library and it looks pretty straightforward to add control of the data direction to the transmit and receive routines. Is there anything in particular I should look out for?
I would think it would be pretty simple to add the pin direction commands into the serial library sending function at this time. However the arduino 1 latest release does or will come out with interrupt driven transmit function, so that might make it a bit of a different animal to figure out how to do proberly if even possible?
The main problem is in detecting that the UART output has finished in order to avoid prematurely shutting off the RS485 transmitter.
This is the code I've been using, with references to my sources.
/* I/O pins used for RS485 comms
*/
#define SERIAL_DUPLEX 2
#define SERIAL_XMIT 1
#define SERIAL_RECV 0
/* transmit a frame from a memory buffer
*/
void frame_send(uint8_t *data, int len)
{
uint8_t i, l;
l = (uint8_t) len;
/* Magic stuff from
* http://real2electronics.blogspot.com/2009/09/arduino-and-rs485-english-version.html
* Reset the transmitter empty flag then turn on the serial transmitter.
* Wait a short time -- 200 microsecs is about 2 bit widths -- before
* beginning transmission.
*/
UCSR0A = UCSR0A |(1 << TXC0);
digitalWrite(SERIAL_DUPLEX, HIGH);
delayMicroseconds(200);
frame_send_begin(l);
for (i = 0; i < l; i++)
frame_send_byte(*data++);
frame_send_end();
/* wait for the output to drain
*/
while (!(UCSR0A & (1 << TXC0)));
digitalWrite(SERIAL_DUPLEX, LOW);
}
The main problem is in detecting that the UART output has finished in order to avoid prematurely shutting off the RS485 transmitter.
This is the code I've been using, with references to my sources
That was mentioned in the Atmega8 data sheet as well. Thanks for reminding me and thanks for the code example.
I would think it would be pretty simple to add the pin direction commands into the serial library sending function at this time. However the arduino 1 latest release does or will come out with interrupt driven transmit function, so that might make it a bit of a different animal to figure out how to do proberly if even possible?
Lefty
I'm not particularly concerned about that. I'll use whatever library I modify and even stick with 0022 or earlier if necessary. In fact, I might drop back to 0016 or so anyway so that the output files are easier to find. In OS X, the 0022 IDE buries them so deeply that the full path can't even be displayed in the verbose output.
Graynomad:
I'd grab the current TX code, rename and modify it and make it part of your app, then you are not bound to any particular release version.
Rob
That's what I've done. Once you clean all the conditionals out and are left with the source for your particular chip, it's pretty straightforward. I'm not too proud to yell for help if I run into any problems, though.
While modifying the HardwareSerial library, I discovered that Serial.print uses about 120 bytes per call, than Serial.write. That's quite a difference and good to know since I only have 8K of flash.
I'm talking to the designer of this 'brick' about changes he wants to make...
In a point-to-point RS485 link I was thinking about being able to have the serial transmit function signal itself control the direction of the rs485 chip, sort of like VOX? If it was fast enough the start bit wouldn't be shortened much. Or maybe that's not workable.. Haven't tried it..
terryking228:
Hi, Still a little confused about what you're doing! Are you modifying the 'new' AAG product seen here: http://www.aag.com.mx/aagusa/index1.html??
I'm talking to the designer of this 'brick' about changes he wants to make...
In a point-to-point RS485 link I was thinking about being able to have the serial transmit function signal itself control the direction of the rs485 chip, sort of like VOX? If it was fast enough the start bit wouldn't be shortened much. Or maybe that's not workable.. Haven't tried it..
The AAG I'm modifying is the WS602 RS485 Weather Instrument. It comes with an RS485 to USB bridge as part of the kit.
I can't tell for sure but it looks like the Arduino serial port is dedicated to RS485 through the sensor shield so you would have to upload a sketch and then let the sketch communicate with the AAG.
You might be able to trigger a re-triggerable one-shot to keep the driver enabled long enough to work but like you say it might not turn on fast enough. Certainly worth a try. Might work at the lower baud rates.
You might be able to trigger a re-triggerable one-shot to keep the driver enabled long enough to work
There was an old trick using a 555 that did just that, Google should find it.
But these days you can use auto-direction transceivers like the MAX13410.
Rob
I knew it was a good idea but like many of mine, someone else had it first!!