Adding a PIR sensor to an Arlec Smart LED Strip

I built a shed on Australia Day.

Actually, I built two of them over the Australia Day Long Weekend. I bought them from easyshed.com.au, and they were pretty nifty. Specifically, I bought a couple of the off the wall sheds, to attach them to the wall of my garage. There’s already a concrete path there that I was able to use as the floor.

One of the sheds is longer than the others, and is used for storage of tools. Mostly I need to get stuff during the day, but sometimes at night I may need to access something from in there. So, I bought a 2m Grid Connect LED Strip Light. It’s colour changing, but I’m not really that fussed about the colours: this one has a Warm White LED too, so that’s better than trying to twiddle the colours to get the right temperature.

Being Grid Connect, it’s really Tuya, which means it’s flashable. So I did. I’ve got a nice esphome firmware on there, which hooks it up to HomeKit via my MQTT bridge.

I wasn’t really able to get the colour parts working correctly, so I just disabled those pins, and use the light in monochromatic mode.

However, being the tinkerer I am, I opened it up to have a look inside. It’s got one of the standard Tuya mini-boards, in fact a TYWE3S.

This exposes a bunch of pins, most of which were in use:

  • GPIO 0: (Used during boot)
  • GPIO 2: UART0 (TX)
  • GPIO 4: Red LED channel
  • GPIO 5: Warm White LED channel
  • GPIO 12: Green LED channel
  • GPIO 13: unused
  • GPIO 14: Blue LED channel
  • GPIO 15: (Used during boot)
  • GPIO 16: unused

Because the LED strip runs at 12V, I was able to use this to power a PIR sensor, which I then hooked up to GPIO 13. I also tried to connect a DS18B20 temperature sensor to GPIO 16, but was not able to get it to be recognised. From the page linked above, perhaps I needed a pull-up resistor, however, I didn’t really need a temperature sensor.

Having a PIR sensor on the LED strip is worthwhile, however. Otherwise, you’d need to manually turn the lights on when going into the shed.

Having a sensor light is fantastic, but at times you might want the light to stay on, even when it does not detect motion. To achieve this, I have a global variable manual_override, that is set when the light is turned on “manually” (using HomeKit, as there is no physical switch). When this variable is set, the light will not turn off when motion is no longer detected.

I also found it was simpler to have the motion detector (binary_sensor in esphome) have a “delayed off” filter for the period I wanted the light to stay on for, rather than try to manage that in conjunction with the manual override.

The full YAML follows:

esphome:
  name: $device_name
  platform: ESP8266
  board: esp01_1m
  on_loop:
    then:
      - if:
          condition:
            not:
              mqtt.connected:
          then:
            - globals.set:
                id: has_connected_to_mqtt
                value: 'false'

globals:
  - id: has_connected_to_mqtt
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: manual_override
    type: bool
    restore_value: no
    initial_value: 'false'

light:
  - platform: monochromatic
    name: "White"
    id: white
    output: white_channel
    restore_mode: ALWAYS_OFF
    default_transition_length: 0.25s

output:
  - platform: esp8266_pwm
    pin:
      number: GPIO5
    id: white_channel
    inverted: False

sensor:
  - platform: wifi_signal
    name: "WiFi signal sensor"
    update_interval: 5min

binary_sensor:
  - platform: gpio
    pin: GPIO13
    name: "PIR Sensor"
    device_class: motion
    id: pir
    filters:
      - delayed_off: 15s
    on_press:
      then:
        - mqtt.publish:
            topic: HomeKit/${device_name}/MotionSensor/MotionDetected
            payload: "1"
        - if:
            condition:
              light.is_off: white
            then:
              - light.turn_on: white
              - mqtt.publish:
                  topic: HomeKit/${device_name}/Lightbulb/On
                  payload: "1"
    on_release:
      - mqtt.publish:
          topic: HomeKit/${device_name}/MotionSensor/MotionDetected
          payload: "0"
      - if:
          condition:
            lambda: 'return id(manual_override);'
          then:
            - logger.log: "Manual override prevents auto off."
          else:
            - logger.log: "Turning off after motion delay."
            - if:
                condition:
                  - light.is_on: white
                then:
                  - light.turn_off: white
                  - mqtt.publish:
                      topic: HomeKit/${device_name}/Lightbulb/On
                      payload: "0"

ota:

logger:

mqtt:
  broker: "mqtt.lan"
  discovery: false
  topic_prefix: esphome/${device_name}
  on_message:
    - topic: HomeKit/${device_name}/Lightbulb/Brightness
      then:
        - logger.log: "Brightness message"
        - globals.set:
            id: manual_override
            value: 'true'
        - light.turn_on:
            id: white
            brightness: !lambda "return atof(x.c_str()) / 100;"
        - globals.set:
            id: has_connected_to_mqtt
            value: 'true'

    - topic: HomeKit/${device_name}/Lightbulb/On
      payload: "1"
      then:
        - logger.log: "Turn on message"
        - if:
            condition:
              and:
                - binary_sensor.is_off: pir
                - lambda: "return id(has_connected_to_mqtt);"
            then:
              - globals.set:
                  id: manual_override
                  value: 'true'
              - logger.log: "Manual override enabled"
            else:
              - globals.set:
                  id: manual_override
                  value: 'false'
              - logger.log: "Manual override disabled"
        - light.turn_on:
            id: white
        - globals.set:
            id: has_connected_to_mqtt
            value: 'true'
    - topic: HomeKit/${device_name}/Lightbulb/On
      payload: "0"
      then:
        - logger.log: "Turn off message"
        - if:
            condition:
              lambda: 'return id(has_connected_to_mqtt);'
            then:
              - light.turn_off:
                  id: white
              - globals.set:
                  id: manual_override
                  value: 'false'
              - logger.log: "Manual override disabled"
        - globals.set:
            id: has_connected_to_mqtt
            value: 'true'

  birth_message:
    topic: HomeKit/${device_name}/Lightbulb/On
    payload: "1"
  will_message:
    topic: HomeKit/${device_name}/Lightbulb/On
    payload: "0"

