Got two MAX485s connected to two MCU's, one is Arduino and another is mBed board which simply displays data on terminal of whatever it is receiving.
The snapshot of the code at arduino with problem is below:
ISR (TIMER1_COMPA_vect){
state1=0;
deBounce++;
if (deBounce==60) deBounce=0;
if (digitalRead(start)) bitSet(state1,0);
if (!digitalRead(but1)) bitSet(state1,5);
if (!digitalRead(but2)) bitSet(state1,6);
if (!digitalRead(but3)) bitSet(state1,7);
//.
//.
//. and so on upto 12 buttons
if (deBounce==20){
digitalWrite(txRx,HIGH) ; // put max485 in transmit mode and send data below after a certain delay which is apps 50mS for the interrupt
Serial3.println(state1,BIN);
// digitalWrite(txRx,LOW); -> code works fine with this commented but without this I am not able to receive data. I tried putting a delay(5) before this statement but something goes wrong with the data at the other end if this line is not commented.
}
}
Can someone please explain why this behaviour of max485?
Sorry about that, I am sure I typed this but it seems something went wrong with my mac as well
So for example - If I send "Test" I will receive "Test" at the other end with that line commented but I will only receive "Te" if I uncomment it, even if I add a 5 second delay before pulling the pin low, I get the same result.
HardwareSerial uses interrupts. You must wait till all data has been send before you disable the MAX485 by e.g. using a delay (as you tried).
Your code is inside an interrupt routine; so interrupts are disabled and the HardwareSerial will not be able to send all data.
It works if you don't disable the MAX485 because when you leave the ISR the HardwareSerial is able to finish its work.
Conclusion: don't use HardwareSerial inside an ISR. Set a flag that there is data to be transmitted, check the flag in loop() and if set, send the data and clear the flag.
Note: there is a method AvailableForWrite that you might have to use to determine when to disable the MAX485 chip. No experience with RS485 or the method so you have to fiddle a bit
The hardware serial is kind of hands-off. You only get to load a byte into the hardware register and then it decides when to send the bits. You don't normally need to know when the bits have been sent. An ISR should absolutely NOT wait that long. acaulableForWrite() is useful but it only sees the software buffer and can't see into the last byte in the hardware buffer.
If you dig deep enough into the datasheet for your chip, you may find there is a register you can inspect to see if the serial is currently transmitting. Depending on which chip, you may find that it can be configured specifically in RS485 mode and there is a dedicated pin to drive the transmit select line.
You need to flush serial output as it is asynchronously handled via an ISR.
You start buffer up the data and cancel TX mode before the buffer has all been sent. You
must wait for the buffer to drain before cancelling TX mode.
As you are doing this in an ISR you'll have to test for availableForWrite () getting back to
its starting value (the buffer len) and then test for 1 byte's time to elapsed before clearing txRx
A small state machine is needed to manage all this - it is not trivial.