Lydia - Printhead
Modbus Object Management

Functions

boolean Modbus::getTimeOutState ()
 get communication watch-dog timer state More...
 
int8_t Modbus::poll ()
 cyclic poll for master More...
 
int8_t Modbus::poll (uint16_t *regs, uint8_t u8size)
 cyclic poll for slave More...
 
int8_t Modbus::query (modbus_t telegram)
 only for master More...
 

Detailed Description

Function Documentation

◆ getTimeOutState()

boolean Modbus::getTimeOutState ( )

get communication watch-dog timer state

Return communication Watchdog state. It could be useful to reset outputs if the watchdog is fired.

Returns
TRUE if millis() > u32timeOut

Definition at line 506 of file ModbusRtu.h.

507 {
508  return (millis() > u32timeOut);
509 }

◆ poll() [1/2]

int8_t Modbus::poll ( )

cyclic poll for master

*** Only for Modbus Master *** This method checks if there is any incoming answer if pending. If there is no answer, it would change Master state to COM_IDLE. This method must be called only at loop section. Avoid any delay() function.

Any incoming data would be redirected to au16regs pointer, as defined in its modbus_t query telegram.

@params nothing

Returns
errors counter

Definition at line 691 of file ModbusRtu.h.

692 {
693  // check if there is any incoming frame
694  uint8_t u8current;
695  if (u8serno < 4)
696  {
697  u8current = port->available();
698  }
699  else
700  {
701  u8current = softPort->available();
702  }
703 
704  if (millis() > u32timeOut)
705  {
706  u8state = COM_IDLE;
708  u16errCnt++;
709  return 0;
710  }
711 
712  if (u8current == 0)
713  {
714  return 0;
715  }
716 
717  // check T35 after frame end or still no frame end
718  if (u8current != u8lastRec)
719  {
720  u8lastRec = u8current;
721  u32time = millis() + T35;
722  return 0;
723  }
724  if (millis() < u32time)
725  {
726  return 0;
727  };
728 
729  // transfer Serial buffer frame to auBuffer
730  u8lastRec = 0;
731  int8_t i8state = getRxBuffer();
732  if (i8state < 7)
733  {
734  u8state = COM_IDLE;
735  u16errCnt++;
736  Log.verboseln("Add error : %d - RX-Buffer < 7", i8state);
738  return i8state;
739  }
740 
741  // validate message: id, CRC, FCT, exception
742  uint8_t u8exception = validateAnswer();
743  if (u8exception != 0)
744  {
745  Log.verboseln("ModbusRTU::poll : exception : %d", u8exception);
746  u8state = COM_IDLE;
747  return u8exception;
748  }
749 
750  // process answer
751  switch (au8Buffer[FUNC])
752  {
753  case MB_FC_READ_COILS:
754  case MB_FC_READ_DISCRETE_INPUT:
755  // call get_FC1 to transfer the incoming message to au16regs buffer
756  get_FC1();
757  break;
758  case MB_FC_READ_INPUT_REGISTER:
759  case MB_FC_READ_REGISTERS:
760  // call get_FC3 to transfer the incoming message to au16regs buffer
761  get_FC3();
762  break;
763  case MB_FC_WRITE_COIL:
764  case MB_FC_WRITE_REGISTER:
765  case MB_FC_WRITE_MULTIPLE_COILS:
766  case MB_FC_WRITE_MULTIPLE_REGISTERS:
767  // nothing to do
768  break;
769  default:
770  break;
771  }
772  u8state = COM_IDLE;
774  return u8BufferSize;
775 }

◆ poll() [2/2]

int8_t Modbus::poll ( uint16_t *  regs,
uint8_t  u8size 
)

cyclic poll for slave

*** Only for Modbus Slave *** This method checks if there is any incoming query Afterwards, it would shoot a validation routine plus a register query Avoid any delay() function !!!! After a successful frame between the Master and the Slave, the time-out timer is reset.

Parameters
*regsregister table for communication exchange
u8sizesize of the register table
Returns
0 if no query, 1..4 if communication error, >4 if correct query processed

Definition at line 790 of file ModbusRtu.h.

791 {
792 
793  au16regs = regs;
794  u8regsize = u8size;
795  uint8_t u8current;
796 
797  // check if there is any incoming frame
798  if (u8serno < 4)
799  u8current = port->available();
800  else
801  u8current = softPort->available();
802 
803  if (u8current == 0)
804  return 0;
805 
806  // check T35 after frame end or still no frame end
807  if (u8current != u8lastRec)
808  {
809  u8lastRec = u8current;
810  u32time = millis() + T35;
811  return 0;
812  }
813  if (millis() < u32time)
814  return 0;
815 
816  u8lastRec = 0;
817  int8_t i8state = getRxBuffer();
818  u8lastError = i8state;
819  if (i8state < 7)
820  return i8state;
821 
822  // check slave id
823  if (au8Buffer[ID] != u8id)
824  {
825  return 0;
826  }
827 
828  // validate message: CRC, FCT, address and size
829  uint8_t u8exception = validateRequest();
830  if (u8exception > 0)
831  {
832  Serial.println("exception : 1");
833  if (u8exception != NO_REPLY)
834  {
835  buildException(u8exception);
836  sendTxBuffer();
837  }
838  u8lastError = u8exception;
839  return u8exception;
840  }
841 
842  u32timeOut = millis() + long(u16timeOut);
843  u8lastError = 0;
844 
845  Log.verboseln("mb : process message : %d", FUNC);
846 
847  // process message
848  switch (au8Buffer[FUNC])
849  {
850  case MB_FC_READ_COILS:
851  case MB_FC_READ_DISCRETE_INPUT:
852  return process_FC1(regs, u8size);
853  break;
854  case MB_FC_READ_INPUT_REGISTER:
855  case MB_FC_READ_REGISTERS:
856  return process_FC3(regs, u8size);
857  break;
858  case MB_FC_WRITE_COIL:
859  return process_FC5(regs, u8size);
860  break;
861  case MB_FC_WRITE_REGISTER:
862  return process_FC6(regs, u8size);
863  break;
864  case MB_FC_WRITE_MULTIPLE_COILS:
865  return process_FC15(regs, u8size);
866  break;
867  case MB_FC_WRITE_MULTIPLE_REGISTERS:
868  return process_FC16(regs, u8size);
869  break;
870  default:
871  break;
872  }
874  return i8state;
875 }

◆ query()

int8_t Modbus::query ( modbus_t  telegram)

only for master

*** Only Modbus Master *** Generate a query to an slave with a modbus_t telegram structure The Master must be in COM_IDLE mode. After it, its state would be COM_WAITING. This method has to be called only in loop() section.

See also
modbus_t
Parameters
modbus_tmodbus telegram structure (id, fct, ...)
Todo:
finish function 15

Definition at line 592 of file ModbusRtu.h.

