Attachment 'MODBUS.v1.0.txt'
Download 1 :Namespace MODBUS
2 ⍝ Driver for serial Modbus communication in RTU Mode
3 ⍝
4 ⍝ The following command are supported
5 ⍝ FORCE_COIL_ON = Force ON a Single Coil
6 ⍝ FORCE_COIL_OFF = Force OFF a Single Coil
7 ⍝ READ_REG_FLOAT = Read One FLOAT Register
8 ⍝ READ_BYTE = Read Multiple Registers as Bytes
9 ⍝ PRESET_REG_FLOAT = Write a Float Value to a Register
10 ⍝ PRESET_REG_INT = Write an Integer Value to a Register
11 ⍝
12 ⍝ See the comments of the individual methods for more information
13
14
15 (⎕IO ⎕ML ⎕WX)←1 3 3 ⍝ System variables
16
17 I2H2←{'0123456789ABCDEF'[⎕IO+16 16⊤⍵]} ⍝ Convert one Integer (0-255) to 2 Bytes Hexadecimal
18 I2H4←{,⍉'0123456789ABCDEF'[⎕IO+16 16⊤255 255⊤⍵]} ⍝ Convert one Integer (0-65535) to 4 Bytes Hexadecimal
19 H22B←{16⊥¨16|(-⎕IO)+(⊂'0123456789ABCDEF0123456789abcdef')⍳¨((⍴⍵)⍴2 1)⊂⍵} ⍝ Convert a pair of HEX characters to Bytes (0-255)
20
21
22 ∇ r←sendObj FORCE_COIL_ON(modbusAddr coilNumber)
23 :Access Public
24 ⍝ To Force ON a Single Coil
25 ⍝
26 ⍝ sendObj = SerialPort or TCP object
27 ⍝ modbusAddr = Address of MODBUS device
28 ⍝ coilNumber = Coil Number
29 ⍝
30 ⍝ r[1] = 1 for Success, 0 for Failure
31 ⍝ r[2] = Value if Success or Literal Error if failure
32
33 r←I2H2 modbusAddr ⍝ Address of MODBUS device
34 r,←'05' ⍝ Force Single Coil Command (5 decimal)
35 r,←I2H4 coilNumber-1 ⍝ Coil Number (coil #1 is 0 in the program)
36 r,←'FF00' ⍝ Coil ON hex command
37 r,←CRC_H r ⍝ Checksum Calculation
38 r←H22B r ⍝ To Bytes
39 r←sendObj.SendReceive r ⍝ Communication
40
41 ⍝ To Exit on Communication Error
42 :If 0=1⊃r ⋄ r←0(2⊃r) ⋄ →0 ⋄ :Else ⋄ r←2⊃r ⋄ :End
43
44 ⍝ To Check if Byte Count is Correct
45 :If 7=⍴,r ⋄ r←0 'Byte Count Incorrect Error' ⋄ →0 ⋄ :End
46
47 ⍝ To Check if the CRC of the Answer is Correct
48 :If ~(CRC_D ¯2↓r)≡¯2↑r
49 r←0 'CRC Error on Answer' ⋄ →0
50 :End
51
52 ⍝ To Check if the Meter Address is Present
53 :If modbusAddr≠r[1] ⋄ r←0 'Modbus Address Not Present Error' ⋄ →0 ⋄ :End
54
55 ⍝ To Check if Command Number is Present
56 :If 131=r[2] ⋄ r←0 'Command Number Error' ⋄ →0 ⋄ :End
57 :If 5≠r[2] ⋄ r←0 'Command Number Not Present' ⋄ →0 ⋄ :End
58
59 ⍝ To Check if Coil ON is in the answer
60 :If 255 0≢r[5 6] ⋄ r←0 'Error in answer' ⋄ →0 ⋄ :End
61
62 ⍝ Success
63 r←1
64 ∇
65
66
67 ∇ r←sendObj FORCE_COIL_OFF(modbusAddr coilNumber)
68 :Access Public
69 ⍝ To Force OFF a Single Coil
70 ⍝
71 ⍝ sendObj = SerialPort or TCP object
72 ⍝ modbusAddr = Address of MODBUS device
73 ⍝ coilNumber = Coil Number
74 ⍝
75 ⍝ r[1] = 1 for Success, 0 for Failure
76 ⍝ r[2] = Value if Success or Literal Error if failure
77
78 r←I2H2 modbusAddr ⍝ Address of MODBUS device
79 r,←'05' ⍝ Force Single Coil Command (5 decimal)
80 r,←I2H4 coilNumber-1 ⍝ Coil Number (coil #1 is 0 in the program)
81 r,←'0000' ⍝ Coil OFF hex command
82 r,←CRC_H r ⍝ Checksum Calculation
83 r←H22B r ⍝ To Bytes
84 r←sendObj.SendReceive r ⍝ Communication
85
86 ⍝ To Exit on Communication Error
87 :If 0=1⊃r ⋄ r←0(2⊃r) ⋄ →0 ⋄ :Else ⋄ r←2⊃r ⋄ :End
88
89 ⍝ To Check if Byte Count is Correct
90 :If 7=⍴,r ⋄ r←0 'Byte Count Incorrect Error' ⋄ →0 ⋄ :End
91
92 ⍝ To Check if the CRC of the Answer is Correct
93 :If ~(CRC_D ¯2↓r)≡¯2↑r
94 r←0 'CRC Error on Answer' ⋄ →0
95 :End
96
97 ⍝ To Check if the Meter Address is Present
98 :If modbusAddr≠r[1] ⋄ r←0 'Modbus Address Not Present Error' ⋄ →0 ⋄ :End
99
100 ⍝ To Check if Command Number is Present
101 :If 131=r[2] ⋄ r←0 'Command Number Error' ⋄ →0 ⋄ :End
102 :If 5≠r[2] ⋄ r←0 'Command Number Not Present' ⋄ →0 ⋄ :End
103
104 ⍝ To Check if Coil OFF is in the answer
105 :If 0 0≢r[5 6] ⋄ r←0 'Error in answer' ⋄ →0 ⋄ :End
106
107 ⍝ Success
108 r←1
109 ∇
110
111
112 ∇ r←sendObj READ_BYTE(modbusAddr regAddr regQty)
113 :Access Public
114 ⍝ Read Register(s) as Bytes
115 ⍝
116 ⍝ sendObj = SerialPort or TCP object
117 ⍝ modbusAddr = Address of MODBUS device
118 ⍝ regAddr = Starting register
119 ⍝ regQty = Number of registers to read (2 bytes per registers)
120 ⍝
121 ⍝ r[1] = 1 for Success, 0 for Failure
122 ⍝ r[2] = Bytes in register(s) if Success or Literal Error if failure
123
124 r←I2H2 modbusAddr ⍝ Address of MODBUS device
125 r,←'03' ⍝ Read Holding Register Command (3 decimal)
126 r,←I2H4 regAddr-40001 ⍝ Starting Address (address 0 is 40001)
127 r,←I2H4 regQty ⍝ Number of Registers To Read
128 r,←CRC_H r ⍝ Checksum Calculation
129 r←H22B r ⍝ Hex To Bytes
130 r←sendObj.SendReceive r ⍝ Communication
131
132 ⍝ To Exit on Communication Error
133 :If 0=1⊃r ⋄ r←0(2⊃r) ⋄ →0 ⋄ :Else ⋄ r←2⊃r ⋄ :End
134
135 ⍝ To Check if Byte Count is Correct
136 :If 3>⍴,r
137 :OrIf r[3]≠¯5+⍴,r
138 r←0 'Byte Count Incorrect Error' ⋄ →0
139 :End
140
141 ⍝ To Check if the CRC of the Answer is Correct
142 :If ~(CRC_D ¯2↓r)≡¯2↑r
143 r←0 'CRC Error on Answer' ⋄ →0
144 :End
145
146 ⍝ To Check if the Modbus Address is Present
147 :If modbusAddr≠r[1] ⋄ r←0 'Modbus Address Not Present Error' ⋄ →0 ⋄ :End
148
149 ⍝ To Check if Command Number is Present
150 :If 131=r[2] ⋄ r←0 'Command Number Error' ⋄ →0 ⋄ :End
151 :If 3≠r[2] ⋄ r←0 'Command Number Not Present' ⋄ →0 ⋄ :End
152
153 ⍝ Success
154 r←1(3↓¯2↓r)
155 ∇
156
157
158 ∇ r←sendObj READ_REG_FLOAT(modbusAddr regAddr)
159 :Access Public
160 ⍝ Read One FLOAT Register of a MODBUS device
161 ⍝
162 ⍝ sendObj = SerialPort or TCP object
163 ⍝ modbusAddr = Address of MODBUS device
164 ⍝ regAddr = Address of Register
165 ⍝
166 ⍝ r[1] = 1 for Success, 0 for Failure
167 ⍝ r[2] = Value if Success or Literal Error if failure
168
169 r←I2H2 modbusAddr ⍝ Address of MODBUS device
170 r,←'03' ⍝ Read Holding Register Command (3 decimal)
171 r,←I2H4 regAddr-40001 ⍝ Starting Address
172 r,←'0002' ⍝ 2 Registers To Read
173 r,←CRC_H r ⍝ Checksum Calculation
174 r←H22B r ⍝ To Bytes
175 r←sendObj.SendReceive r ⍝ Communication
176
177 ⍝ To Exit on Communication Error
178 :If 0=1⊃r ⋄ →0 ⋄ :Else ⋄ r←2⊃r ⋄ :End
179
180 ⍝ To Check if Byte Count is Correct
181 :If 3>⍴,r
182 :OrIf r[3]≠¯5+⍴,r
183 r←0 'Byte Count Incorrect Error' ⋄ →0
184 :End
185
186 ⍝ To Check if the CRC of the Answer is Correct
187 :If ~(CRC_D ¯2↓r)≡¯2↑r
188 r←0 'CRC Error on Answer' ⋄ →0
189 :End
190
191 ⍝ To Check if the Address of MODBUS device is Present
192 :If modbusAddr≠r[1] ⋄ r←0 'Serial Address of MODBUS device Not Present Error' ⋄ →0 ⋄ :End
193
194 ⍝ To Check if Command Number is Present
195 :If 131=r[2] ⋄ r←0 'Command Number Error' ⋄ →0 ⋄ :End
196 :If 3≠r[2] ⋄ r←0 'Command Number Not Present' ⋄ →0 ⋄ :End
197
198 ⍝ Success
199 r←3↓¯2↓r
200 r←1,(FLOAT_TO_DEC r[⍳4])
201 ∇
202
203
204 ∇ r←sendObj PRESET_REG_FLOAT(modbusAddr regAddr value)
205 :Access Public
206 ⍝ Write a Float Value to a single Register
207 ⍝
208 ⍝ sendObj = SerialPort or TCP object
209 ⍝ modbusAddr = Address of MODBUS device
210 ⍝ regAddr = Address of Register
211 ⍝ value = Value
212 ⍝
213 ⍝ r[1] = 1 for Success, 0 for Failure
214 ⍝ r[2] = Literal Error if Failure
215
216 r←I2H2 modbusAddr ⍝ Serial Address of MODBUS device
217 r,←'10' ⍝ Preset Register Command (16 decimal)
218 r,←I2H4 regAddr-40001 ⍝ Starting Address
219 r,←'0002' ⍝ 2 Registers To Write
220 r,←'02' ⍝ Byte Count
221 r,←DEC_TO_FLOAT value ⍝ Decimal to Hex
222 r,←CRC_H r ⍝ Checksum Calculation
223 r←H22B r ⍝ Hex To Bytes
224 r←sendObj.SendReceive r ⍝ Communication
225
226 ⍝ To Exit on Communication Error
227 :If 0=1⊃r ⋄ →0 ⋄ :Else ⋄ r←2⊃r ⋄ :End
228
229 ⍝ To Check if the CRC of the Answer is Correct
230 :If ~(CRC_D ¯2↓r)≡¯2↑r
231 r←0 'CRC Error on Answer' ⋄ →0
232 :End
233
234 ⍝ To Check if the Address of MODBUS device is Present
235 :If modbusAddr≠r[1] ⋄ r←0 'Serial Address of MODBUS device Not Present Error' ⋄ →0 ⋄ :End
236
237 ⍝ To Check if Command Number is Present
238 :If 131=r[2] ⋄ r←0 'Command Number Error' ⋄ →0 ⋄ :End
239 :If 16≠r[2] ⋄ r←0 'Command Number Not Present' ⋄ →0 ⋄ :End
240
241 ⍝ Success
242 r←1
243 ∇
244
245
246 ∇ r←sendObj PRESET_REG_INT(modbusAddr regAddr value)
247 :Access Public
248 ⍝ Write an Integer Value to a single Register
249 ⍝
250 ⍝ sendObj = SerialPort or TCP object
251 ⍝ modbusAddr = Address of MODBUS device
252 ⍝ regAddr = Address of Register
253 ⍝ value = Value (0 - 65535)
254 ⍝
255 ⍝ r[1] = 1 for Success, 0 for Failure
256 ⍝ r[2] = Literal Error if Failure
257
258 r←I2H2 modbusAddr ⍝ Serial Address of MODBUS device
259 r,←'10' ⍝ Preset Register Command
260 r,←I2H4 regAddr-40001 ⍝ Starting Address
261 r,←'0001' ⍝ 1 Registers To Write
262 r,←'02' ⍝ Byte Count
263 r,←I2H4 value ⍝ Integer to Hex
264 r,←CRC_H r ⍝ Checksum Calculation
265 r←H22B r ⍝ Hex To Bytes
266 r←sendObj.SendReceive r ⍝ Communication
267
268 ⍝ To Exit on Communication Error
269 :If 0=1⊃r ⋄ →0 ⋄ :Else ⋄ r←2⊃r ⋄ :End
270
271 ⍝ To Check if the CRC of the Answer is Correct
272 :If ~(CRC_D ¯2↓r)≡¯2↑r
273 r←0 'CRC Error on Answer' ⋄ →0
274 :End
275
276 ⍝ To Check if the Address of MODBUS device is Present
277 :If modbusAddr≠r[1] ⋄ r←0 'Address of MODBUS device Not Present Error' ⋄ →0 ⋄ :End
278
279 ⍝ To Check if Command Number is Present
280 :If 131=r[2] ⋄ r←0 'Command Number Error' ⋄ →0 ⋄ :End
281 :If 16≠r[2] ⋄ r←0 'Command Number Not Present' ⋄ →0 ⋄ :End
282
283 ⍝ No error
284 r←1
285 ∇
286
287
288 ∇ r←CRC_D v;i;ii;lsb
289 ⍝ Calculate the CRC of a Decimal String
290 r←16⍴1
291 :For i :In ⍳⍴v
292 r[⎕IO+7+⍳8]←(¯8↑r)≠,⍉(8⍴2)⊤v[i] ⍝ XOR est ≠
293
294 :For ii :In ⍳8
295 lsb←¯1↑r ⋄ r←0,15↑r
296 :If 1=lsb
297 r←r≠1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
298 :End
299 :End
300 :End
301 r←⌽2⊥⍉2 8⍴r
302 ∇
303
304
305 ∇ r←CRC_H v;hex;i;ii;lsb
306 ⍝ Calculate the CRC of a Hexadecimal String
307 hex←'0123456789ABCDEF' ⋄ v←(-⎕IO)+hex⍳,v~' ' ⋄ r←16⍴1
308 :For i :In ¯1+2×⍳0.5×⍴v
309 r[⎕IO+7+⍳8]←(¯8↑r)≠,⍉2 2 2 2⊤v[i,i+1] ⍝ XOR est ≠
310
311 :For ii :In ⍳8
312 lsb←¯1↑r ⋄ r←0,15↑r
313 :If 1=lsb
314 r←r≠1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
315 :End
316 :End
317 :End
318 r←2⌽hex[⎕IO+2⊥⍉4 4⍴r]
319 ∇
320
321
322 ∇ r←FLOAT_TO_DEC v;exponent;sign;significand
323 ⍝ Convert a Float Quadlet (32 bits) to Decimal Number
324 v←,(⍉(8⍴2)⊤v)[3 4 1 2;]
325 sign←,1↑[1]⍉v
326 exponent←2⊥8↑[1]1↓[1]⍉v
327 significand←2⊥¯23↑[1]⍉v
328 r←(¯1*sign)×(1+significand÷2*23)×2*(exponent-127)
329 r←(0≠+/[1]⍉v)×r
330 ∇
331
332
333 ∇ r←DEC_TO_FLOAT v;exponent;sign;significand
334 ⍝ Convert a Decimal Number to a Float Quadlet
335 ⍝ THE 2*¯127 IS TO TAKE CARE OF ZERO (ERROR IF ⍟0)
336 sign←¯1=×v
337 exponent←⍉(8⍴2)⊤127+⌊2⍟|v⍝+2*¯127
338 significand←⍉(23⍴2)⊤⌊(2*23)ׯ1+2*1|2⍟|v⍝+2*¯127
339 r←sign,exponent,significand
340 r←4⌽'0123456789ABCDEF'[⎕IO+2⊥⍉8 4⍴r]
341 ∇
342
343 :EndNamespace
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.