|
|
|
@ -7,11 +7,18 @@
@@ -7,11 +7,18 @@
|
|
|
|
|
#include "SoftRS485.h" |
|
|
|
|
|
|
|
|
|
//#define DEBUG
|
|
|
|
|
|
|
|
|
|
#define MSG_LEN 64 |
|
|
|
|
#define IDLE 0 |
|
|
|
|
#define WAIT 1 |
|
|
|
|
#define SEND 2 |
|
|
|
|
#define SENT 3 |
|
|
|
|
|
|
|
|
|
#define TIMER 250 |
|
|
|
|
// Pins
|
|
|
|
|
int _RO, _RE, _DE, _DI; |
|
|
|
|
long _pulse_len = 100; |
|
|
|
|
long _pulse_len = 850; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Receive vars
|
|
|
|
|
boolean _recv_bit = false; |
|
|
|
@ -21,6 +28,28 @@ int _recv_pos = 0;
@@ -21,6 +28,28 @@ int _recv_pos = 0;
|
|
|
|
|
int _recv_idx = 0; |
|
|
|
|
boolean _avail = false; |
|
|
|
|
|
|
|
|
|
// Send vars
|
|
|
|
|
char _send_message[MSG_LEN]; |
|
|
|
|
int _send_state = IDLE; |
|
|
|
|
int _send_pos = 0; |
|
|
|
|
int _send_idx = 0; |
|
|
|
|
boolean _send_bit = false; |
|
|
|
|
|
|
|
|
|
void enableSendTimer(){ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("Enabling send timer. Old Value: b")); |
|
|
|
|
Serial.println(TIMSK1,BIN); |
|
|
|
|
#endif |
|
|
|
|
TIMSK1 |= B00000010; // Enable Timer COMPA Interrupt
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void disableSendTimer(){ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println("Disable send timer"); |
|
|
|
|
#endif |
|
|
|
|
TIMSK1 = TIMSK1 & ~B00000010; // Enable Timer COMPA Interrupt
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void interrupt485(){ |
|
|
|
|
_recv_bit = !digitalRead(_RO); // HIGH level = logical zero and vice versa
|
|
|
|
|
long now = micros(); |
|
|
|
@ -28,22 +57,36 @@ void interrupt485(){
@@ -28,22 +57,36 @@ void interrupt485(){
|
|
|
|
|
_last_flip = now; |
|
|
|
|
if (diff > 20*_pulse_len){ // we received a start bit
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("State changed to ")); Serial.println(_recv_bit); |
|
|
|
|
Serial.println(F("received start bit")); |
|
|
|
|
#endif |
|
|
|
|
_recv_pos = 0; |
|
|
|
|
_recv_idx = 0; |
|
|
|
|
_last_flip+=_pulse_len; |
|
|
|
|
} else { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(diff); |
|
|
|
|
Serial.println("µs"); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
long count = diff/_pulse_len; |
|
|
|
|
for (int i=0; i<count; i++){ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(_recv_bit); |
|
|
|
|
Serial.println(" <="); |
|
|
|
|
#endif |
|
|
|
|
if (_recv_idx == 0) { |
|
|
|
|
_recv_msg[_recv_pos] = (!_recv_bit); |
|
|
|
|
_recv_msg[_recv_pos] = (_recv_bit); |
|
|
|
|
} else { |
|
|
|
|
_recv_msg[_recv_pos] |= (!_recv_bit)<<_recv_idx; |
|
|
|
|
_recv_msg[_recv_pos] |= (_recv_bit)<<_recv_idx; |
|
|
|
|
} |
|
|
|
|
_recv_idx++; |
|
|
|
|
if (_recv_idx == 8){ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("0x"); |
|
|
|
|
Serial.print(_recv_msg[_recv_pos],HEX); |
|
|
|
|
Serial.print(" recevied / "); |
|
|
|
|
Serial.println((char)_recv_msg[_recv_pos]); |
|
|
|
|
#endif |
|
|
|
|
_recv_idx = 0; |
|
|
|
|
if (_recv_msg[_recv_pos] == 0x00){ |
|
|
|
|
_avail = _recv_pos != 0; |
|
|
|
@ -55,6 +98,102 @@ void interrupt485(){
@@ -55,6 +98,102 @@ void interrupt485(){
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ISR(TIMER1_COMPA_vect){ |
|
|
|
|
OCR1A += TIMER; // Advance The COMPA Register
|
|
|
|
|
|
|
|
|
|
boolean echo = digitalRead(_RO); |
|
|
|
|
|
|
|
|
|
if (_send_state == SENT){ |
|
|
|
|
if (echo != _send_bit){ |
|
|
|
|
digitalWrite(_DE,LOW); |
|
|
|
|
_send_state = WAIT; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Collision")); |
|
|
|
|
#endif |
|
|
|
|
} else { |
|
|
|
|
digitalWrite(_DE,LOW); |
|
|
|
|
_send_message[0] = 0x00; |
|
|
|
|
_send_state = IDLE; |
|
|
|
|
disableSendTimer(); |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Transmission complete")); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_send_state == SEND){ |
|
|
|
|
if (echo != _send_bit){ |
|
|
|
|
digitalWrite(_DE,LOW); |
|
|
|
|
_send_state = WAIT; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Collision")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
char c = _send_message[_send_pos]; |
|
|
|
|
_send_bit = c & (1 << _send_idx); |
|
|
|
|
digitalWrite(_DI,_send_bit); |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
if (!_send_idx) { |
|
|
|
|
Serial.print("Sending "); Serial.print(c); Serial.print(" / 0x"); Serial.println(c,HEX); |
|
|
|
|
} |
|
|
|
|
Serial.print("<--- "); Serial.println(_send_bit); |
|
|
|
|
#endif |
|
|
|
|
_send_idx++; |
|
|
|
|
if (_send_idx == 8) { |
|
|
|
|
_send_idx = 0; |
|
|
|
|
_send_pos++; |
|
|
|
|
if (c == 0x00 || _send_pos == MSG_LEN){ |
|
|
|
|
_send_state = SENT; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_send_state == WAIT){ |
|
|
|
|
long diff = micros() - _last_flip; // µs
|
|
|
|
|
long idle_count = diff / _pulse_len; |
|
|
|
|
if (idle_count > MSG_LEN){ |
|
|
|
|
_send_bit = LOW; |
|
|
|
|
digitalWrite(_DE,HIGH); |
|
|
|
|
digitalWrite(_DI,_send_bit); |
|
|
|
|
_send_state = SEND; |
|
|
|
|
_send_idx = 0; |
|
|
|
|
_send_pos = 0; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Sending start bit (1)")); |
|
|
|
|
#endif |
|
|
|
|
} else { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Bus busy")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
echo = digitalRead(_RO); |
|
|
|
|
if (echo != _send_bit){ |
|
|
|
|
digitalWrite(_DE,LOW); |
|
|
|
|
_send_state = WAIT; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Collision")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void configureSendTimer(){ |
|
|
|
|
TCCR1A = 0; // Init Timer1A
|
|
|
|
|
TCCR1B = 0; // Init Timer1B
|
|
|
|
|
TCCR1B |= B00000011; // Prescaler = 1
|
|
|
|
|
OCR1A = TIMER; // Timer Compare1A Register
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void init485(int RO, int nRE, int DE, int DI){ |
|
|
|
|
_RO=RO; |
|
|
|
|
_RE=nRE; |
|
|
|
@ -73,7 +212,7 @@ void init485(int RO, int nRE, int DE, int DI){
@@ -73,7 +212,7 @@ void init485(int RO, int nRE, int DE, int DI){
|
|
|
|
|
digitalWrite(_DI,LOW); // output line = LOW
|
|
|
|
|
|
|
|
|
|
attachInterrupt(digitalPinToInterrupt(_RO),interrupt485,CHANGE); |
|
|
|
|
|
|
|
|
|
configureSendTimer(); |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.begin(115200); |
|
|
|
|
Serial.print(F("RO = ")); |
|
|
|
@ -88,15 +227,6 @@ void init485(int RO, int nRE, int DE, int DI){
@@ -88,15 +227,6 @@ void init485(int RO, int nRE, int DE, int DI){
|
|
|
|
|
_last_flip = micros(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void speed485(long baudrate){ |
|
|
|
|
#ifndef DEBUG |
|
|
|
|
_pulse_len = 1e6 / baudrate; |
|
|
|
|
#else |
|
|
|
|
_pulse_len = 1000; |
|
|
|
|
Serial.print(F("Set pulse_len to ")); Serial.print(_pulse_len); Serial.println(F("µs")); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean available485(){ |
|
|
|
|
return _avail; |
|
|
|
|
} |
|
|
|
@ -106,59 +236,29 @@ String get485message(){
@@ -106,59 +236,29 @@ String get485message(){
|
|
|
|
|
return String((char*)_recv_msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean writeBit(boolean bit){ |
|
|
|
|
digitalWrite(_DI,!bit); |
|
|
|
|
delayMicroseconds(5); |
|
|
|
|
if (_recv_bit != bit){ // collision!
|
|
|
|
|
digitalWrite(_DE,LOW); |
|
|
|
|
|
|
|
|
|
boolean send485(String message){ |
|
|
|
|
if (_send_message[0] != 0x00) { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Collision!")); |
|
|
|
|
Serial.println("Busy!"); |
|
|
|
|
#endif |
|
|
|
|
return false; |
|
|
|
|
return false; // we already have a queued message, abort!
|
|
|
|
|
} |
|
|
|
|
delayMicroseconds(_pulse_len-5); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean send485(char message[]){ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("preparing to send ")); |
|
|
|
|
Serial.print(message); |
|
|
|
|
Serial.print(F(": line state = ")); |
|
|
|
|
Serial.print(_recv_bit); |
|
|
|
|
Serial.print(F(" / last_flip = ")); |
|
|
|
|
Serial.print(_last_flip); |
|
|
|
|
Serial.print(F(" / micros = ")); |
|
|
|
|
Serial.println(micros()); |
|
|
|
|
Serial.print(F("Preparing to send ")); Serial.println(message); |
|
|
|
|
#endif |
|
|
|
|
while (_recv_bit || (micros() - _last_flip) < (20 * _pulse_len)) { |
|
|
|
|
delayMicroseconds(20*_pulse_len); |
|
|
|
|
const char* buf = message.c_str(); |
|
|
|
|
for (int idx = 0; idx<MSG_LEN; idx++){ |
|
|
|
|
_send_message[idx] = buf[idx]; // copy message
|
|
|
|
|
if (_send_message[idx] == 0x00) break; |
|
|
|
|
} |
|
|
|
|
if (_send_message[0] == 0x00) return false; // message is empty
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("enabling driver…")); |
|
|
|
|
Serial.print(F("Message copied to send buffer: ")); |
|
|
|
|
Serial.println(_send_message); |
|
|
|
|
#endif |
|
|
|
|
digitalWrite(_DE,HIGH); // enable driver
|
|
|
|
|
if (!writeBit(HIGH)) return false; |
|
|
|
|
int pos = -1; |
|
|
|
|
boolean good = true; |
|
|
|
|
do { |
|
|
|
|
pos++; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("sending character ")); Serial.println(message[pos]); |
|
|
|
|
#endif |
|
|
|
|
good = writeBit(message[pos] & 0x01) |
|
|
|
|
&& writeBit(message[pos] & 0x02) |
|
|
|
|
&& writeBit(message[pos] & 0x04) |
|
|
|
|
&& writeBit(message[pos] & 0x08) |
|
|
|
|
&& writeBit(message[pos] & 0x10) |
|
|
|
|
&& writeBit(message[pos] & 0x20) |
|
|
|
|
&& writeBit(message[pos] & 0x40) |
|
|
|
|
&& writeBit(message[pos] & 0x80); |
|
|
|
|
} while (good && message[pos]); |
|
|
|
|
if (good) writeBit(1); |
|
|
|
|
digitalWrite(_DE,LOW); // disable driver
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("disabled driver…")); |
|
|
|
|
#endif |
|
|
|
|
return good; |
|
|
|
|
_send_state = WAIT; |
|
|
|
|
enableSendTimer(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|