1+ /*
2+ Modbus T1S Client Temperature Humidity sensor
3+
4+ This sketch creates a Modbus T1S Client and demonstrates
5+ how to use the ModbusT1S API to communicate.
6+ - Arduino Uno Wifi R4
7+ - T1S shield
8+ - SPE ethernet connected to the client
9+ - all the terminations placed on the hardware
10+ */
11+
12+ #include < ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
13+ #include < ArduinoModbus.h>
14+ #include " arduino_secrets.h"
15+
16+ /* *************************************************************************************
17+ CONSTANTS
18+ **************************************************************************************/
19+ #define RS485_SERIAL Serial1
20+ #define RS485_TX_PIN 1
21+ #define RS485_RX_PIN 0
22+ #define RS485_DE_PIN 8
23+ #define RS485_RE_PIN 7
24+ #define PRE_DELAY 100
25+ #define POST_DELAY 100
26+ #define PWR_CARRIER_RATIO 0 .18f
27+ RS485Class serial485 (RS485_SERIAL, RS485_TX_PIN, RS485_DE_PIN, RS485_RE_PIN);
28+
29+ static unsigned int const MODBUS_BAUDRATE = 9600 ;
30+ static float const MODBUS_BIT_DURATION = 1 .f / MODBUS_BAUDRATE;
31+ static float const MODBUS_PRE_DELAY_BR = MODBUS_BIT_DURATION * 9 .6f * 3 .5f * 1e6 ;
32+ static float const MODBUS_POST_DELAY_BR = MODBUS_BIT_DURATION * 9 .6f * 3 .5f * 1e6 ;
33+
34+ static int const MODBUS_DEVICE_ID = 1 ;
35+ static int const MODBUS_DEVICE_TEMPERATURE_REGISTER = 0x0001 ;
36+ static int const MODBUS_DEVICE_HUMIDITY_REGISTER = 0x0002 ;
37+
38+ static uint8_t const T1S_PLCA_NODE_ID = 0 ; /* The UDP server doubles as PLCA coordinator. */
39+
40+ static IPAddress const ip_addr {
41+ 192 , 168 , 42 , 100 + T1S_PLCA_NODE_ID
42+ };
43+ static IPAddress const network_mask {
44+ 255 , 255 , 255 , 0
45+ };
46+ static IPAddress const gateway {
47+ 192 , 168 , 42 , 100
48+ };
49+
50+ static T1SPlcaSettings const t1s_plca_settings {
51+ T1S_PLCA_NODE_ID
52+ };
53+ static T1SMacSettings const t1s_default_mac_settings;
54+
55+ /* *************************************************************************************
56+ GLOBAL VARIABLES
57+ **************************************************************************************/
58+ auto const tc6_io = new TC6::TC6_Io
59+ ( SPI
60+ , CS_PIN
61+ , RESET_PIN
62+ , IRQ_PIN);
63+ auto const tc6_inst = new TC6::TC6_Arduino_10BASE_T1S(tc6_io);
64+ Arduino_10BASE_T1S_UDP udp_server;
65+
66+ /* *************************************************************************************
67+ SETUP/LOOP
68+ **************************************************************************************/
69+ void setup () {
70+ Serial.begin (115200 );
71+
72+ Serial.println (" Modbus RTU Server LED" );
73+
74+ /* Initialize digital IO interface for interfacing
75+ with the LAN8651.
76+ */
77+ pinMode (IRQ_PIN, INPUT_PULLUP);
78+ attachInterrupt (digitalPinToInterrupt (IRQ_PIN),
79+ []() {
80+ tc6_io->onInterrupt ();
81+ },
82+ FALLING);
83+
84+ /* Initialize IO module. */
85+ if (!tc6_io->begin ())
86+ {
87+ Serial.println (" 'TC6_Io::begin(...)' failed." );
88+ for (;;) { }
89+ }
90+
91+ MacAddress const mac_addr = MacAddress::create_from_uid ();
92+
93+ if (!tc6_inst->begin (ip_addr
94+ , network_mask
95+ , gateway
96+ , mac_addr
97+ , t1s_plca_settings
98+ , t1s_default_mac_settings))
99+ {
100+ Serial.println (" 'TC6::begin(...)' failed." );
101+ for (;;) { }
102+ }
103+
104+ Serial.print (" IP\t " );
105+ Serial.println (ip_addr);
106+ Serial.println (mac_addr);
107+ Serial.println (t1s_plca_settings);
108+ Serial.println (t1s_default_mac_settings);
109+
110+ if (!udp_server.begin (UDP_SERVER_PORT))
111+ {
112+ Serial.println (" begin(...) failed for UDP coil read server " );
113+ for (;;) { }
114+ }
115+
116+ tc6_inst->digitalWrite (TC6::DIO::A0, false );
117+ /* A1 -> T1S_DISABLE -> close the switch connecting network to board. */
118+ tc6_inst->digitalWrite (TC6::DIO::A1, true );
119+
120+ serial485.setDelays (MODBUS_PRE_DELAY_BR, MODBUS_POST_DELAY_BR);
121+ unsigned long br = MODBUS_BAUDRATE;
122+ uint16_t config = SERIAL_8N1;
123+ if (!ModbusT1SServer.begin (serial485, br, config)) {
124+ Serial.println (" Failed to start Modbus RTU Client!" );
125+ while (1 );
126+ }
127+
128+ ModbusT1SServer.setT1SServer (&udp_server);
129+ Serial.println (" UDP_Server" );
130+ Serial.println (MODBUS_PRE_DELAY_BR);
131+ Serial.println (MODBUS_POST_DELAY_BR);
132+ }
133+
134+ void loop () {
135+ /* Services the hardware and the protocol stack.
136+ Must be called cyclic. The faster the better.
137+ */
138+ tc6_inst->service ();
139+
140+ static unsigned long prev_beacon_check = 0 ;
141+
142+ auto const now = millis ();
143+ if ((now - prev_beacon_check) > 1000 )
144+ {
145+ prev_beacon_check = now;
146+ if (!tc6_inst->getPlcaStatus (OnPlcaStatus)) {
147+ Serial.println (" getPlcaStatus(...) failed" );
148+ }
149+ }
150+
151+ switch (ModbusT1SServer.parsePacket ())
152+ {
153+ case UDP_READ_COIL_PORT:
154+ Serial.println (" Read coil" );
155+ ModbusT1SServer.coilRead ();
156+ break ;
157+
158+ case UDP_WRITE_COIL_PORT:
159+ Serial.println (" Write coil" );
160+ ModbusT1SServer.coilWrite ();
161+ break ;
162+
163+ case UDP_READ_DI_PORT:
164+ Serial.println (" Read discrete input" );
165+ ModbusT1SServer.discreteInputRead ();
166+ break ;
167+
168+ case UDP_READ_IR_PORT:
169+ Serial.println (" Read input register" );
170+ ModbusT1SServer.inputRegisterRead ();
171+ break ;
172+
173+ case UDP_READ_HR_PORT:
174+ Serial.println (" Read holding register" );
175+ ModbusT1SServer.holdingRegisterRead ();
176+ break ;
177+
178+ case UDP_WRITE_HR_PORT:
179+ Serial.println (" Write holding register" );
180+ ModbusT1SServer.holdingRegisterWrite ();
181+ break ;
182+
183+ default :
184+ break ;
185+ }
186+ }
187+
188+ static void OnPlcaStatus (bool success, bool plcaStatus)
189+ {
190+ if (!success)
191+ {
192+ Serial.println (" PLCA status register read failed" );
193+ return ;
194+ }
195+
196+ if (plcaStatus) {
197+ Serial.println (" PLCA Mode active" );
198+ } else {
199+ Serial.println (" CSMA/CD fallback" );
200+ tc6_inst->enablePlca ();
201+ }
202+ }
0 commit comments