593 {
594 
595  uint8_t u8regsno, u8bytesno;
596  if (u8id != 0)
597  return -2;
598  if (u8state != COM_IDLE)
599  return -1;
600 
601  if ((telegram.u8id == 0) || (telegram.u8id > 247))
602  return -3;
603 
604  au16regs = telegram.au16reg;
605  telegram.flags = QUEUED;
606  currentQuery = &telegram;
607 
608  // telegram header
609  au8Buffer[ID] = telegram.u8id;
610  au8Buffer[FUNC] = telegram.u8fct;
611  au8Buffer[ADD_HI] = highByte(telegram.u16RegAdd);
612  au8Buffer[ADD_LO] = lowByte(telegram.u16RegAdd);
613 
614  switch (telegram.u8fct)
615  {
616  case MB_FC_READ_COILS:
617  case MB_FC_READ_DISCRETE_INPUT:
618  case MB_FC_READ_REGISTERS:
619  case MB_FC_READ_INPUT_REGISTER:
620  au8Buffer[NB_HI] = highByte(telegram.u16CoilsNo);
621  au8Buffer[NB_LO] = lowByte(telegram.u16CoilsNo);
622  u8BufferSize = 6;
623  break;
624  case MB_FC_WRITE_COIL:
625  au8Buffer[NB_HI] = ((telegram.u16CoilsNo > 0) ? 0xff : 0);
626  au8Buffer[NB_LO] = 0;
627  u8BufferSize = 6;
628  break;
629  case MB_FC_WRITE_REGISTER:
630  au8Buffer[NB_HI] = highByte(telegram.u16CoilsNo);
631  au8Buffer[NB_LO] = lowByte(telegram.u16CoilsNo);
632  u8BufferSize = 6;
633  break;
634  case MB_FC_WRITE_MULTIPLE_COILS: // TODO: implement "sending coils"
635  u8regsno = telegram.u16CoilsNo / 16;
636  u8bytesno = u8regsno * 2;
637  if ((telegram.u16CoilsNo % 16) != 0)
638  {
639  u8bytesno++;
640  u8regsno++;
641  }
642 
643  au8Buffer[NB_HI] = highByte(telegram.u16CoilsNo);
644  au8Buffer[NB_LO] = lowByte(telegram.u16CoilsNo);
645  au8Buffer[NB_LO + 1] = u8bytesno;
646  u8BufferSize = 7;
647 
648  u8regsno = u8bytesno = 0;
649  break;
650 
652  {
653 
654  break;
655  }
656  case MB_FC_WRITE_MULTIPLE_REGISTERS:
657  au8Buffer[NB_HI] = highByte(telegram.u16CoilsNo);
658  au8Buffer[NB_LO] = lowByte(telegram.u16CoilsNo);
659  au8Buffer[NB_LO + 1] = (uint8_t)(telegram.u16CoilsNo * 2);
660  u8BufferSize = 7;
661 
662  for (uint16_t i = 0; i < telegram.u16CoilsNo; i++)
663  {
664  au8Buffer[u8BufferSize] = highByte(au16regs[i]);
665  u8BufferSize++;
666  au8Buffer[u8BufferSize] = lowByte(au16regs[i]);
667  u8BufferSize++;
668  }
669  break;
670  }
671 
672  sendTxBuffer();
674  return 0;
675 }
Modbus::u32time
uint32_t u32time
Definition: ModbusRtu.h:168
Modbus::validateAnswer
uint8_t validateAnswer()
This method validates master incoming messages.
Definition: ModbusRtu.h:1201
Modbus::u32timeOut
uint32_t u32timeOut
Definition: ModbusRtu.h:168
Modbus::get_FC1
void get_FC1()
Definition: ModbusRtu.h:1261
COM_IDLE
@ COM_IDLE
Definition: ModbusRtu.h:113
Modbus::u8BufferSize
uint8_t u8BufferSize
Definition: ModbusRtu.h:163
modbus_t::flags
uint8_t flags
Definition: ModbusRtu.h:74
modbus_t::au16reg
uint16_t * au16reg
Definition: ModbusRtu.h:73
Modbus::u8state
uint8_t u8state
Definition: ModbusRtu.h:160
Modbus::buildException
void buildException(uint8_t u8exception)
This method builds an exception message.
Definition: ModbusRtu.h:1244
Modbus::get_FC3
void get_FC3()
Definition: ModbusRtu.h:1280
Modbus::u8lastRec
uint8_t u8lastRec
Definition: ModbusRtu.h:164
Modbus::currentQuery
modbus_t * currentQuery
Definition: ModbusRtu.h:178
NB_HI
@ NB_HI
Number of coils or registers high byte.
Definition: ModbusRtu.h:97
Modbus::u8regsize
uint8_t u8regsize
Definition: ModbusRtu.h:169
Modbus::process_FC15
int8_t process_FC15(uint16_t *regs, uint8_t u8size)
This method processes function 15 This method writes a bit array assigned by the master.
Definition: ModbusRtu.h:1447
Modbus::au16regs
uint16_t * au16regs
Definition: ModbusRtu.h:165
Modbus::u16errCnt
uint16_t u16errCnt
Definition: ModbusRtu.h:166
Modbus::process_FC5
int8_t process_FC5(uint16_t *regs, uint8_t u8size)
This method processes function 5 This method writes a value assigned by the master to a single bit.
Definition: ModbusRtu.h:1389
Modbus::validateRequest
uint8_t validateRequest()
This method validates slave incoming messages.
Definition: ModbusRtu.h:1128
Modbus::u8serno
uint8_t u8serno
serial port: 0-Serial, 1..3-Serial1..Serial3; 4: use software serial
Definition: ModbusRtu.h:158
COM_WAITING
@ COM_WAITING
Definition: ModbusRtu.h:114
printHex
void printHex(uint8_t *data, uint8_t length)
Definition: utils.cpp:3
ku8MBLinkTestOmronMX2Only
#define ku8MBLinkTestOmronMX2Only
Modbus function 0x08 Test.
Definition: enums.h:109
Modbus::rxBuffer
uint8_t rxBuffer[MAX_BUFFER]
Definition: ModbusRtu.h:217
modbus_t::u16CoilsNo
uint16_t u16CoilsNo
Definition: ModbusRtu.h:72
Modbus::sendTxBuffer
void sendTxBuffer()
This method transmits au8Buffer to Serial line. Only if u8txenpin != 0, there is a flow handling in o...
Definition: ModbusRtu.h:962
Modbus::process_FC6
int8_t process_FC6(uint16_t *regs, uint8_t u8size)
This method processes function 6 This method writes a value assigned by the master to a single word.
Definition: ModbusRtu.h:1421
modbus_t::u8id
uint8_t u8id
Definition: ModbusRtu.h:69
modbus_t::u8fct
uint8_t u8fct
Definition: ModbusRtu.h:70
Modbus::u16timeOut
uint16_t u16timeOut
Definition: ModbusRtu.h:167
QUEUED
@ QUEUED
Definition: enums.h:90
Modbus::au8Buffer
uint8_t au8Buffer[MAX_BUFFER]
Definition: ModbusRtu.h:162
modbus_t::u16RegAdd
uint16_t u16RegAdd
Definition: ModbusRtu.h:71
FUNC
@ FUNC
Function code position.
Definition: ModbusRtu.h:94
Modbus::process_FC1
int8_t process_FC1(uint16_t *regs, uint8_t u8size)
This method processes functions 1 & 2 This method reads a bit array and transfers it to the master.
Definition: ModbusRtu.h:1302
NO_REPLY
@ NO_REPLY
Definition: ModbusRtu.h:128
ADD_HI
@ ADD_HI
Address high byte.
Definition: ModbusRtu.h:95
Modbus::u8lastError
uint8_t u8lastError
Definition: ModbusRtu.h:161
Modbus::process_FC16
int8_t process_FC16(uint16_t *regs, uint8_t u8size)
This method processes function 16 This method writes a word array assigned by the master.
Definition: ModbusRtu.h:1502
RESPONDED
@ RESPONDED
Definition: enums.h:93
Modbus::process_FC3
int8_t process_FC3(uint16_t *regs, uint8_t u8size)
This method processes functions 3 & 4 This method reads a word array and transfers it to the master.
Definition: ModbusRtu.h:1357
Modbus::softPort
SoftwareSerial * softPort
Pointer to SoftwareSerial class object.
Definition: ModbusRtu.h:156
Modbus::port
HardwareSerial * port
Pointer to Serial class object.
Definition: ModbusRtu.h:155
ID
@ ID
ID field.
Definition: ModbusRtu.h:93
Modbus::u8id
uint8_t u8id
0=master, 1..247=slave number
Definition: ModbusRtu.h:157
T35
#define T35
Definition: ModbusRtu.h:56
Modbus::getRxBuffer
int8_t getRxBuffer()
This method moves Serial buffer data to the Modbus au8Buffer.
Definition: ModbusRtu.h:905
ADD_LO
@ ADD_LO
Address low byte.
Definition: ModbusRtu.h:96
NB_LO
@ NB_LO
Number of coils or registers low byte.
Definition: ModbusRtu.h:98