OH3 write value in modbus slave

Hello,
i’m sitting on a problem and can’t find a working solution, I know the solution is probably simple but apparently not for me :frowning:

I have modbus adapter to air conditioner UTY-VMSX MODBUS and i can read value with state but i cant write any value from OH3, from emulator modbus “qmodbus” is write well.

Air conditioner have address reiestr to write valu is 40003 and value 1=power off 2=power on, but to read state air conditioner is 30054 and value 1=power off 2=power on.

My .thing looks like this:

Bridge modbus:tcp:Klima [ host="192.168.2.7", port=503, id=22, receiveTimeoutMillis="150", timeBetweenTransactionsMillis="50" ]
    {
     Bridge poller inputID22 [start=54, length=4, refresh=500, type="input" ]{
          Thing data stanpracy [ readStart="54", readValueType="uint16" ]
          }
    Bridge poller winputID22 [start=3, length=1, refresh=500, type="holding" ]{
          Thing data OnOffKlim [writeType="holding", writeStart="3", writeValueType="uint16" ]


    }
}

.item

Number klimaOnOff       "Stan pracy [MAP(klimaOnOff.map):%s]"                {channel="modbus:data:Klima:inputID22:stanpracy:number"}

Number OnOffKlima        "Stan pracy [%s]"  {channel="modbus:data:Klima:winputID22:OnOffKlim:number"}

.sitemap

 Text item=klimaOnOff
Switch item=OnOffKlima icon="switch" mappings=[1="OFF", 2="ON" ]

i log i do not have any errors, could you help, please :slight_smile:

Please show us the successful write command for this, then we’ll be able to work out what you’re trying to do in openHAB.

Note that the Fujitsu documents talk about holding register numbers 40001 to 49999.
As you’ve already worked out, the 4xxxx part just means “holding type” and is not really part of the address. Probably.

There are two ways to reference registers, ‘numbers’ that start counting from 1 and ‘addresses’ that start counting from 0
Fujitsu seem to use numbers.
I don’t know what qmodbus uses.
openHAB uses addresses.
Register number 3 (or 40003) = (holding) register address 2

1 Like

You have right, its working:

Bridge poller winputID22 [start=2, length=1, refresh=500, type="holding" ]{
          Thing data OnOffKlim [writeType="holding", writeStart="2", writeValueType="int16" ]

Because your data Thing is write-only, you don’t need to read poll holding register 2 at all.
You can put your write-only for holding 2 under the same Bridge poller for input 4 (and should that one be input 3?)

Hello Rossko57,
i have one more question about modbus adapter to air conditioner UTY-VMSX MODBUS.
Follow the manual to change temperature i must write FC6 in address 3 value for example 80 and this is 80/4 = 20C

To read FC4 addresses 55 - here i see value but if i change in FC6 3 there is no change value only change when i change by manipulator.

What im doing wrong ?

**


**

I’ve no idea what meaning the device gives to that location.
EDIT - I found 30056 represent set temp x 4, so that looks good.

I think you’re telling us that whether you use openHAB or qmodbus, you don’t get what you expect?

EDIT - I found a doc for this, and (in English)
fuji_reg03
it seems to say that you must set bit 0 or else there is no change.
Further, because bit 0 is used for that, the actual value goes into bits 1 - 8
And also it goes in 0.5C steps, not 0.25C that you might expect from the odd “x 4” business.

Alright, so let’s assume Fujitsu call the least significant register bit “0”.
You’ll need to send an odd-numbered value to set that bit.
So,not 80 but 81.

Although it’s not clear from the docs if you might have to shift the “80” up a bit position - then it would be not 80 but 161.

If you can work out what is needed, you can do all this in a write transformation JS. That is, command your Item with 20 and have it transformed at the channel to 81 or 161.

You are good :slight_smile:
Thank you very much for your help and i thing i will have more questions but not now :slight_smile:
when write FC6 3 “161” → FC4 55 “80” → 20.0°C and it’s work :slight_smile:
When i finish my configuration i will public tutorial.

Have you worked out transformations? I was curious enough to have a think about that.

Incoming readTransform for 30056 seems easy enough

// function to divide Modbus integer by 4 to give value in C
// input variable i contains data passed by OpenHAB binding
(function(i) {
    if (i == 'UNDEF') { return i; } // pass any error
    else { return  parseFloat(i) / 4 ; }
})(input)

The output writeTransform for 40004 is more challenging

// function to do Fujitsu magic from command in C
(function(i) {
    var x = Math.round(parseFloat(i) * 2) / 2;  // round to 0.5 steps
    x = (x * 8) + 1; // x2 to shift one bit, x4 for Fujitsu, +1 for bit 0
    return  x ;  // will be integer
})(input)

Untested, but you get the idea

Ok, my air conditioner is working. It works, but it could work more elegantly and could be optimized. I did as I can. Optimization fixes welcome.

modbus.thing

Bridge modbus:tcp:Klima [ host="192.168.2.7", port=503, id=22, receiveTimeoutMillis="150", timeBetweenTransactionsMillis="50" ]
    {
     Bridge poller inputID22 [start=53, length=4, refresh=500, type="input" ]{
          Thing data trybpracy [ readStart="53", readValueType="uint16" ]
          Thing data stanpracy [ readStart="54", readValueType="uint16" ]
          Thing data tempnast [ readStart="55", readValueType="uint16" ]
          Thing data ustawienienawiewu [ readStart="56", readValueType="uint16" ]
          }
    Bridge poller winputID22 [start=1, length=4, refresh=500, type="holding" ]{
          Thing data TrybKlim [writeType="holding", writeStart="1", writeValueType="int16" ]
          Thing data OnOffKlim [writeType="holding", writeStart="2", writeValueType="int16" ]
          Thing data UstTemp [writeType="holding", writeStart="3", writeValueType="int16" ]
          Thing data NawKlim [writeType="holding", writeStart="4", writeValueType="int16" ]
    }
}

air_conditioner.items

Number klimaOnOff       "Stan pracy [MAP(klimaOnOff.map):%s]"                {channel="modbus:data:Klima:inputID22:stanpracy:number"}
Number klimaTryb       "Stan pracy [MAP(klimaTrybP.map):%s]"                {channel="modbus:data:Klima:inputID22:trybpracy:number"}
Number klimaUstNaw       "Ust. nawiewu [MAP(klimaUstNaw.map):%s]"                {channel="modbus:data:Klima:inputID22:ustawienienawiewu:number"}
Number klimaTempNast                                 {channel="modbus:data:Klima:inputID22:tempnast:number"}
Number klimaTempNastR       "Temp. nastawoina [%.1f °C]"

Number OnOffKlimaW          {channel="modbus:data:Klima:winputID22:OnOffKlim:number"}
Switch OnOffKlima    "Stan pracy [%s]"

Number TrybKlimaW          {channel="modbus:data:Klima:winputID22:TrybKlim:number"}
Number TrybKlima "Tryb pracy"

Number NawiKlimaW          {channel="modbus:data:Klima:winputID22:NawKlim:number"}
Number NawiKlima "Ust. nawiewu"

Number TempKlimaW          {channel="modbus:data:Klima:winputID22:UstTemp:number"}
Number TempKlimaWTym "Temperatura [%.1f °C]"

air_conditioner.sitemap

sitemap home label="My home"
{
Text label="Klimatyzacja" item=klimaOnOff icon="snow" valuecolor=[ On==2="green", Off==1="red" ] {
      Frame label="Statusy" {
        Text item=klimaOnOff valuecolor=[ On==2="green", Off==1="red" ]
        Text item=klimaTryb valuecolor=[ Chlodzenie==2="blue", Grzanie==4="red" ]
        Text item=klimaUstNaw
        Text item=HollgTemp
        Text item=klimaTempNastR
     }
     Frame label="Nastawy" {
        Switch item=OnOffKlima
        Selection item=TrybKlima mappings=[1="Auto", 2="Chłodzenie", 3="Osuszanie", 4="Grzanie", 5="Wentylacja"] valuecolor=[ Chlodzenie==2="blue", Grzanie==4="red" ]
        Selection item=NawiKlima mappings=[1="Auto", 2="Cicha praca", 3="Niskie obroty", 4="Średnie obroty", 5="Wysokie obroty", 6="Średnie-niskie", 7="Średnie-wysokie"]
        Setpoint item=TempKlimaWTym minValue=16 maxValue=25 step=0.5
   }
}

klimaOnOff.map

0=Bez zmian
1=Off
2=On

klimaTrybP.map

0=Bez zmian
1=Auto
2=Chlodzenie
3=Osuszanie
4=Grzanie
5=Wentylacja

klimaUstNaw.map

0=Bez zmian
1=Auto
2=Cicha praca
3=Niskie obroty
4=Średnie obroty
5=Wysokie obroty
6=Średnie-niskie
7=Średnie-wysokie

Rules:

klimaNaw.rules

rule "Przycisk NawiewKlima"
when
    Item NawiKlima changed
then
    if(NawiKlima.state == 1) {
                   logInfo("klimaNaw.rules", "KlimaNaw 1")
                   NawiKlimaW.sendCommand(1)
       } else if (NawiKlima.state == 2) {
                   logInfo("klimaNaw.rules", "KlimaNaw 2")
                   NawiKlimaW.sendCommand(2)
       } else if (NawiKlima.state == 3) {
                   logInfo("klimaNaw.rules", "KlimaNaw 3")
                   NawiKlimaW.sendCommand(3)
       } else if (NawiKlima.state == 4) {
                   logInfo("klimaNaw.rules", "KlimaNaw 4")
                   NawiKlimaW.sendCommand(4)
       } else if (NawiKlima.state == 5) {
                   logInfo("klimaNaw.rules", "KlimaNaw 5")
                   NawiKlimaW.sendCommand(5)
       } else if (NawiKlima.state == 6) {
                   logInfo("klimaNaw.rules", "KlimaNaw 6")
                   NawiKlimaW.sendCommand(6)
       } else if (NawiKlima.state == 7) {
                   logInfo("klimaNaw.rules", "KlimaNaw 7")
                   NawiKlimaW.sendCommand(7)
       }
end
rule "klimaUstNaw manual"
when
    Item klimaUstNaw changed
then
      if(klimaUstNaw.state == 1) {
                   NawiKlima.postUpdate(1)
       } else if (klimaUstNaw.state == 2) {
                   NawiKlima.postUpdate(2)
       } else if (klimaUstNaw.state == 3) {
                   NawiKlima.postUpdate(3)
       } else if (klimaUstNaw.state == 4) {
                   NawiKlima.postUpdate(4)
       } else if (klimaUstNaw.state == 5) {
                   NawiKlima.postUpdate(5)
       } else if (klimaUstNaw.state == 6) {
                   NawiKlima.postUpdate(6)
       } else if (klimaUstNaw.state == 7) {
                   NawiKlima.postUpdate(7)
       }
end

klima.rules

rule "Temperatura Nastawiona"
when
    Item klimaTempNast changed
     or
    Item TempKlimaW changed
     or
    Item TempKlimaWTym changed
then
    var TNTemp = klimaTempNast.state as DecimalType / 4
              postUpdate(klimaTempNastR, TNTemp)
end

rule "Klimatyzacja OnOff manual"
when
    Item klimaOnOff changed
then
     if(klimaOnOff.state == 2) {
                   logInfo("klima.rules", "Klima manual ON")
                   OnOffKlima.postUpdate(ON)
       } else if (klimaOnOff.state == 1) {
                   logInfo("klima.rules", "Klima manual OFF")
                   OnOffKlima.postUpdate(OFF)
       }
end
rule "Przycisk OnOff"
when
    Item OnOffKlima changed
then
    if(OnOffKlima.state == ON) {
                   logInfo("klima.rules", "KlimaTemp ON")
                   OnOffKlimaW.sendCommand(2)
       } else if (OnOffKlima.state == OFF) {
                   logInfo("klima.rules", "KlimaTemp OFF")
                   OnOffKlimaW.sendCommand(1)
       }
end

klimaTemp.rules

rule "Przycisk TrybKlima"
when
    Item TempKlimaWTym changed
then
       var TempKlimaWTym1 = TempKlimaWTym.state as DecimalType * 8 + 1
//       var TempKlimaWTymNum = TempKlimaWTym1.state as Number
        TempKlimaW.sendCommand(TempKlimaWTym1)
end

klimaTryb.rules

rule "Przycisk TrybKlima"
when
    Item TrybKlima changed
then
    if(TrybKlima.state == 1) {
                   logInfo("klimaTryb.rules", "KlimaTemp ON")
                   TrybKlimaW.sendCommand(1)
       } else if (TrybKlima.state == 2) {
                   logInfo("klimaTryb.rules", "KlimaTemp OFF")
                   TrybKlimaW.sendCommand(2)
       } else if (TrybKlima.state == 3) {
                   logInfo("klimaTryb.rules", "KlimaTemp OFF")
                   TrybKlimaW.sendCommand(3)
       } else if (TrybKlima.state == 4) {
                   logInfo("klimaTryb.rules", "KlimaTemp OFF")
                   TrybKlimaW.sendCommand(4)
       } else if (TrybKlima.state == 5) {
                   logInfo("klimaTryb.rules", "KlimaTemp OFF")
                   TrybKlimaW.sendCommand(5)
       }
end

rule "TrybKlima manual"
when
    Item klimaTryb changed
then
      if(klimaTryb.state == 1) {
                   TrybKlima.postUpdate(1)
       } else if (klimaTryb.state == 2) {
                   TrybKlima.postUpdate(2)
       } else if (klimaTryb.state == 3) {
                   TrybKlima.postUpdate(3)
       } else if (klimaTryb.state == 4) {
                   TrybKlima.postUpdate(4)
       } else if (klimaTryb.state == 5) {
                   TrybKlima.postUpdate(5)
       }
end

You mean, like this ? Because looks like it’s working :slight_smile:

Bridge modbus:tcp:Klima [ host="192.168.2.7", port=503, id=22, receiveTimeoutMillis="150", timeBetweenTransactionsMillis="50" ]
    {
     Bridge poller inputID22 [start=1, length=56, refresh=500, type="input" ]{
          Thing data trybpracy [ readStart="53", readValueType="uint16",writeType="holding", writeStart="1", writeValueType="int16" ]
          Thing data stanpracy [ readStart="54", readValueType="uint16",writeType="holding", writeStart="2", writeValueType="int16" ]
          Thing data tempnast [ readStart="55", readValueType="uint16", readTransform="JS:klimaTemp.js", writeType="holding", writeStart="3", writeValueType="int16", writeTransform="JS:klimaTempW.js" ]
          Thing data ustawienienawiewu [ readStart="56", readValueType="uint16", writeType="holding", writeStart="4", writeValueType="int16" ]
          }