Closed pkkrusty closed 8 months ago
this is already implemented. i once wanted to adapt my GROWATT inverter to the german 70 percent rule and startet with this MODBUS slave. However this rule is no longer needed, so i did not further test it. here is my initial script for the slave mode. that did work but will certainly need some tweaking
remark: in this example the slave gets its input values from global variables.
needs #define USE_SCRIPT_SERIAL
>D 64
IP=192.168.188.99
; simulate eastron sdm modbus meter
res=0
m:req=0 8
m:resp=0 128
addr=1
regs=0
; maximum allowed export with 10,35 kw modules
limit=7250
; aktueller verbrauch bzw einspeisung
g:zwzc=0
g:zwzi=0
g:zwzo=0
; udp timeout timer
t:udpt=30
col="green"
>BS
res=0
res=so(18 19 9600 8N1 1024)
print open %res%
->setsensor127 0
>G
; reset udp timer
udpt=60
>F
res=sa()
if res>0
then
;print res=%res%
res=sra(req)
print request = %req[1]% - %req[2]% - %req[3]% - %req[4]% - %req[5]% - %req[6]%
delay(10)
; slave adress
; function code
; start adress Hi
; start adress Lo
; np Hi
; np Lo
; crc Lo
; crc Hi
regs=req[6]/2
resp[1]=0
resp[2]=0
resp[3]=0
resp[4]=0
resp[5]=0
resp[6]=0
resp[7]=0
resp[8]=0
resp[9]=0
resp[10]=0
if res==8
and req[1]==addr
and req[2]==4
and req[3]==0
and req[4]==0 {
print Reg 0 7
; report 230 Volts, current, watts, va
resp[1]=230
resp[2]=0
resp[3]=0
resp[4]=2
resp[5]=0
resp[6]=0
resp[7]=abs(zwzc)
smw(addr 3 resp regs)
}
if res==8
and req[1]==addr
and req[2]==4
and req[3]==0
and req[4]==70 {
print Reg 0x46 5
;frequency 0x46, total import, total export, total imp kva, total export kva
resp[1]=50
resp[2]=zwzo
resp[3]=zwzi
resp[4]=zwzo
resp[5]=zwzi
smw(addr 3 resp regs)
}
if res==8
and req[1]==addr
and req[2]==4
and req[3]==1
and req[4]==86 {
print Reg 0x156 2
; report total kwh, kvarh
resp[1]=zwzo
resp[2]=zwzo
smw(addr 3 resp regs)
}
if res==8
and req[1]==addr
and req[2]==4
and req[3]==0
and req[4]==18 {
print Reg 0x12 7
; p1 voltamps 0x12, voltamps reactive
resp[1]=abs(zwzc)
resp[2]=0
resp[3]=0
resp[4]=abs(zwzc)
resp[5]= 0
resp[6]= 0
resp[7]=1
smw(addr 3 resp regs)
}
endif
>S
; upd timeout
if udpt==0 {
gvr
udpt=-1
}
if zwzc<0
then
col="green"
else
col="red"
endif
>W
ZRZ total Verbrauch: {m}<span style="color:red;">%0zwzi% W</span>
ZRZ total Einspeisung: {m}<span style="color:green;">%0zwzo% W</span>
ZRZ akt Verbrauch/Einspeisung: {m}<span style="color:%col%;">%0zwzc% W</span>
In documentation smw() has three arguments, address, mode, number, i.e. smw(0 0 65535). But you use in this example four arguments. smw(addr 3 resp regs)
I assume undocumented feature that sends array length regs
(in this case array of float values)?
Also, usual modbus master address is 0, so if I am communicating with another tasmota device that is using SML scripting, it will be master with address 0, correct?
smw(ADDR MODE ARRAY NVALS ) NVALS = number of values of array to send
yes
another user wanted a modbus slave with TCP. (SML reader simulates a TCP modbus device)
so i added TCP IO support today.
in case you are also interested i will post the new commands here
In these days I got a new central heating Type Solvis Ben which provides all Sensor and counting values by TCP Modbus. So I might be one future user of your implementation. Thanks in advance, but I guess it takes some weeks for me to do a first test. Maybe you can collect your postings into one document related to Modbus or whatever to have one common source.
syntax of TCP interface
wso(port) start a tcp stream server at port
wsc() close tcp stream server
wsa() return bytes available on tcp stream
str=wsrs() return a string read from tcp stream
wsws(string) writes a string to tcp stream
wsra(array) reads a tcp stream into array
wswa(array num) writes num bytes of array to tcp stream
Thanks Gerhard. Any additional hint for me to understand the modbus stream / protocol? I was wondering that the wso() do not need an IP address. Is this because a slave is waiting until the server likes to talk to him? In this case I guess my heating controller is a modbus slave itself and an information reading device has to act as server. By the way, have you heard anything about Solvis Control 3 (SC-3) or a guy who wants to do the same like me?
we are talking from a modbus slave that simulates a modbus tcp meter
a TCP modbus master is implemented in the SML driver. (see docs)
sorry i have no knowledge about any Solvis user.
this emulates an SDM630 meter
>D
IP=192.168.188.106
; emulate SDM630 (has float registers)
res=0
cnt=0
xcnt=0
once=0
reg=0
ind=0
nval=0
M:req=0 16
M:resp=0 64
>BS
; start server
res=wso(502)
print res=%res%
; set register values
#dosel
switch reg
case 0
resp[ind]=230
case 2
resp[ind]=231
case 4
resp[ind]=232
case 6
resp[ind]=10
case 8
resp[ind]=20
case 10
resp[ind]=30
case 12
resp[ind]=100
case 14
resp[ind]=200
case 16
resp[ind]=300
ends
>F
; check incomming data
xcnt =wsa()
if xcnt>0 {
print bytes=%xcnt%
; read request
res=wsra(req)
reg=req[10]
print register %reg%
nval=req[12]
print count %nval%
; transaction id
resp[1]=req[1]
resp[2]=req[2]
; protocol id
resp[3]=req[3]
resp[4]=req[4]
; length
resp[5]=0
resp[6]=req[12]*2+3
;device address
resp[7]=req[7]
; function code
resp[8]=req[8]
; payload len
resp[9]=req[12]*2
; write response
wswa(resp 9)
resp[1]=99
; 3 phase voltage, current, power values
ind=1
for cnt 1 nval 2
=#dosel
reg+=2
ind+=1
next
; write data part (float values)
wswa(resp ind-1 3)
}
>R
; close server
res=wsc()
this is a master modbus script for sdm630
>D
IP=192.168.188.117
>B
->sensor53 r
; multiple float register request
>M 1
+1,[192.168.188.106],m,0,502,SDM630,0,10,r010400000006,r010400060006,r0104000c0006
1,01040cffffffff@i0:1,Voltage P1,V,Voltage_P1,2
1,01040cx4ffffffff@i0:1,Voltage P2,V,Voltage_P2,2
1,01040cx8ffffffff@i0:1,Voltage P3,V,Voltage_P3,2
1,01040cffffffff@i1:1,Current P1,A,Current_P1,2
1,01040cx4ffffffff@i1:1,Current P2,A,Current_P2,2
1,01040cx8ffffffff@i1:1,Current P3,A,Current_P3,2
1,01040cffffffff@i2:1,Active Power P1,W,Power_P1,2
1,01040cx4ffffffff@i2:1,Active Power P2,W,Power_P2,2
1,01040cx8ffffffff@i2:1,Active Power P3,W,Power_P3,2
#
; single float register request
>xM 1
+1,[192.168.188.106],m,0,502,SDM630,0,10,01040000,01040002,01040004,01040006,01040008,0104000a,0104000c,0104000e,01040010
1,010404ffffffff@i0:1,Voltage P1,V,Voltage_P1,2
1,010404ffffffff@i1:1,Voltage P2,V,Voltage_P2,2
1,010404ffffffff@i2:1,Voltage P3,V,Voltage_P3,2
1,010404ffffffff@i3:1,Current P1,A,Current_P1,2
1,010404ffffffff@i4:1,Current P2,A,Current_P2,2
1,010404ffffffff@i5:1,Current P3,A,Current_P3,2
1,010404ffffffff@i6:1,Active Power P1,W,Power_P1,2
1,010404ffffffff@i7:1,Active Power P2,W,Power_P2,2
1,010404ffffffff@i8:1,Active Power P3,W,Power_P3,2
#
Have you looked for this feature in other issues and in the docs?
Is your feature request related to a problem? Please describe.
Possibility of tasmota device acting as MODBUS slave. If it can be assigned a slave ID and and the function return data from an array, could even happen without user input.
Describe the solution you'd like
User enters slave ID (or even slave ID as array[1], then all registers in the array depending on size defined.
Describe alternatives you've considered
Would allow for long distance two-wire communication between tasmota devices on a single bus.
Additional context
Add any other context or screenshots about the feature request here.
(Please, remember to close the issue when the problem has been addressed)