Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!

Automatisk styring av Systemair SAVE ventilator


strips

Anbefalte innlegg

Akkurat ferdig testet et script for å styre vår Systemair SAVE VTR 300 via Modbus. Det er nok tråder om Modbus her at jeg gidder å snakke om det nå :)

 

Scriptet leser to Netatmo innemoduler sin Co2, temp og relativ fuktighet. Ut i fra disse verdiene så settes aggregatet i auto som standard, crowded (party) eller refresh (boost) basert på noen grensetall.

 

Takk til @Moskus og  @Hillmar for formel for absolutt fuktighet

 

 

Forenklede regler

  • Brannalarm: TODO
  • Hvis trykkvakt eller spesialmodus (kjøkkenhette, vedovn, sentralstøvsuger) er aktivert skal vi ikke endre noe.
  • Hvis stue eller bad har for høy Co2 så øker luftmegden først til Crowded så Boost.
  • Hvis bad har høyere absolutt fuktighet en stuen med en viss margin så økes luftmengden til Boost
  • Hvis ingen av regelene over treffer eller Co2 er under en terskel så sett til Auto.

 

For å bruke scriptet må du endre alle variablene i toppen som begynner med dev.

 

Det er 3 regel-blokker lengre nede som dekker mitt behov og kan dupliseres for flere rom eller fjernes hvis man ikke har nok sensorer.

 

Class VentilatorControl
    Public Sub Main(ByVal Parms As Object)

        Dim Debug As Boolean = True
        Dim logName As String = "VentilatorControl"

        Console.WriteLine("Started: " & logName)
        If Debug Then hs.WriteLog(logName, "Started")


        Dim fireAlarm As Boolean = False ' for the future when I get a fire alarm integrated

        Dim devBath1_RH As Integer = 820 ' netatmo bad innemodul
        Dim devBath1_T As Integer = 817 ' netatmo bad innemodul
        Dim devBath1_Co2 As Integer = 821 ' netatmo bad innemodul
        Dim devLivingRoom1_RH As Integer = 788 ' netatmo stue hovedmodul
        Dim devLivingRoom1_T As Integer = 783 ' netatmo stue hovedmodul
        Dim devLivingRoom1_Co2 As Integer = 787 ' netatmo stue hovedmodul
        Dim devVentModeGet As Integer = 774 ' systemair Modbus
        Dim devVentModeSet As Integer = 773 ' systemair Modbus

        Dim valueLivingRoom1_T As Double = hs.DeviceValueEx(devLivingRoom1_T)
        Dim valueLivingRoom1_Co2 As Integer = hs.DeviceValue(devLivingRoom1_Co2)
        Dim valueLivingRoom1_RH As Double = hs.DeviceValueEx(devLivingRoom1_RH)
        Dim valueLivingRoom1_AH As Double = AbsHumidity(valueLivingRoom1_RH, valueLivingRoom1_T)
        Dim valueBath1_T As Double = hs.DeviceValueEx(devBath1_T)
        Dim valueBath1_Co2 As Integer = hs.DeviceValue(devBath1_Co2)
        Dim valueBath1_RH As Double = hs.DeviceValueEx(devBath1_RH)
        Dim valueBath1_AH As Double = AbsHumidity(valueBath1_RH, valueBath1_T)
        Dim humidDeltaBath1 As Double = Math.Round(valueBath1_AH / valueLivingRoom1_AH, 2)
        Dim valueVentModeGet As Integer = hs.DeviceValue(devVentModeGet)

        Dim ventModeGetCodeArray(12) As String
        ventModeGetCodeArray(0) = "Auto"
        ventModeGetCodeArray(1) = "Manual"
        ventModeGetCodeArray(2) = "Crowded"
        ventModeGetCodeArray(3) = "Refresh"
        ventModeGetCodeArray(4) = "Fireplace"
        ventModeGetCodeArray(5) = "Away"
        ventModeGetCodeArray(6) = "Holiday"
        ventModeGetCodeArray(7) = "Cooker Hood"
        ventModeGetCodeArray(8) = "Vacuum Cleaner"
        ventModeGetCodeArray(9) = "CDI1"
        ventModeGetCodeArray(10) = "CDI2"
        ventModeGetCodeArray(11) = "CDI3"
        ventModeGetCodeArray(12) = "PressureGuard"

        Dim ventModeSetCodeArray(7) As String
        ventModeSetCodeArray(0) = "None"
        ventModeSetCodeArray(1) = "Auto"
        ventModeSetCodeArray(2) = "Manual"
        ventModeSetCodeArray(3) = "Crowded"
        ventModeSetCodeArray(4) = "Refresh"
        ventModeSetCodeArray(5) = "Fireplace"
        ventModeSetCodeArray(6) = "Away"
        ventModeSetCodeArray(7) = "Holiday"

        ' Co2 threshold levels have a severity of 3 levels
        Dim co2ThresholdNormal As Integer = 550 ' less than
        Dim co2ThresholdHigh As Integer = 700 ' higher than
        Dim co2ThresholdMax As Integer = 900 ' higher than

        ' relative humididy threshold levels have a severity of 2 levels
        Dim humidDeltaThresholdNormal As Double = 1.1 ' less than
        Dim humidDeltaThresholdHigh As Double = 1.4 ' hihger than

        If Debug Then hs.WriteLog(logName, "valueLivingRoom1_T: " & valueLivingRoom1_T)
        If Debug Then hs.WriteLog(logName, "valueLivingRoom1_Co2: " & valueLivingRoom1_Co2)
        If Debug Then hs.WriteLog(logName, "valueLivingRoom1_RH: " & valueLivingRoom1_RH)
        If Debug Then hs.WriteLog(logName, "valueLivingRoom1_AH: " & valueLivingRoom1_AH)
        If Debug Then hs.WriteLog(logName, "valueBath1_T: " & valueBath1_T)
        If Debug Then hs.WriteLog(logName, "valueBath1_Co2: " & valueBath1_Co2)
        If Debug Then hs.WriteLog(logName, "valueBath1_RH: " & valueBath1_RH)
        If Debug Then hs.WriteLog(logName, "valueBath1_AH: " & valueBath1_AH)
        If Debug Then hs.WriteLog(logName, "humidDeltaBath1: " & humidDeltaBath1)
        If Debug Then hs.WriteLog(logName, "Current Ventilator Mode: " & ventModeGetCodeArray(valueVentModeGet))


        If Debug Then hs.WriteLog(logName, "co2ThresholdNormal: " & co2ThresholdNormal)
        If Debug Then hs.WriteLog(logName, "co2ThresholdHigh: " & co2ThresholdHigh)
        If Debug Then hs.WriteLog(logName, "co2ThresholdMax: " & co2ThresholdMax)

        ' assign index from ventModeSetCodeArray
        Dim normalVentilatorGetMode As Integer = Array.IndexOf(ventModeGetCodeArray, "Auto")
        Dim normalVentilatorSetMode As Integer = Array.IndexOf(ventModeSetCodeArray, "Auto")
        Dim highVentilatorGetMode As Integer = Array.IndexOf(ventModeGetCodeArray, "Crowded")
        Dim highVentilatorSetMode As Integer = Array.IndexOf(ventModeSetCodeArray, "Crowded")
        Dim maxVentilatorGetMode As Integer = Array.IndexOf(ventModeGetCodeArray, "Refresh")
        Dim maxVentilatorSetMode As Integer = Array.IndexOf(ventModeSetCodeArray, "Refresh")
        Dim ventilatorSetLevel As Integer
        Dim ventilatorSetModeArray(3) As String
        ventilatorSetModeArray(1) = "Auto"
        ventilatorSetModeArray(2) = "Crowded"
        ventilatorSetModeArray(3) = "Refresh"


        If (fireAlarm) Then
            ' If fire alarm is true we stop ventilator or set it to minimum
            ' TODO identify best setting to disable the ventilator
            ' set mode manual
            ' set manual fan level to 
            hs.WriteLog(logName, "Firealarm not implemented. Ventilator is in " & ventModeGetCodeArray(valueVentModeGet) & " mode.")

        ElseIf (valueVentModeGet >= Array.IndexOf(ventModeGetCodeArray, "Cooker Hood")) Then
            ' If ventilator is in get mode 7 (Cooker Hood) or higher we do nothing because the system is not in balance
            hs.WriteLog(logName, "Ventilator is in " & ventModeGetCodeArray(valueVentModeGet) & " mode, we do nothing!")

        Else
            ' Always start with normal as default level
            ventilatorSetLevel = 1

            ' Co2 in living room 1
            If (valueLivingRoom1_Co2 > co2ThresholdMax) And (ventilatorSetLevel < 3) Then
                ventilatorSetLevel = 3
                If Debug Then hs.WriteLog(logName, "If (valueLivingRoom1_Co2 > co2ThresholdMax) And (ventilatorSetLevel < 3) Then, setting ventilatorSetMode to " & ventilatorSetLevel)
            ElseIf (valueLivingRoom1_Co2 > co2ThresholdHigh) And (ventilatorSetLevel < 2) Then
                ventilatorSetLevel = 2
                If Debug Then hs.WriteLog(logName, "ElseIf (valueLivingRoom1_Co2 > co2ThresholdHigh) And (ventilatorSetLevel < 2) Then, setting ventilatorSetMode to " & ventilatorSetLevel)
            ElseIf (valueLivingRoom1_Co2 <= co2ThresholdNormal) And (ventilatorSetLevel = 1) Then
                If Debug Then hs.WriteLog(logName, "ElseIf (valueLivingRoom1_Co2 <= co2ThresholdNormal) And (ventilatorSetLevel = 1) Then, ventilatorSetLevel = 1")
            End If

            ' Co2 in bath 1
            If (valueBath1_Co2 > co2ThresholdMax) And (ventilatorSetLevel < 3) Then
                ventilatorSetLevel = 3
                If Debug Then hs.WriteLog(logName, "If (valueBath1_Co2 > co2ThresholdMax) And (ventilatorSetLevel < 3) Then, setting ventilatorSetMode to " & ventilatorSetLevel)
            ElseIf (valueBath1_Co2 > co2ThresholdHigh) And (ventilatorSetLevel < 2) Then
                ventilatorSetLevel = 2
                If Debug Then hs.WriteLog(logName, "ElseIf (valueBath1_Co2 > co2ThresholdHigh) And (ventilatorSetLevel < 2) Then, setting ventilatorSetMode to " & ventilatorSetLevel)
            ElseIf (valueBath1_Co2 <= co2ThresholdNormal) And (ventilatorSetLevel = 1) Then
                If Debug Then hs.WriteLog(logName, "ElseIf (valueBath1_Co2 <= co2ThresholdNormal) And (ventilatorSetLevel = 1) Then, ventilatorSetLevel = 1")
            End If

            ' humidity in bath 1
            If (humidDeltaBath1 > humidDeltaThresholdHigh) And (ventilatorSetLevel < 3) Then
                ventilatorSetLevel = 3
                If Debug Then hs.WriteLog(logName, "If (humidDeltaBath1 > humidDeltaThresholdHigh) And (ventilatorSetLevel < 3) Then, setting ventilatorSetMode to " & ventilatorSetLevel)
            ElseIf (humidDeltaBath1 <= humidDeltaThresholdNormal) And (ventilatorSetLevel = 1) Then
                If Debug Then hs.WriteLog(logName, "ElseIf (humidDeltaBath1 <= humidDeltaThresholdNormal) And (ventilatorSetLevel = 1) Then, ventilatorSetLevel = 1")
            End If


            ' If the current ventilator mode is at the same mode/level we want to set then we do not have to do anything
            If (ventModeGetCodeArray(valueVentModeGet) = ventilatorSetModeArray(ventilatorSetLevel)) Then
                If Debug Then hs.WriteLog(logName, "ventModeGetCodeArray(valueVentModeGet) = " & ventModeGetCodeArray(valueVentModeGet))
                If Debug Then hs.WriteLog(logName, "ventilatorSetModeArray(ventilatorSetLevel) = " & ventilatorSetModeArray(ventilatorSetLevel))
                If Debug Then hs.WriteLog(logName, "If (ventModeGetCodeArray(valueVentModeGet) [" & ventModeGetCodeArray(valueVentModeGet) & "] = ventilatorSetModeArray(ventilatorSetLevel)[" & ventilatorSetModeArray(ventilatorSetLevel) & "]  ) Then, no changes in ventilatorSetMode")
            Else
                ' Set ventilator device devVentModeSet to index of ventModeSetCodeArray where value is ventilatorSetLevel translated thru ventModeSetCodeArray
                If Debug Then hs.WriteLog(logName, "If Not (ventModeGetCodeArray(valueVentModeGet) [" & ventModeGetCodeArray(valueVentModeGet) & "] = ventilatorSetModeArray(ventilatorSetLevel)[" & ventilatorSetModeArray(ventilatorSetLevel) & "]  ) Then, set ventilator to " & ventilatorSetModeArray(ventilatorSetLevel))
                If Debug Then hs.WriteLog(logName, "ventilatorSetLevel = " & ventilatorSetLevel)
                If Debug Then hs.WriteLog(logName, "ventilatorSetModeArray(ventilatorSetLevel) = " & ventilatorSetModeArray(ventilatorSetLevel))
                If Debug Then hs.WriteLog(logName, "before set devVentModeSet to " & Array.IndexOf(ventModeSetCodeArray, ventilatorSetModeArray(ventilatorSetLevel)))

                If Debug Then hs.WriteLog(logName, "hs.CAPIControlHandler(hs.CAPIGetSingleControl(" & devVentModeSet & ", True, " & ventilatorSetModeArray(ventilatorSetLevel) & ", False, False))")
                hs.CAPIControlHandler(hs.CAPIGetSingleControl(devVentModeSet, True, ventilatorSetModeArray(ventilatorSetLevel), False, False))
                hs.WriteLog(logName, "set devVentModeSet to " & Array.IndexOf(ventModeSetCodeArray, ventilatorSetModeArray(ventilatorSetLevel)))

            End If

        End If

    End Sub

    Function AbsHumidity(ByVal relHumidity As Double, ByVal temp As Double) As Double
        ' Formula found here:
        ' https://www.hjemmeautomasjon.no/forums/topic/5896-konvertere-fra-relativ-til-absolutt-luftfuktighet/?do=findComment&comment=68448
        AbsHumidity = Math.Round(6.112 * Math.E ^ ((17.67 * temp) / (temp + 243.5)) * relHumidity * 2.1674 / (273.15 + temp), 2)
    End Function

End Class

 

Lenke til kommentar
Del på andre sider

Kan jeg komme med et forbedringsforslag? One-line IF er utmerket for kun én linje, men blir veldig uoversiktelig når den skal dekke flere (samt at det teknisk sett krever mer regnekraft, selv om det er ubetydelig nå om dagen).

 

Jeg hadde mao. skrevet den siste IF-setningen slik:

        ' If the current ventilator mode is at the same mode/level we want to set then we do not have to do anything
        If (ventModeGetCodeArray(valueVentModeGet) = ventilatorSetModeArray(ventilatorSetLevel)) Then
            If Debug Then
                hs.WriteLog(logName, "ventModeGetCodeArray(valueVentModeGet) = " & ventModeGetCodeArray(valueVentModeGet))
                hs.WriteLog(logName, "ventilatorSetModeArray(ventilatorSetLevel) = " & ventilatorSetModeArray(ventilatorSetLevel))
                hs.WriteLog(logName, "If (ventModeGetCodeArray(valueVentModeGet) [" & ventModeGetCodeArray(valueVentModeGet) & "] = ventilatorSetModeArray(ventilatorSetLevel)[" & ventilatorSetModeArray(ventilatorSetLevel) & "]  ) Then, no changes in ventilatorSetMode")
            End If
        Else
            ' Set ventilator device devVentModeSet to index of ventModeSetCodeArray where value is ventilatorSetLevel translated thru ventModeSetCodeArray
            If Debug Then
                hs.WriteLog(logName, "If Not (ventModeGetCodeArray(valueVentModeGet) [" & ventModeGetCodeArray(valueVentModeGet) & "] = ventilatorSetModeArray(ventilatorSetLevel)[" & ventilatorSetModeArray(ventilatorSetLevel) & "]  ) Then, set ventilator to " & ventilatorSetModeArray(ventilatorSetLevel))
                hs.WriteLog(logName, "ventilatorSetLevel = " & ventilatorSetLevel)
                hs.WriteLog(logName, "ventilatorSetModeArray(ventilatorSetLevel) = " & ventilatorSetModeArray(ventilatorSetLevel))
                hs.WriteLog(logName, "before set devVentModeSet to " & Array.IndexOf(ventModeSetCodeArray, ventilatorSetModeArray(ventilatorSetLevel)))

                hs.WriteLog(logName, "hs.CAPIControlHandler(hs.CAPIGetSingleControl(" & devVentModeSet & ", True, " & ventilatorSetModeArray(ventilatorSetLevel) & ", False, False))")
            End If

            hs.CAPIControlHandler(hs.CAPIGetSingleControl(devVentModeSet, True, ventilatorSetModeArray(ventilatorSetLevel), False, False))
            hs.WriteLog(logName, "set devVentModeSet to " & Array.IndexOf(ventModeSetCodeArray, ventilatorSetModeArray(ventilatorSetLevel)))
        End If

 

 

