sw:openhab:examples:heating:3pa

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
sw:openhab:examples:heating:3pa [2023/12/26 17:42] – создано lazygattosw:openhab:examples:heating:3pa [2023/12/26 18:07] (текущий) lazygatto
Строка 5: Строка 5:
 Управлением открытия/закрытия занимается контроллер MegaD, задействованы 2 релейных выхода. Для них созданы соответствующие Items. Управлением открытия/закрытия занимается контроллер MegaD, задействованы 2 релейных выхода. Для них созданы соответствующие Items.
  
-1. Установлен Add-on [[https://www.openhab.org/addons/automation/pidcontroller/|PID Controller]], который соответственно рассчитывает выходное значение в зависимости от температуры уставки и текущей температуры подачи.+1. Установлен Add-on [[https://www.openhab.org/addons/automation/pidcontroller/|PID Controller]], который соответственно рассчитывает выходное значение в зависимости от температуры уставки (''tp_setpoint''и текущей температуры подачи (''tp_flowpipe'') и записывает его в Item ''tp_pid''. Настройки по коэффициентами пока выбраны следующие: P=10, I=0.5, D=80, D-T1=300 
 Код правила для расчета PID: Код правила для расчета PID:
 <sxh> <sxh>
Строка 42: Строка 43:
       itemName: tp_pid       itemName: tp_pid
     type: core.ItemCommandAction     type: core.ItemCommandAction
 +
 +</sxh>
 +
 +Поскольку котел у меня 1-контурный, и в момент переключения котла в режим подогрева ГВС температура в контуре подачи теплого пола неминуемо падает - стоит исключение на запуск этого правила, когда ''boiler_flame'' и ''boiler_status'' активны. Это позволяет несколько снизить лишнее "кручение" клапаном.
 +
 +2. Следующее правило запускается по cron каждые 3 минуты, и в зависимости от текущего значения PID управляет 3-х ходовым клапаном.
 +
 +Код правила управления 3-х ходовым клапаном:
 +<sxh>
 +configuration: {}
 +triggers:
 +  - id: "1"
 +    configuration:
 +      cronExpression: 0 0/3 * * * ? *
 +    type: timer.GenericCronTrigger
 +conditions: []
 +actions:
 +  - inputs: {}
 +    id: "2"
 +    configuration:
 +      type: application/javascript
 +      script: >-
 +        /*
 +
 +
 +        Items to control 3p Actuator
 +
 +        three_way_close - close relay
 +
 +        three_way_open - open relay
 +
 +
 +        */
 +
 +
 +        function rotateActuator (pidValue) {
 +          
 +          var actionTimerCorrection = 2 // Maybe 1 to any reasonable value, decreasing rotation time 
 +          var actionTimerMax = 15000 // milliseconds, maximum 15 sec
 +          var actionTimerMin = 1000 // milliseconds, minimum 1 sec
 +          
 +          console.log('PID: ' + pidValue)
 +          
 +          var actionItem3pActuator = null
 +          var action = null
 +          var actionTimer = 0
 +          
 +          action = (pidValue > 0) ? 'open' : 'close';
 +          
 +          action3pActuator = items.getItem('three_way_' + action)
 +          actionTimer = Math.round( Math.abs( pidValue ) / actionTimerCorrection ) * 500
 +
 +          // Limit to actionTimerMax if it more
 +          actionTimer = (actionTimer > actionTimerMax) ? actionTimerMax : actionTimer;
 +          
 +          if (actionTimer >= actionTimerMin) 
 +          {
 +            console.log ('Actuator action: ' + action3pActuator.name + ' for ' + actionTimer + ' (' + actionTimer/1000 + ' sec)')
 +            
 +            console.info(action3pActuator.name + ' send command ON')
 +            action3pActuator.sendCommand('ON')
 +            
 +            setTimeout(() => {
 +              console.info(action3pActuator.name + ' send command OFF')
 +              action3pActuator.sendCommand('OFF')
 +            }, actionTimer);  
 +          
 +          } 
 +          else 
 +          {
 +            console.info('actionTimer: ' + actionTimer/1000 + ' < ' + actionTimerMin/1000 + ' sec - nothing to do with 3p actuator'   
 +          }
 +
 +        }
 +
 +
 +        rotateActuator(items.tp_pid.state)
 +    type: script.ScriptAction
 +
 +</sxh>
 +
 +Знать текущее положение клапана, насколько он открыт или закрыт в реальности абсолютно не нужно. В крайних положениях он в любом случае отключается по внутри установленным реле.\\
 +Но интересно же! :)
 +
 +Поэтому попробовал реализовать и такую вещь, как отображение текущего уровня открытия 3-х ходового клапана.
 +
 +Логика следующая. Есть отдельный Item (''tp_3pA_status''), в который будет писаться уровень открытия клапана. \\
 +И отдельное правило, которое отслеживает работу реле открытия/закрытия клапана, считает время, на которое соответствующее реле было открыто или закрыто, и обновляет собственно статус в нужный нам Item.
 +
 +Экспериментальным путем было установлено, что полное время открытия/закрытия клапана составляет в моем случае 127 сек. (при заявленных 120 сек. производителем). Именно это значение используется в дальнейшем.
 +
 +Код правила для обновления статуса клапана:
 +<sxh>
 +configuration: {}
 +triggers:
 +  - id: "1"
 +    configuration:
 +      itemName: three_way_close
 +    type: core.ItemStateChangeTrigger
 +  - id: "2"
 +    configuration:
 +      itemName: three_way_open
 +    type: core.ItemStateChangeTrigger
 +conditions: []
 +actions:
 +  - inputs: {}
 +    id: "3"
 +    configuration:
 +      type: application/javascript
 +      script: >-
 +        
 +        var maxRotationTime = 127000
 +
 +
 +        var current3pAState = items.tp_3pA_status.state
 +
 +        var new3pAState = null
 +
 +
 +        var cacheId = 'tp_3pAStatus_Id'
 +
 +        var processDuration = 0
 +
 +
 +        var stor = cache.private.get(cacheId, () => ({
 +          'cacheId': cacheId,
 +          'openStarts': null,
 +          'closeStarts': null,
 +        }));
 +
 +
 +        function resetStorage(stor) {
 +          stor.openStarts = null;
 +          stor.closeStarts = null;
 +          cache.private.put(stor.cacheId, stor);
 +        }
 +
 +
 +        function startMoving(stor, direction) {
 +          stor[direction + 'Starts'] = Date.now();
 +          cache.private.put(stor.cacheId, stor);
 +          console.log('3pA ' + direction + ' starts at: ' + stor[direction + 'Starts'])
 +        }
 +
 +
 +        function stopMoving(stor, direction) {
 +          
 +          processDuration = Date.now() - stor[direction + 'Starts'];
 +          
 +          console.log('3pA ' + direction + ' stopped at ' +  Date.now() + ', start was at: ' + stor[direction + 'Starts'] + ', Dur:' + processDuration)
 +
 +          rotationPercent = processDuration / maxRotationTime;
 +          console.log('Rotation was at: ' + rotationPercent * 100 + '%')
 +         
 +          new3pAState = Number.parseFloat(current3pAState) + ((direction == 'open') ? + Number.parseFloat(rotationPercent) : - Number.parseFloat(rotationPercent))
 +          
 +          console.log('New status is set to: ' + (new3pAState) * 100 + '%')
 +
 +          items.tp_3pA_status.postUpdate(new3pAState)
 +          resetStorage(stor)  
 +        }
 +
 +
 +        var direction = null
 +
 +
 +        switch(event.itemName) {
 +          case 'three_way_open':
 +            direction = 'open'
 +            if (event.itemState.toString() == 'ON') {
 +              startMoving(stor, direction)
 +            } else {
 +              stopMoving(stor, direction)
 +            }
 +            break
 +
 +          case 'three_way_close':
 +            direction = 'close'
 +            if (event.itemState.toString() == 'ON') {
 +              startMoving(stor, direction)
 +            } else {
 +              stopMoving(stor, direction)
 +            }
 +            break
 +
 +          default:
 +            console.error('We not supposed to be here. Something wrong')
 +            break
 +        }
 +    type: script.ScriptAction
 +
 +</sxh>
 +
 +4. Ну и в завершение есть еще небольшое правило, для сброса статуса уровня открытия клапана. Оно вращает клапан до крайнего положения закрытия, и обновляет статус в ноль. Ну а на время своей работы отключает другие правила, которые могут попытаться как то с клапаном работать.
 +
 +<sxh>
 +configuration: {}
 +triggers: []
 +conditions: []
 +actions:
 +  - inputs: {}
 +    id: "1"
 +    configuration:
 +      type: application/javascript
 +      script: >+
 +        console.log("=== Resetting 3 point actuator Status ===")
 +
 +
 +        var maxRotationTime = 127000 // 127 sec
 +
 +
 +        var rulesToDisable = [
 +          'pidTest',
 +          'update3pAStatus',
 +          'rotate_3p_actuator_with_pid',
 +        ]
 +
 +
 +        // Disable rules
 +
 +        console.log('Disabling needed rules, to prevent their runnig:')
 +
 +        rulesToDisable.forEach((rule) => {
 +          rules.setEnabled(rule, false);
 +          console.log('Rule ' + rule + ' disabled.')
 +        });
 +
 +
 +        items.three_way_close.sendCommand('ON')
 +
 +        console.log('Starting closing 3pA for ' + Math.round(maxRotationTime/1000) + ' sec.')
 +
 +
 +        setTimeout(() => {
 +          items.three_way_close.sendCommand('OFF')
 +          console.log('Closing 3pA done')
 +          items.tp_3pA_status.postUpdate(0)
 +          console.log('Status of 3pA updated to 0')
 +          // Enable rules
 +          console.log('Resetting complete. Enabling rules:')
 +          rulesToDisable.forEach((rule) => {
 +            rules.setEnabled(rule, true);
 +            console.log('Rule ' + rule + ' enabled.')
 +          });
 +        }, maxRotationTime);
 +
 +    type: script.ScriptAction
  
 </sxh> </sxh>
  • sw/openhab/examples/heating/3pa.1703601729.txt.gz
  • Последнее изменение: 2023/12/26 17:42
  • lazygatto