Перейти к содержанию
USB WatchDog ARU-P2 uLua: примеры кода

USB WatchDog ARU-P2 uLua: примеры кода

Примеры кода для ARU-P2 uLua: Reset при пропадании сигнала от ПК, Reset по сухому контакту и выключение при перегреве.

Каждый пример решает одну задачу и использует каналы ARU-P2 напрямую:

НазначениеАлиас uLuaАктивное состояние
Resethw.p60
Powerhw.p20
Дополнительный вход или DHT22hw.p9зависит от сценария

Запущенная или записанная пользовательская программа заменяет штатный алгоритм WatchDog. В ней будут работать только явно реализованные действия.

hw.p9 — одна физическая линия. Сухой контакт и DHT22 в примерах — два альтернативных подключения; использовать их одновременно нельзя.

Как безопасно проверить пример

  1. Отключите провода Reset и Power от материнской платы, оставьте только USB.
  2. Откройте uLua веб-IDE, подключитесь и нажмите «Стоп».
  3. Скопируйте код и выберите «Скомпилировать и запустить».
  4. Проверьте индикацию и команды без подключения каналов к материнской плате.
  5. Остановите программу, выключите ПК, подключите нужный канал параллельно кнопке Reset или Power и повторите проверку.
  6. Записывайте код во флеш-память только после успешного теста.

Reset, если ПК перестал посылать контрольный сигнал

Программа принимает по USB CDC пару байтов ~U, отвечает ~A и начинает новый 60-секундный интервал. Если сигнал не пришёл вовремя, ARU-P2 замыкает канал Reset на 200 мс. Команда ~I возвращает короткую строку версии.

Открыть исходник watchdog-heartbeat-reset.lua

local RESET_PIN = hw.p6
local TIMEOUT_MS = 60000
local RESET_PULSE_MS = 200
local last_heartbeat = hw.now()
local after_tilde = false

function pulse(pin, duration_ms)
    hw.gpio_set(pin, 0)
    hw.delay_ms(duration_ms)
    hw.gpio_set(pin, 1)
end

hw.gpio_init(RESET_PIN, hw.out)
hw.gpio_set(RESET_PIN, 1)
hw.rled(false)
hw.gled(false)

while true do
    while hw.cdc_available() > 0 do
        local byte = hw.cdc_read()

        if after_tilde then
            after_tilde = false

            if byte == 85 then
                last_heartbeat = hw.now()
                hw.gled(true)
                hw.cdc_write("~A")
            elseif byte == 73 then
                hw.cdc_write("~IARU-P2 uLua quick watchdog")
            else
                hw.cdc_write("~E")
            end
        elseif byte == 126 then
            after_tilde = true
        end
    end

    if hw.now_delta(last_heartbeat) >= TIMEOUT_MS then
        hw.rled(true)
        pulse(RESET_PIN, RESET_PULSE_MS)
        hw.rled(false)
        last_heartbeat = hw.now()
    end

    hw.delay_ms(20)
    hw.gled(false)
end

Задайте допустимую паузу в TIMEOUT_MS. Программа на ПК должна отправлять ~U чаще этого интервала, например раз в 10 секунд. Пример реализует только команды ~U и ~I, а не весь протокол штатной программы.

Reset по внешнему сухому контакту

Подключите релейный или сухой контакт между hw.p9 и GND. Вход имеет внутреннюю подтяжку и в нормальном состоянии читается как 1. Если контакт остаётся замкнутым не менее секунды, WatchDog формирует один импульс Reset и ждёт размыкания перед следующим срабатыванием.

Открыть исходник watchdog-contact-reset.lua

local RESET_PIN = hw.p6
local CONTACT_PIN = hw.p9
local HOLD_MS = 1000
local contact_active = false
local active_since = 0

function pulse(pin, duration_ms)
    hw.gpio_set(pin, 0)
    hw.delay_ms(duration_ms)
    hw.gpio_set(pin, 1)
end

hw.gpio_init(RESET_PIN, hw.out)
hw.gpio_set(RESET_PIN, 1)
hw.gpio_init(CONTACT_PIN, hw.inp)

while true do
    if hw.gpio_get(CONTACT_PIN) == 0 then
        if not contact_active then
            contact_active = true
            active_since = hw.now()
        end

        if hw.now_delta(active_since) >= HOLD_MS then
            hw.rled(true)
            pulse(RESET_PIN, 200)
            hw.rled(false)

            while hw.gpio_get(CONTACT_PIN) == 0 do
                hw.delay_ms(20)
            end
            contact_active = false
        end
    else
        contact_active = false
    end

    hw.delay_ms(20)
end

Параметр HOLD_MS задаёт время подтверждения аварийного сигнала. Такой сценарий подходит для дискретного выхода контроллера, ИБП, термостата или другого оборудования.

Аварийное выключение при перегреве

Подключите DATA датчика DHT22/AM2302 к hw.p9, питание и GND — согласно исполнению датчика. Если на модуле нет подтяжки, поставьте резистор 4,7–10 кОм между DATA и питанием. Канал Power должен быть подключён параллельно кнопке питания ПК.

Открыть исходник watchdog-overheat-poweroff.lua

local POWER_PIN = hw.p2
local SENSOR_PIN = hw.p9
local POWER_HOLD_MS = 5000
local OFF_TEMP = 700
local REARM_TEMP = 650
local armed = true
local last_sample = 0

function hold_power(pin, duration_ms)
    hw.gpio_set(pin, 0)
    hw.delay_ms(duration_ms)
    hw.gpio_set(pin, 1)
end

hw.gpio_init(POWER_PIN, hw.out)
hw.gpio_set(POWER_PIN, 1)
hw.gpio_init(SENSOR_PIN, hw.dht22)
hw.rled(false)

while true do
    local sample = hw.dht_ts(SENSOR_PIN)

    if sample ~= 0 and sample ~= last_sample then
        last_sample = sample
        local temperature = hw.dht_temp(SENSOR_PIN)
        hw.cdc_write("temperature x10=" .. temperature .. "\n")

        if armed and temperature >= OFF_TEMP then
            hw.rled(true)
            hold_power(POWER_PIN, POWER_HOLD_MS)
            hw.rled(false)
            armed = false
        elseif not armed and temperature <= REARM_TEMP then
            armed = true
        end
    end

    hw.delay_ms(100)
end

При 70,0 °C (OFF_TEMP = 700) программа удерживает Power пять секунд. Повторное срабатывание разрешается только после охлаждения до 65,0 °C. Такое аппаратное выключение может привести к потере несохранённых данных, поэтому сначала проверьте пороги и датчик без подключения канала Power.

Если нужно изменить сценарий