Det samme med linjene over:

    If Debug Then
        hs.WriteLog(logName, "valueLivingRoom1_T: " & valueLivingRoom1_T)
        hs.WriteLog(logName, "valueLivingRoom1_Co2: " & valueLivingRoom1_Co2)
        hs.WriteLog(logName, "valueLivingRoom1_RH: " & valueLivingRoom1_RH)
        hs.WriteLog(logName, "valueLivingRoom1_AH: " & valueLivingRoom1_AH)
        hs.WriteLog(logName, "valueBath1_T: " & valueBath1_T)
        hs.WriteLog(logName, "valueBath1_Co2: " & valueBath1_Co2)
        hs.WriteLog(logName, "valueBath1_RH: " & valueBath1_RH)
        hs.WriteLog(logName, "valueBath1_AH: " & valueBath1_AH)
        hs.WriteLog(logName, "humidDeltaBath1: " & humidDeltaBath1)
        hs.WriteLog(logName, "Current Ventilator Mode: " & ventModeGetCodeArray(valueVentModeGet))


        hs.WriteLog(logName, "co2ThresholdNormal: " & co2ThresholdNormal)
        hs.WriteLog(logName, "co2ThresholdHigh: " & co2ThresholdHigh)
        hs.WriteLog(logName, "co2ThresholdMax: " & co2ThresholdMax)
    End If

 