There’s also some logic in there to prevent the light turning off and then back on when it first connects to the MQTT broker and is already turned on.

Arlec Powerboard esphome

I bought one of the Grid Connect powerboards from Bunnings last week, and flashed it with a custom firmware.

The model I bought was the PB89HA, which is the one with 5 sockets (one of which is not switchable).

The button is on GPIO3, and the LED is an inverted GPIO1.

The four relays are on GPIO5, GPIO4, GPIO13 and GPIO12, starting with the one closest to the button.

Since there is only one button, and four switchable outlets, I had to come up with a mechanism for controlling all of them. I ended up (after playing around with single-through-quadruple click) with a single click for toggling the first relay (nearest the button). Then, a medium (between 1 and 2 second) press turns all relays off, and a long (greater than 2 second) press turns them all on.

This is not really ideal, as there is no way to toggle just relay 2-4 without using some sort of external control - which goes against my ethos with respect to smart home.

Having said that, I’m not actually sure how I’m going to use this board…I don’t really have a bunch of things that are potentially close together that need individual control. I guess I could have it turn off everything in the entertainment unit except the PVR - that might be a way to save power overnight. I’d want the button more accessible than the powerboard that currently controls them though.

Anyway, the base YAML file follows - be aware that this does not include wifi, and would need to be included in an actual config file (with a device name defined).

esphome:
  name: $device_name
  platform: ESP8266
  board: esp01_1m
  on_boot:
    - light.turn_on:
        id: led
        brightness: 20%

binary_sensor:
  - platform: status
    name: "Status"

  - platform: gpio
    pin:
      number: GPIO3
      inverted: true
      mode: INPUT_PULLUP
    name: button
    on_multi_click:
      - timing:
        - ON for at least 1s
        - OFF for at least 0.2s
        then:
          - switch.turn_off: relay_0
          - switch.turn_off: relay_1
          - switch.turn_off: relay_2
          - switch.turn_off: relay_3

      - timing:
        - ON for at least 2s
        - OFF for at least 0.2s
        then:
          - switch.turn_on: relay_0
          - switch.turn_on: relay_1
          - switch.turn_on: relay_2
          - switch.turn_on: relay_3

      - timing:
        - ON for at most 0.5s
        - OFF for at least 0.2s
        then:
          - switch.toggle: relay_0

switch:
  - platform: gpio
    id: relay_0
    pin: GPIO5
    on_turn_on:
      - mqtt.publish:
          topic: HomeKit/${device_name}/Outlet/0/On
          retain: ON
          payload: 1
    on_turn_off:
      - mqtt.publish:
         topic: HomeKit/${device_name}/Outlet/0/On
         retain: ON
         payload: 0

  - platform: gpio
    id: relay_1
    pin: GPIO4
    on_turn_on:
      - mqtt.publish:
          topic: HomeKit/${device_name}/Outlet/1/On
          retain: ON
          payload: 1
    on_turn_off:
      - mqtt.publish:
         topic: HomeKit/${device_name}/Outlet/1/On
         retain: ON
         payload: 0

  - platform: gpio
    id: relay_2
    pin: GPIO13
    on_turn_on:
      - mqtt.publish:
          topic: HomeKit/${device_name}/Outlet/2/On
          retain: ON
          payload: 1
    on_turn_off:
      - mqtt.publish:
         topic: HomeKit/${device_name}/Outlet/2/On
         retain: ON
         payload: 0

  - platform: gpio
    id: relay_3
    pin: GPIO12
    on_turn_on:
      - mqtt.publish:
          topic: HomeKit/${device_name}/Outlet/3/On
          retain: ON
          payload: 1
    on_turn_off:
      - mqtt.publish:
         topic: HomeKit/${device_name}/Outlet/3/On
         retain: ON
         payload: 0

light:
  - platform: monochromatic
    output: led1
    id: led
    restore_mode: ALWAYS_ON

output:
  - platform: esp8266_pwm
    pin:
      number: GPIO1
    id: led1
    inverted: True

sensor:
  - platform: wifi_signal
    name: "WiFi signal sensor"
    update_interval: 5min

ota:

logger:

mqtt:
  broker: "mqtt.lan"
  discovery: false
  topic_prefix: esphome/${device_name}
  on_message:
    - topic: HomeKit/${device_name}/Outlet/0/On
      payload: "1"
      then:
        - switch.turn_on:
            id: relay_0
    - topic: HomeKit/${device_name}/Outlet/0/On
      payload: "0"
      then:
        - switch.turn_off:
            id: relay_0

    - topic: HomeKit/${device_name}/Outlet/1/On
      payload: "1"
      then:
        - switch.turn_on:
            id: relay_1
    - topic: HomeKit/${device_name}/Outlet/1/On
      payload: "0"
      then:
        - switch.turn_off:
            id: relay_1

    - topic: HomeKit/${device_name}/Outlet/2/On
      payload: "1"
      then:
        - switch.turn_on:
            id: relay_2
    - topic: HomeKit/${device_name}/Outlet/2/On
      payload: "0"
      then:
        - switch.turn_off:
            id: relay_2

    - topic: HomeKit/${device_name}/Outlet/3/On
      payload: "1"
      then:
        - switch.turn_on:
            id: relay_3
    - topic: HomeKit/${device_name}/Outlet/3/On
      payload: "0"
      then:
        - switch.turn_off:
            id: relay_3