Chain PIR

PIRChain is the helper class for PIR (Passive Infrared) sensor devices on the Chain bus. It provides methods to read IR induction values, configure trigger delay, and monitor PIR trigger events.

Support the following products:

Chain PIR

UiFlow2 Example

PIR motion detection

Open the m5core_chain_pir_basic_example.m5f2 project in UiFlow2.

This example demonstrates how to use trigger callbacks from the Chain PIR sensor to update motion status on screen. It enables trigger auto-send, configures trigger hold time, and counts the detected duration while motion is active.

UiFlow2 Code Block:

m5core_chain_pir_basic_example.png

Example output:

None

MicroPython Example

PIR motion detection

This example demonstrates how to use trigger callbacks from the Chain PIR sensor to update motion status on screen. It enables trigger auto-send, configures trigger hold time, and counts the detected duration while motion is active.

MicroPython Code Block:

  1# SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
  2#
  3# SPDX-License-Identifier: MIT
  4
  5import os, sys, io
  6import M5
  7from M5 import *
  8from chain import PIRChain
  9from chain import ChainBus
 10import time
 11
 12
 13title0 = None
 14label_status = None
 15label_count = None
 16bus2 = None
 17chain_pir_0 = None
 18detected = None
 19count = None
 20last_time = None
 21trigger_hold_time = None
 22
 23
 24def chain_pir_0_motion_detected_event(args):
 25    global \
 26        title0, \
 27        label_status, \
 28        label_count, \
 29        bus2, \
 30        chain_pir_0, \
 31        detected, \
 32        count, \
 33        last_time, \
 34        trigger_hold_time
 35    print("detect motion")
 36    detected = True
 37    count = 0
 38    label_status.setText(str("Status: detected"))
 39    label_status.setColor(0x009900, 0x000000)
 40    label_count.setVisible(True)
 41
 42
 43def chain_pir_0_motion_ended_event(args):
 44    global \
 45        title0, \
 46        label_status, \
 47        label_count, \
 48        bus2, \
 49        chain_pir_0, \
 50        detected, \
 51        count, \
 52        last_time, \
 53        trigger_hold_time
 54    print("not detect")
 55    detected = False
 56    label_status.setText(str("Status: no detect"))
 57    label_status.setColor(0xCCCCCC, 0x000000)
 58    label_count.setVisible(False)
 59
 60
 61def setup():
 62    global \
 63        title0, \
 64        label_status, \
 65        label_count, \
 66        bus2, \
 67        chain_pir_0, \
 68        detected, \
 69        count, \
 70        last_time, \
 71        trigger_hold_time
 72
 73    M5.begin()
 74    Widgets.setRotation(1)
 75    Widgets.fillScreen(0x000000)
 76    title0 = Widgets.Title("Chain PIR Example", 3, 0xFFFFFF, 0x0000FF, Widgets.FONTS.DejaVu24)
 77    label_status = Widgets.Label(
 78        "Status: --", 20, 70, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu24
 79    )
 80    label_count = Widgets.Label(
 81        "Count: --", 20, 165, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu24
 82    )
 83
 84    bus2 = ChainBus(2, tx=21, rx=22)
 85    chain_pir_0 = PIRChain(bus2, 1)
 86    chain_pir_0.set_trigger_callback(
 87        PIRChain.TRIGGER_MOTION_DETECTED, chain_pir_0_motion_detected_event
 88    )
 89    chain_pir_0.set_trigger_callback(PIRChain.TRIGGER_MOTION_ENDED, chain_pir_0_motion_ended_event)
 90    chain_pir_0.set_trigger(True)
 91    chain_pir_0.set_trigger_hold_time(5, save=False)
 92    trigger_hold_time = chain_pir_0.get_trigger_hold_time()
 93    print((str("trigger hold time: ") + str(trigger_hold_time)))
 94    detected = chain_pir_0.get_detect_status()
 95    if detected:
 96        label_status.setText(str("Status: detected"))
 97        label_status.setColor(0x009900, 0x000000)
 98
 99