Lenke til kommentar
Del på andre sider

Hvis du skal ha det enda mer oversiktlig så pakker du slike ting inn i sub rutiner med godt beskrivende navn

 

	If (ventModeGetCodeArray(valueVentModeGet) = ventilatorSetModeArray(ventilatorSetLevel)) Then
		WriteDebugForVentilatorSetModeArray(Debug)
	Else
            ' Set ventilator device devVentModeSet to index of ventModeSetCodeArray where value is ventilatorSetLevel translated thru ventModeSetCodeArray
		WriteDebugForTheOtherStuff(Debug)   
		' Det underliggende kunne også trekkes ut som en egen godt beskrevet sub
		hs.CAPIControlHandler(hs.CAPIGetSingleControl(devVentModeSet, True, ventilatorSetModeArray(ventilatorSetLevel), False, False))
		hs.WriteLog(logName, "set devVentModeSet to " & Array.IndexOf(ventModeSetCodeArray, ventilatorSetModeArray(ventilatorSetLevel)))
	End If
..
..
..
Sub WriteDebugForVentilatorSetModeArray(Debug as bool)
	If Debug Then
    	hs.WriteLog(logName, "ventModeGetCodeArray(valueVentModeGet) = " & ventModeGetCodeArray(valueVentModeGet))
    	hs.WriteLog(logName, "ventilatorSetModeArray(ventilatorSetLevel) = " & ventilatorSetModeArray(ventilatorSetLevel))
    	hs.WriteLog(logName, "If (ventModeGetCodeArray(valueVentModeGet) [" & ventModeGetCodeArray(valueVentModeGet) & "] = 		ventilatorSetModeArray(ventilatorSetLevel)[" & ventilatorSetModeArray(ventilatorSetLevel) & "]  ) Then, no changes in ventilatorSetMode")
	End If
