Skip to content

Commit ce3489b

Browse files
authored
Merge pull request #17 from gabrielsan/master
minor fixes when using softserial
2 parents 2297787 + e9d0f9f commit ce3489b

File tree

1 file changed

+42
-67
lines changed

1 file changed

+42
-67
lines changed

ModbusRtu.h

Lines changed: 42 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* @author Samuel Marco i Armengol
66
* @contact [email protected]
77
* @contribution Helium6072
8+
* @contribution gabrielsan
89
*
910
* @description
1011
* Arduino library for communicating with Modbus devices
@@ -167,7 +168,7 @@ class Modbus
167168
uint16_t *au16regs;
168169
uint16_t u16InCnt, u16OutCnt, u16errCnt;
169170
uint16_t u16timeOut;
170-
uint32_t u32time, u32timeOut;
171+
uint32_t u32time, u32timeOut, u32overTime;
171172
uint8_t u8regsize;
172173

173174
void init(uint8_t u8id, uint8_t u8serno, uint8_t u8txenpin);
@@ -194,9 +195,9 @@ class Modbus
194195
Modbus(uint8_t u8id);
195196
void begin(long u32speed);
196197
void begin(SoftwareSerial *sPort, long u32speed);
197-
void begin(long u32speed, uint8_t u8config);
198+
//void begin(long u32speed, uint8_t u8config);
198199
void begin();
199-
void setTimeOut( uint16_t u16timeout); //!<write communication watch-dog timer
200+
void setTimeOut( uint16_t u16timeOut); //!<write communication watch-dog timer
200201
uint16_t getTimeOut(); //!<get communication watch-dog timer value
201202
boolean getTimeOutState(); //!<get communication watch-dog timer state
202203
int8_t query( modbus_t telegram ); //!<only for master
@@ -209,6 +210,7 @@ class Modbus
209210
uint8_t getState();
210211
uint8_t getLastError(); //!<get last error message
211212
void setID( uint8_t u8id ); //!<write new ID for the slave
213+
void setTxendPinOverTime( uint32_t u32overTime );
212214
void end(); //!<finish any communication and release serial communication port
213215
};
214216

@@ -372,7 +374,7 @@ void Modbus::begin(SoftwareSerial *sPort, long u32speed)
372374
* @param config data frame settings (data length, parity and stop bits)
373375
* @ingroup setup
374376
*/
375-
void Modbus::begin(long u32speed,uint8_t u8config)
377+
/* void Modbus::begin(long u32speed,uint8_t u8config)
376378
{
377379
378380
switch( u8serno )
@@ -411,7 +413,7 @@ void Modbus::begin(long u32speed,uint8_t u8config)
411413
while(port->read() >= 0);
412414
u8lastRec = u8BufferSize = 0;
413415
u16InCnt = u16OutCnt = u16errCnt = 0;
414-
}
416+
} */
415417

416418
/**
417419
* @brief
@@ -443,6 +445,21 @@ void Modbus::setID( uint8_t u8id)
443445
}
444446
}
445447

448+
/**
449+
* @brief
450+
* Method to write the overtime count for txend pin.
451+
* It waits until count reaches 0 after the transfer is done.
452+
* With this, you can extend the time between txempty and
453+
* the falling edge if needed.
454+
*
455+
* @param uint32_t overtime count for txend pin
456+
* @ingroup setup
457+
*/
458+
void Modbus::setTxendPinOverTime( uint32_t u32overTime )
459+
{
460+
this->u32overTime = u32overTime;
461+
}
462+
446463
/**
447464
* @brief
448465
* Method to read current slave ID address
@@ -481,7 +498,7 @@ void Modbus::setTimeOut( uint16_t u16timeOut)
481498
*/
482499
boolean Modbus::getTimeOutState()
483500
{
484-
return (millis() > u32timeOut);
501+
return ((unsigned long)(millis() -u32timeOut) > (unsigned long)u16timeOut);
485502
}
486503