100def loop():
101    global \
102        title0, \
103        label_status, \
104        label_count, \
105        bus2, \
106        chain_pir_0, \
107        detected, \
108        count, \
109        last_time, \
110        trigger_hold_time
111    M5.update()
112    if detected:
113        if (time.ticks_diff((time.ticks_ms()), last_time)) >= 1000:
114            last_time = time.ticks_ms()
115            count = (count if isinstance(count, (int, float)) else 0) + 1
116            label_count.setText(str((str("Count: ") + str(count))))
117    else:
118        pass
119
120
121if __name__ == "__main__":
122    try:
123        setup()
124        while True:
125            loop()
126    except (Exception, KeyboardInterrupt) as e:
127        try:
128            bus2.deinit()
129            from utility import print_error_msg
130
131            print_error_msg(e)
132        except ImportError:
133            print("please update to latest firmware")

Example output:

None

API

PIRChain

class chain.pir.PIRChain(bus, device_id)

Bases: KeyChain

PIR Chain class for interacting with PIR (Passive Infrared) sensor devices over Chain bus.

Parameters:
  • bus (ChainBus) – The Chain bus instance.

  • device_id (int) – The device ID of the PIR sensor on the Chain bus.

UiFlow2 Code Block:

init.png

MicroPython Code Block:

from chain import ChainBus
from chain import PIRChain

bus2 = ChainBus(2, tx=21, rx=22)
chain_pir_0 = PIRChain(bus2, 1)

For other button and some general methods, please refer to the ChainKey class.

get_detect_status()

Get the motion detection status.

Returns:

Motion detection status. True means motion detected, False means motion ended. Returns False if failed.

Return type:

bool

UiFlow2 Code Block:

get_detect_status.png

MicroPython Code Block:

status = chain_pir_0.get_detect_status()
set_trigger(enable)

Enable or disable PIR detection reporting.

Parameters:

enable (bool) – True to enable PIR detection reporting, False to disable it.

Returns:

True if the operation was successful, False otherwise.

Return type:

bool

UiFlow2 Code Block:

set_trigger.png

MicroPython Code Block:

success = chain_pir_0.set_trigger(True)
get_trigger()

Get whether PIR detection reporting is enabled.

Returns:

True if PIR detection reporting is enabled, False if disabled. Returns False if failed.

Return type:

bool

UiFlow2 Code Block:

get_trigger.png

MicroPython Code Block:

enabled = chain_pir_0.get_trigger()
set_trigger_hold_time(seconds, save=False)

Set the hold time before triggering motion ended status.

Parameters:
  • seconds (int) – Hold time in seconds. Range: 0-255.

  • save (bool) – Whether to save the setting to flash. Default: False.

Returns:

True if the operation was successful, False otherwise.

Return type:

bool

UiFlow2 Code Block:

set_trigger_hold_time.png

MicroPython Code Block:

success = chain_pir_0.set_trigger_hold_time(5, False)
get_trigger_hold_time()

Get the hold time before triggering motion ended status.

Returns:

Hold time in seconds, or None if failed.

Return type:

int

UiFlow2 Code Block:

get_trigger_hold_time.png

MicroPython Code Block:

hold_time = chain_pir_0.get_trigger_hold_time()
set_trigger_callback(trigger_type, callback)

Set callback for PIR motion detection events.

Parameters:
  • trigger_type (int) – Trigger type to listen for. Use PIRChain.TRIGGER_MOTION_DETECTED (1) for motion detected or PIRChain.TRIGGER_MOTION_ENDED (0) for motion ended.

  • callback – Callback function that will be called when PIR motion detection changes.

Return type:

None

Note

Chain related methods cannot be called in the callback function.

UiFlow2 Code Block:

set_trigger_callback.png

MicroPython Code Block:

def motion_detected_callback(args):
    print("Motion detected")

def motion_ended_callback(args):
    print("Motion ended")

# Listen for motion detected only
chain_pir_0.set_trigger_callback(PIRChain.TRIGGER_MOTION_DETECTED, motion_detected_callback)

# Listen for motion ended only
chain_pir_0.set_trigger_callback(PIRChain.TRIGGER_MOTION_ENDED, motion_ended_callback)