End Sub

Sub WriteDebugForTheOtherStuff(Debug as bool)
	If Debug Then
    	hs.WriteLog(logName, "If Not (ventModeGetCodeArray(valueVentModeGet) [" & ventModeGetCodeArray(valueVentModeGet) & "] = ventilatorSetModeArray(ventilatorSetLevel)[" & ventilatorSetModeArray(ventilatorSetLevel) & "]  ) Then, set ventilator to " & ventilatorSetModeArray(ventilatorSetLevel))
    	hs.WriteLog(logName, "ventilatorSetLevel = " & ventilatorSetLevel)
    	hs.WriteLog(logName, "ventilatorSetModeArray(ventilatorSetLevel) = " & ventilatorSetModeArray(ventilatorSetLevel))
    	hs.WriteLog(logName, "before set devVentModeSet to " & Array.IndexOf(ventModeSetCodeArray, ventilatorSetModeArray(ventilatorSetLevel)))
    	hs.WriteLog(logName, "hs.CAPIControlHandler(hs.CAPIGetSingleControl(" & devVentModeSet & ", True, " & ventilatorSetModeArray(ventilatorSetLevel) & ", False, False))")
	End If
End Sub

 

Lenke til kommentar
Del på andre sider

Takker for tips @Moskus og @Guahtdim

 

Enig at det er penere og kjappere med en if (debug) men etter hvet som de vokste ble det sånn. Så er det veldig praktisk å bare lime inn en linje og endre teksten. Så det er med overlegg one-linere.

 

Mulig det hadde blitt mer oversiktlig med sub-rutiner. Men for et så lite script er det lite vits. VB.Net er kun noe jeg tar i fordi jeg må. Skulle helst gjort dette i C# og øvd meg på det men er så få eksempler på C#-kode for Homeseer.

 

Ellers hjelper det å bruke Visual Studio med tenScripting for debugging.

 

 

Lenke til kommentar
Del på andre sider

C# script motoren i HomeSeer er så dårlig så det er lettere å gjøre ting i vbscript. 

Jeg prøvde lenge med C# script, men ga etterhvert opp. Etter å ha gravd litt så fant jeg ut at de hadde implementert en veldig gammel motor. Og siden de ikke bruker den selv så tviler jeg på at de stresser så mye over at det er kronglete.

 

Det gjør litt vondt de gangene jeg må inn og scripte, men det gjør enda mer vondt å prøve å få det til i CS-Script (https://www.cs-script.net/)

Endret av Guahtdim
  • Like 1
Lenke til kommentar
Del på andre sider

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.