487504
/**
@@ -668,7 +685,7 @@ int8_t Modbus::poll()
668685
else
669686
u8current = softPort->available();
670687

671-
if (millis() > u32timeOut)
688+
if ((unsigned long)(millis() -u32timeOut) > (unsigned long)u16timeOut)
672689
{
673690
u8state = COM_IDLE;
674691
u8lastError = NO_REPLY;
@@ -682,10 +699,10 @@ int8_t Modbus::poll()
682699
if (u8current != u8lastRec)
683700
{
684701
u8lastRec = u8current;
685-
u32time = millis() + T35;
702+
u32time = millis();
686703
return 0;
687704
}
688-
if (millis() < u32time) return 0;
705+
if ((unsigned long)(millis() -u32time) < (unsigned long)T35) return 0;
689706

690707
// transfer Serial buffer frame to auBuffer
691708
u8lastRec = 0;
@@ -764,10 +781,10 @@ int8_t Modbus::poll( uint16_t *regs, uint8_t u8size )
764781
if (u8current != u8lastRec)
765782
{
766783
u8lastRec = u8current;
767-
u32time = millis() + T35;
784+
u32time = millis();
768785
return 0;
769786
}
770-
if (millis() < u32time) return 0;
787+
if ((unsigned long)(millis() -u32time) < (unsigned long)T35) return 0;
771788

772789
u8lastRec = 0;
773790
int8_t i8state = getRxBuffer();
@@ -790,7 +807,7 @@ int8_t Modbus::poll( uint16_t *regs, uint8_t u8size )
790807
return u8exception;
791808
}
792809

793-
u32timeOut = millis() + long(u16timeOut);
810+
u32timeOut = millis();
794811
u8lastError = 0;
795812

796813
// process message
@@ -827,9 +844,10 @@ int8_t Modbus::poll( uint16_t *regs, uint8_t u8size )
827844
void Modbus::init(uint8_t u8id, uint8_t u8serno, uint8_t u8txenpin)
828845
{
829846
this->u8id = u8id;
830-
this->u8serno = (u8serno > 3) ? 0 : u8serno;
847+
this->u8serno = u8serno;
831848
this->u8txenpin = u8txenpin;
832849
this->u16timeOut = 1000;
850+
this->u32overTime = 0;
833851
}
834852

835853
void Modbus::init(uint8_t u8id)
@@ -838,6 +856,7 @@ void Modbus::init(uint8_t u8id)
838856
this->u8serno = 4;
839857
this->u8txenpin = 0;
840858
this->u16timeOut = 1000;
859+
this->u32overTime = 0;
841860
}
842861

843862
/**
@@ -902,72 +921,28 @@ void Modbus::sendTxBuffer()
902921
u8BufferSize++;
903922
au8Buffer[ u8BufferSize ] = u16crc & 0x00ff;
904923
u8BufferSize++;
905-
906-
// set RS485 transceiver to transmit mode
924+
907925
if (u8txenpin > 1)
908926
{
909-
switch( u8serno )
910-
{
911-
#if defined(UBRR1H)
912-
case 1:
913-
UCSR1A=UCSR1A |(1 << TXC1);
914-
break;
915-
#endif
916-
917-
#if defined(UBRR2H)
918-
case 2:
919-
UCSR2A=UCSR2A |(1 << TXC2);
920-
break;
921-
#endif
922-
923-
#if defined(UBRR3H)
924-
case 3:
925-
UCSR3A=UCSR3A |(1 << TXC3);
926-
break;
927-
#endif
928-
case 0:
929-
default:
930-
UCSR0A=UCSR0A |(1 << TXC0);
931-
break;
932-
}
927+
// set RS485 transceiver to transmit mode
933928
digitalWrite( u8txenpin, HIGH );
934929
}
935930

936931
// transfer buffer to serial line
937-
if(u8serno<4)
932+
if (u8serno < 4)
938933
port->write( au8Buffer, u8BufferSize );
939934
else
940935
softPort->write( au8Buffer, u8BufferSize );
941936

942-
// keep RS485 transceiver in transmit mode as long as sending
943937
if (u8txenpin > 1)
944938
{
945-
switch( u8serno )
946-
{
947-
#if defined(UBRR1H)
948-
case 1:
949-
while (!(UCSR1A & (1 << TXC1)));
950-
break;
951-
#endif
952-
953-
#if defined(UBRR2H)
954-
case 2:
955-
while (!(UCSR2A & (1 << TXC2)));
956-
break;
957-
#endif
958-
959-
#if defined(UBRR3H)
960-
case 3:
961-
while (!(UCSR3A & (1 << TXC3)));
962-
break;
963-
#endif
964-
case 0:
965-
default:
966-
while (!(UCSR0A & (1 << TXC0)));
967-
break;
968-
}
969-
939+
// must wait transmission end before changing pin state
940+
// soft serial does not need it since it is blocking
941+
if (u8serno < 4)
942+
port->flush();
970943
// return RS485 transceiver to receive mode
944+
volatile uint32_t u32overTimeCountDown = u32overTime;
945+
while ( u32overTimeCountDown-- > 0);
971946
digitalWrite( u8txenpin, LOW );
972947
}
973948
if(u8serno<4)
@@ -978,7 +953,7 @@ void Modbus::sendTxBuffer()
978953
u8BufferSize = 0;
979954

980955
// set time-out for master
981-
u32timeOut = millis() + (unsigned long) u16timeOut;
956+
u32timeOut = millis();
982957

983958
// increase message counter
984959
u16OutCnt++;

0 commit comments

Comments
 (0)