Page 1 of 4 123 ... LastLast
Results 1 to 10 of 36

Thread: Control protocol StorkAir WHR950

  1. #1
    Join Date
    Oct 2008
    Posts
    2

    Default Control protocol StorkAir WHR950

    Hi anyone!!
    From an earlier post I got to know, that the control protocol for the StorkAir WHR950 is known by user's of the forum.
    Since I want to connect the device to my KNX bus at home I kindly ask to share the information. The manufacturer does not react to my apply, so the forum might help??

    Best regards,
    Lars

  2. #2
    Join Date
    Aug 2004
    Location
    The Netherlands (Norg, near Assen)
    Posts
    625

    Default

    Hi Lars,

    You're right. I control the Storkair WHR950 using Girder. I also read the WHR values from the WHR (Fan speed and Temperatures).

    I'll post the the sending part and the receiving part LUA code. It has not been tidied up yet so you have to find your way through.

    Communication settings: 9600 baud, no parity, 1 stopbits, 8 databits

    Send function:
    Main function is to queue the commands while WHR is still processing.
    (WHR:SendCommand(serial.hextobyte(data)) is the real send function)

    Code:
     
    function ToWHR(funct,data)
     if not Enable.WHR or not WHR then return end
     data=funct..string.format("%02X",string.len(data or 0)/2)..(data or "")
     data="07F000"..data..WHRcrc(data).."070F"
     --WHRLog(data)
     --print ("ToWHR:"..data.." /" ..win.GetElapsedMilliseconds(WHR.LastResponse or 0).." (input)")
     if WHR.ResponsePending or WHRdata~="" or win.GetElapsedMilliseconds(WHR.LastResponse or 0)< 25 or table.getn(WHRqueue)~=0 then
      table.insert(WHRqueue,data)
      if table.getn(WHRqueue)==1 then TIM_WHR:Arm(25) end
     else
         if data and data~="" then --tijdelijk ivm debugging error 'Lastcommand'
       WHR:SendCommand(serial.hextobyte(data))
       --print("ToWHR:"..data.." (send direct)")
      else
       ErrorLog("===========================Unexpected empty Queue in ToWHR ",WHRqueue[1]) 
      end
     end
    end
    function WHRnext()
     --print("WHRnext: Queue checking....")
     if not WHR.ResponsePending and (WHRdata=="" or win.GetElapsedMilliseconds(WHR.LastResponse)>250) then
      if WHRqueue[1] and WHRqueue[1]~="" then --tijdelijk ivm debugging error 'Lastcommand'
       WHR:SendCommand(serial.hextobyte(WHRqueue[1]))
      else
       ErrorLog("===========================Unexpected empty Queue in WHRnext ",WHRqueue[1]) 
      end
      --print("WHRnext: "..WHRqueue[1].." (send queue pos 1 of "..table.getn(WHRqueue)..")")
      table.remove(WHRqueue,1)
      if table.getn(WHRqueue)==0 then TIM_WHR:Cancel() end
     else
      --if WHR.ResponsePending then print("WHRnext: $WHR.ResponsePending still true") end
      --if WHRdata~="" then
       --print("WHRnext: $WHRdata was not yet empty ("..WHRdata..")")
       --if win.GetElapsedMilliseconds(WHR.LastResponse)>250 then print("WHRnext: $WHRdata expired ("..WHRdata..")") end
      --end
     end
    end
    --ToWHR("85")  --Query Temp
    --ToWHR("87")  --Query Ventilatoren
    --ToWHR("89")  --Query Parameters 1 (o.a. snelheden)
    --ToWHR("8B")  --Query Parameters 2 (o.a. temperaturen)
    Receive function:


    Code:
    --processed after each received datastream
    function WHRprocess(data,code)
    if not Enable.WHR then return end
      --print ("WHRRAW="..data.." (code="..code.." t="..win.GetElapsedMilliseconds(WHR.LastResponse).."Length:"..string.len(data)..")")
      if win.GetElapsedMilliseconds(WHR.LastResponse or 0)>1000 then  --if lastinput was too long ago then start new sequence (clear inputbuffer)
        if WHRdata~="" then WHRLog("--------"..WHRdata.." ("..string.len(WHRdata).."/"..win.GetElapsedMilliseconds(WHR.LastResponse)..")") print("WHR: cleared ("..WHRdata..")") end
        WHRdata=""   
      end
      WHRdata=WHRdata..data
      if string.len(WHRdata)>44 then
     WHRLog(WHRdata.." Datalength exceeded 44 chars ("..string.len(WHRdata).."/"..win.GetElapsedMilliseconds(WHR.LastResponse)..")")
     WHRdata=""
      end
      if string.sub(WHRdata,1,4)=="07F0" then  --datagram start
     if string.sub(WHRdata,-4)=="070F" then --datagram terminator 
       if WHRcrc(string.sub(WHRdata,5,-7))==string.sub(WHRdata,-6,-5) then
      WHRLog(WHRdata)
      --print(WHRdata)
      WHRfunction=string.sub(WHRdata,7,8)
      WHRdata=string.sub(WHRdata,9,-7) --strip start("07F0"),function, CRC and terminator("070F")
      Count.WHR=Count.WHR+1
     
      if WHRfunction=="84" then  --Lezen Temp; Query: ToWHR("07F000850032")
       WHR.TempAanvIn=(serial.hextodecimal(string.sub(WHRdata,9,10))/2-21.5) -- -20=normal; other is temp.correction
       WHR.TempAfvIn =(serial.hextodecimal(string.sub(WHRdata,11,12))/2-20)
       WHR.TempAfvUit=(serial.hextodecimal(string.sub(WHRdata,13,14))/2-21)
       WHR.Temp1=(serial.hextodecimal(string.sub(WHRdata,15,16))/2-20)
       NetRemote.SetVariable("Temp17",WHR.TempAanvIn.." C.")
       NetRemote.SetVariable("Temp18",WHR.TempAfvUit.." C.")
       NetRemote.SetVariable("Temp19",WHR.TempAfvIn.." C.")
       NetRemote.SetVariable("WTW.line6",WHR.Temp1.."C.")
       NetRemote.SetVariable("WTW.bypass",serial.hextodecimal(string.sub(WHRdata,3,4)))
       --[[
       print("84: ",
       "Bypass:"..serial.hextodecimal(string.sub(WHRdata,3,4)),
       serial.hextodecimal(string.sub(WHRdata,5,6)),
       serial.hextodecimal(string.sub(WHRdata,7,8)),
       "TaanvIn:"..WHR.TempAanvIn.."C",
       "TafvIn:"..WHR.TempAfvIn.."C",
       "TafvUit:"..WHR.TempAfvUit.."C",
       "T1:"..WHR.Temp1.."C",
       serial.hextodecimal(string.sub(WHRdata,17,18)),
       serial.hextodecimal(string.sub(WHRdata,19,20)),
       serial.hextodecimal(string.sub(WHRdata,21,22)))
       FLog("WHR84",WHRdata)
       --]]
      end
      if WHRfunction=="86" then  --Query: ToWHR("07F000870034")
       WHRvar.currentSpeed=serial.hextodecimal(string.sub(WHRdata,3,4))
       WHRvar.position=serial.hextodecimal(string.sub(WHRdata,19,20))+1
       NetRemote.SetVariable("WTW.line1","Aanvoer : "..WHRvar.currentSpeed.."% "..(serial.hextodecimal(string.sub(WHRdata,7,8))*20).."rpm")
       NetRemote.SetVariable("WTW.line2","Afvoer  : "..serial.hextodecimal(string.sub(WHRdata,5,6)).."% "..(serial.hextodecimal(string.sub(WHRdata,9,10))*20).."rpm")
       NetRemote.SetVariable("WTW.stand",WHRvar.position)
       --[[
       print("86: ",
       "Toevoer:"..serial.hextodecimal(string.sub(WHRdata,3,4)).."%("..(serial.hextodecimal(string.sub(WHRdata,7,8))*20).."rpm)",
       "Afvoer :"..serial.hextodecimal(string.sub(WHRdata,5,6)).."%("..(serial.hextodecimal(string.sub(WHRdata,9,10))*20).."rpm)",
       "ByPass:"..serial.hextodecimal(string.sub(WHRdata,11,12)),
       serial.hextodecimal(string.sub(WHRdata,13,14)),
       serial.hextodecimal(string.sub(WHRdata,15,16)),
       serial.hextodecimal(string.sub(WHRdata,17,18)),
       "Stand:"..serial.hextodecimal(string.sub(WHRdata,19,20)),
       serial.hextodecimal(string.sub(WHRdata,21,22)),
       serial.hextodecimal(string.sub(WHRdata,23,24)))
       FLog("WHR86",WHRdata)
       --]]
      end 
      if WHRfunction=="88" then  --Query: ToWHR("07F000890036")
         WHRvar.param1=WHRdata
       --[[
       print("88: "..serial.hextodecimal(string.sub(WHRdata,1,2)),
       serial.hextodecimal(string.sub(WHRdata,3,4)),
       "Insch.Vertr.Hoogstand"..serial.hextodecimal(string.sub(WHRdata,5,6)),
       "Uitsch.Vertr.Hoogstand"..serial.hextodecimal(string.sub(WHRdata,7,8)),
       serial.hextodecimal(string.sub(WHRdata,9,10)),
       "AfvoerLaag:"..serial.hextodecimal(string.sub(WHRdata,11,12)),
       "AfvoerMidden"..serial.hextodecimal(string.sub(WHRdata,13,14)),
       "AfvoerHoog"..serial.hextodecimal(string.sub(WHRdata,15,16)),   
       "ToevoerLaag:"..serial.hextodecimal(string.sub(WHRdata,17,18)),
       "ToevoerMidden:"..serial.hextodecimal(string.sub(WHRdata,19,20)),
       "ToevoerHoog"..serial.hextodecimal(string.sub(WHRdata,21,22)))
       FLog("WHR88",WHRdata)
       --]]
      end
      if WHRfunction=="8A" then  --Lezen parameters; Query: ToWHR("07F0008B0038")
       WHRvar.param2=WHRdata
       NetRemote.SetVariable("WTW.line3","ComfortT: "..(serial.hextodecimal(string.sub(WHRdata,5,6))/2-20).."C")
       --[[
       print("8A: "..serial.hextodecimal(string.sub(WHRdata,1,2)),
       "ToevHoog:"..serial.hextodecimal(string.sub(WHRdata,3,4)),
       "Comf.T:"..(serial.hextodecimal(string.sub(WHRdata,5,6))/2-20),
       "Naverw.T:"..(serial.hextodecimal(string.sub(WHRdata,7,8))/2-20),
       "EWT.L:"..(serial.hextodecimal(string.sub(WHRdata,9,10))/2-20),
       "EWT.H:"..(serial.hextodecimal(string.sub(WHRdata,11,12))/2-20),
       "ByPass.Hyst:"..(serial.hextodecimal(string.sub(WHRdata,13,14))/2-20),
       serial.hextodecimal(string.sub(WHRdata,15,16)),
       "AntiVorst.T:"..(serial.hextodecimal(string.sub(WHRdata,17,18))/2-20),    
       serial.hextodecimal(string.sub(WHRdata,19,20)),
       serial.hextodecimal(string.sub(WHRdata,21,22)))
       FLog("WHR8A",WHRdata)
       --]]
      end
     
      WHRdata=""
       else
      WHRLog(WHRdata.." CRC error ("..string.len(WHRdata).."/"..win.GetElapsedMilliseconds(WHR.LastResponse)..")")
      WHRdata=""
       end
     elseif string.sub(WHRdata,-4)=="07F)" then  --new datagram start received
      WHRLog(WHRdata.." unexpected start received; "..string.sub(WHRdata,1,-4).." cleared ("..string.len(WHRdata).."/"..win.GetElapsedMilliseconds(WHR.LastResponse)..")")
      WHRdata=string.sub(WHRdata,-4)
     elseif string.len(WHRdata)>(serial.hextodecimal(string.sub(WHRdata,9,10)) or 0)*2+14 then
       WHRLog(WHRdata.." datalength>length-indicatorbyte ("..string.len(WHRdata).."/"..win.GetElapsedMilliseconds(WHR.LastResponse)..")")
       WHRdata=""    
     end
      elseif string.sub(WHRdata,1,2)=="FF" then
      --WHRLog("<=FF") 
      WHRdata=""
      elseif string.sub(WHRdata,1,4)=="07F3" then  --acknowledge
      --WHRLog("<=07F3 ack") 
      WHRdata=""
      elseif string.sub(WHRdata,1,4)=="070F" then -- terminator  without start
      WHRLog(WHRdata.." terminator received without start ("..string.len(WHRdata).."/"..win.GetElapsedMilliseconds(WHR.LastResponse)..")")
      WHRdata=""   
      elseif string.sub(WHRdata,1,2)~="07" then
      WHRdata=""  --throw away bytes if not recognized
      end
    end
    function WHRcrc(data) --Checksum calculation
     local x,sum=0,0 
     for x=1,string.len(data),2 do
      sum=sum+serial.hextodecimal(string.sub(data,x,x+1))
     -- print(x,string.sub(data,x,x+1), serial.hextodecimal(string.sub(data,x,x+1)),sum)
     end
     sum=sum+173
     sum=math.band(sum,255)
     sum=string.format("%02X",sum)
     return sum
    end
    Most description of the variable I store the received values in, are in Dutch. But I think you must be able to find out what the variables mean.


    Let me know if you managed to get your communication going.

    BTW do you have the Windows program to control the WHR? If not I can PM this Maintenance program. This program I used to reverse engineer the protocol.
    Geert

  3. #3
    Join Date
    Oct 2008
    Posts
    2

    Default

    No, I don't have the program, but I would be perfect if you could send it to me!!

    Greets,
    Lars

  4. #4
    Join Date
    Aug 2004
    Location
    The Netherlands (Norg, near Assen)
    Posts
    625

    Default

    Lars, please PM me an e-mail adress I can send the program to.
    Geert

  5. #5
    Join Date
    Jul 2011
    Posts
    5

    Default Stork SW

    Quote Originally Posted by VSDomotics View Post
    Lars, please PM me an e-mail adress I can send the program to.
    Beste,
    ik ben ook bezig om een KNX-Stork RS232 interface te maken. Je info was heel erg nuttig: mijn embedded device draait lua, maar ik ben van plan een dedicated device te maken.

    Kan je me de service software mailen , zie PM ?

    dank u
    Christof

  6. #6
    Join Date
    Jul 2011
    Posts
    5

    Default

    To all who might be interested:


    I checked once more with StorkAir and they do not have this in their pipeline.

    So I have started to build a dedicated KNX EIB communication unit for the Stork or StorkAir (also known under brands Rvent, Rensa and several others) heat recovery units for balanced ventillation.

    The module will connect to the RS 232 of the StorkAir

    The supported units will be:
    WHR 930 (or ComfoD 350)
    WHR 930 luxe (or ComfoD 350 luxe)
    WHR 950 (or ComfoD 550)
    WHR 950 Luxe (or ComfoD 550 Luxe)
    active cooling unit for WHR: Artic
    probably also the WHR 960

    Functions and data available will be all functions and data available on the local panel or the confort panel (CC ease) in user mode... plus some other functions which we deem usefull for this type of application.
    Full fucntionality will (obviously) only be possible with the Luxe versions, because they have an additional control board. It is possible that support for the standard versions will be 'as is' = limited, because people willing to integrate this in a KNX system are likely to have the full-featured Luxe version anyway. Let me know if you see a problem with this.

    If you want to be kept informed about the release, just drop me your email address by mail or PM


    Kind regards,
    Christof
    Last edited by cdebackere; July 31st, 2011 at 05:06 PM.

  7. #7
    Join Date
    Oct 2011
    Posts
    2

    Default

    Hi everyone,

    I have found your posts about WHR-930 software and I have a coupe of questions.

    I have almost the same ventilation unit: zehnder comfoair 350
    It seems to be the same as WHR930 by StorkAir

    anyway I would like to create software that will let me to control and monitor my ventilation unit via web interface. So I need any information about communication protocol.

    Furthermore I have no idea how to connect the vent unit to PC. I have in it two pcb boards. One is at the top and the second one is in the front. The one at the top is connected to the one at the front using RS232 via RJ45. The one at the top has RS232 DB9 connector described RS232 to PC. And It also has two other RS232:
    - One is used for connecting room controller
    - The other one is RS232 RJ45.

    When I use the RS 232 to PC the ventilation unit is sending some data all the time and I do not know how to stop it. It looks like that:

    Code:
    Data received: 07 F3 07 F0 00 D2 09 60 40 4D 52 47 0F 28 28 28 95 07 0F 
     Data received: 07 F3 07 F0 00 40 15 00 00 12 E0 00 06 04 84 29 9A 27 00 00 00 00 00 A5 5A 5A A5 00 6A 07 0F 07 F3 07 F0 00 3C 0A 84 16 87 3F 7F 06 00 00 00 E0 B8 07 0F 07 F3 07 F0 00 E0 07 00 00 05 00 05 00 00 9E 07 0F 
     Data received: 07 F3 07 F0 00 3C 0A 84 16 87 3F 7F 06 00 00 00 E0 B8 07 0F 07 F3 07 F0 00 3C 0A 84 16 87 3F 7F 06 00 00 00 E0 B8 07 0F 
     Data received: 07 F3 07 F0 00 E2 06 00 00 00 00 00 02 97 07 0F 
     Data received: 07 F3 07 F0 00 3E 04 84 29 9A 27 5D 07 0F 07 F3 07 F0 00 3C 0A 84 16 87 3F 7F 06 00 00 00 E0 B8 07 0F 
     Data received: 07 F3 07 F0 00 40 15 00 00 12 E0 00 06 04 84 29 9A 27 00 00 00 00 00 A5 5A 5A A5 00 6A 07 0F
    When I use the RS232 RJ45 and try to send something to ventilation unit I have error message on the room controller: No connection.

    Do you have any idea how to stop speaking the ventilation unit while connecting to the RS232 DB9?

  8. #8
    Join Date
    Aug 2004
    Location
    The Netherlands (Norg, near Assen)
    Posts
    625

    Default

    Here is the code (serial driver) I use to receive (and send) the data form the WHR950.

    Code:
    --[[ 
    StorkAir WHR
     
    --]]
    local device = serial.Classes.Simple:New({
        Name = "WHR",
        Description = "Controlling Stork Air WHR950 over RS485.",
        GlobalName = 'WHR',
        LogLevel = 3,
        BaudRate = 9600,
        Parity = 0,
        StopBits = 1,  --changed on 3-1-2009 from 0 to 1
        DataBits = 8,
        FlowControl = 'N',
        IntraCharacterDelay = 0,
        BurstSize = 256,        -- default=256.
        --CallbackType = serial.CB_FIXEDLENGTH,
        --ReceiveFixedLength = 1,
        CallbackType = serial.CB_TERMINATED,
        ReceiveTerminator = serial.hextobyte("070F"),
        NoResponseTimeout = 1000,
        IncompleteResponseTimeout = 1000,
        Initialize = function (self)
            gir.LogMessage(self.Name, 'WHR Communications OK',3)
            self.Status = 'Waiting for WHR commands'..os.date("!%H:%M:%S")
            return serial.Classes.Simple.Initialize (self)
        end,
        ReceiveResponse = function ( self, data, code )       
            if Initialized and math.band(code,serial.RXCHAR)>0 and data and data ~= '' then
       WHRprocess(serial.binarytohex(data),code)
       end
            serial.Classes.Simple.ReceiveResponse (self,data,code)
        end,
    }
    )
    serial.AddDevice (device)
    As you can see is the protocol the same. The packest are terminated by a "070F" sequence and are then processed using the code in the start of this post.


    It looks your unit automatically sends the datapackets continiously. I have to query for the data.
    Hope this helps.
    Geert

  9. #9
    Join Date
    Oct 2011
    Posts
    2

    Default

    Hi,

    The problem is not with that I cannot communicate with the ventilation unit. I can do that if I disconnect my room controller. But I would like to have connected both: the room controller CC Easy and my PC. The problem is that the room controller is talking all the time with the ventilation unit and I do not have time frame to send question from my PC. There are 3 RS232 ports on the communication PCB board in the ventilation unit but all of them are the same com.

    Does anyone knows how to stop the communication with the CC Easy for a while? I can disconnect the CC Easy for about 8 sec without error message on its display. But doing it manually is not the solution. The only reasonable way is to put all transmission through the PC and brake the communication between CC Easy and ventilation unit for 1-2 sec while sending question from the PC.

    Does anyone has better idea?

  10. #10
    Join Date
    Dec 2011
    Posts
    1

    Default

    Hi,
    does anyone have the original windows maintenance program?

    I'm trying to setup my WHR950 R unit and write my own webapp for controlling, and this little app would be REALLY handy.

    Thanks in advance...

Page 1 of 4 123 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •