Сторожевой таймер
USB WatchDog ARU-P2 (uLua)
Наш самый функциональный сторожевой таймер: встроенный язык программирования uLua позволяет модифицировать логику под самые разные задачи.
Зачем нужны сторожевые таймеры?
Сторожевой таймер используется для контроля ПК и обеспечения его бесперебойной работы в случаях, когда встроенные средства не спасают.

Типовые примеры применения:
  • Обеспечение бесперебойной работы терминала.
  • Автономный компьютер выполняет работу без присмотра персонала.
  • Увеличение надёжности промышленного ПК.
  • GPU-майнер работает нестабильно, а программные средства не помогают.
Как это работает?
Сторожевой таймер подключается через USB интерфейс к ПК. Проводом он напрямую соединяется с контактами Reset или Power материнской платы.
Программа-монитор запускается на ПК и переодически передает сигнал устройству. Если компьютер завис, то зависает и программа: watchdog перестаёт получать сигнал. Через заданное время USB WatchDog автоматически подает сигнал на контакт Reset материнской платы, чтобы перезагрузить систему.
Если Reset не сработал, активируется канал Power, который выключает и снова включает компьютер.
Чем отличается от WatchDog Pro2
Благодаря встроенному языку программирования пользователь может изменять алгоритм работы в очень широких пределах. Пример программы устройства приведён в нижней части страницы.
Установка USB WatchDog ARU-P2
Это краткая инструкция, полную версию можно посмотреть на примере USB WatchDog Pro2.

1. Перед установкой необходимо выключить ПК.
2. Так как устройство бескорпусное, будьте с ним предельно острожны - не допускайте касания металлических поверхностей. Это может привести к порче устройства!
3. Провода Reset и Power необходимо подключить вместо кнопок от системного блока.
4. Как подключать PBD10

Для при установке устройства в материнскую плату убедитесь, что вы подключаете именно к разъему USB. Некоторые интерфейсы (например ieee1394 или COM-порт) имеют на плате такие же 10-выводные разъемы.

Подключение к интерфейсу, отличному от USB, приведет к порче устройства
(возможно с дымом и запахом)!


  • На плате с PBD10 разъемом на плате имеется точка. При подключении к материнской плате ПК она должна быть совмещена со стороной разъема где отсутствует 1 металлический контакт
5. Сами кнопки можно подключить к сторожевому таймеру, чтобы ими тоже можно было пользоваться.
WatchDog Pro2 PBD10
Осн.1 и Доп.1. - параллельно соединённые контакты канала 1. По-умолчанию, подключаются к контактам Reset: например, Осн.1 - на reset мат.платы и Доп.1 - на кнопку reset.
Осн.2 и Доп.2. - параллельно соединённые контакты канала 2. По-умолчанию, подключаются к контактам Power: например, Осн.2 - на power мат.платы и Доп.2-
на кнопку power.
Пример подключения к материнской плате
Драйвер
Работа в ОС ниже Windows7 не поддерживается.
В Windows7 понадобится установить драйвер CDC.
В Windows 8, Windows 10, Linux, macOS установка драйвера не требуется.
Если в Windows8 не заработал системный драйвер CDC, воспользуйтесь инструкцией.
Если Windows 11 не устанавливает драйвер с ошибкой 10, воспользуйтесь инструкцией.

wdtmon3
Программа, которая работает с обычными USB WatchDog Pro2/Lite, но подойдет для базой работы с программмой по умолчанию.
Скачать Win/Lin/OSX
Страница подробной инструкции по программе доступна по ссылке.
Почему Lua ?

Хотя Lua далеко не самый распространенный язык, он имеет ряд больших преимуществ:
  • предназначен для пользователей, не являющихся профессиональными программистами, вследствие чего большое внимание уделено простоте дизайна и лёгкости обучения;
  • простой паскалеподобный синтаксис, известный многим еще со школы;
  • минимум синтаксиса (а в нашей версии еще меньше);
Реализация UnitX Lua
Не смотря на то, что Lua и так очень маленький язык, в такой микроконтроллер его не поместить, а иметь возможность управлять логикой работы иногда очень нужно.
Поэтому мы сделали свою упрощенную реализацию. Получился хороший компромисс для встраиваемых систем, где критичны размер кода и простота работы.
Поддерживается

  • local переменные (int32);
  • арифметика и битовые операции;
  • if, while, repeat, for, break;
  • функции;
  • строки;
  • готовые функции для работы с периферией: io, pwm, adc, cc, ws2812 и т.д.
Не поддерживается

  • таблицы
  • GC
  • замыкания
  • типы данных, кроме строк и int32
  • динамический runtime с `require` и общими Lua-механиками


Когда вы захотите расширить функционал, вам понадобится

Руководство программиста
  • Подключите контроллер к компьютеру по USB
  • Откройте онлайн IDE, либо скачайте и запустите приложение, нажмите "Подключиться" и выберите порт устройства.
Полезные советы
  1. Если программа с циклом (а это большинство программ), то при ее запуске IDE потеряет связь с контроллером - это нормально. Нажмите "Стоп", если нужно вернуть взаимодействие IDE с контроллером.
  2. Если во flash уже загружена программа, то быстрый запуск программы не будет работать - сначала очистите внутреннюю память.
Код устройства
Код, который зашит по-умолчанию.
Базовый функционал сторожевого таймера: ~I, ~U, индикация, reset-power.
-- Watchdog-like "~X" protocol parser.
-- Implemented:
--   ~U           -> ~A, green blink, timer reset, escalation reset
--   ~I           -> firmware/version text

local TIMER_MAX = 300000
local TIMER_MAX_RED_SCALE = 3000
local TIMER_DELTA = 50
local RESET_TIME = 200
local POWER_OFF_T1 = 5000
local POWER_OFF_DELAY = 3000
local POWER_OFF_T2 = 200

local RESET_PIN = hw.p6
local POWER_PIN = hw.p2

local GREEN_BLINK_MS = 120
local RED_BLINK_ON_MS = 120
local RED_STEADY_MS = 400

local VERSION_TEXT = "ARU-P2 watchdog uLua 1.0.0"

local STAGE_RESET = 0
local STAGE_POWER = 1
local PARSE_IDLE = 0
local PARSE_AFTER_TILDE = 1


function write_error()
    hw.cdc_write("~E")
end

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

hw.gpio_init(RESET_PIN, hw.out)
hw.gpio_init(POWER_PIN, hw.out)
hw.gpio_set(RESET_PIN, 1)
hw.gpio_set(POWER_PIN, 1)

hw.gled(false)
hw.rled(false)

local escalation_stage = STAGE_RESET
local timer_ms = TIMER_MAX
local green_ms = 0
local red_phase_ms = RED_BLINK_ON_MS
local parse_state = PARSE_IDLE

while true do
    while hw.cdc_available() > 0 do
        local b = hw.cdc_read()
        if parse_state == PARSE_AFTER_TILDE then
            parse_state = PARSE_IDLE
            if b == 85 then
                escalation_stage = STAGE_RESET
                timer_ms = TIMER_MAX
                red_phase_ms = RED_BLINK_ON_MS
                green_ms = GREEN_BLINK_MS
                hw.rled(false)
                hw.gled(true)
                hw.cdc_write("~A")
            elseif b == 73 then
                hw.cdc_write("~I" .. VERSION_TEXT)
            else
                write_error()
            end
        else
            if b == 126 then
                parse_state = PARSE_AFTER_TILDE
            end
        end
    end

    if green_ms > 0 then
        green_ms = green_ms - TIMER_DELTA
        if green_ms <= 0 then
            green_ms = 0
            hw.gled(false)
        end
    end

    local red_interval = 0
    if green_ms > 0 then
        red_interval = -1
    elseif timer_ms > RED_STEADY_MS then
        red_interval = 300 + (27 * timer_ms) / TIMER_MAX_RED_SCALE
    end

    if red_interval < 0 then
        hw.rled(false)
    elseif red_interval == 0 then
        hw.rled(true)
    else
        red_phase_ms = red_phase_ms + TIMER_DELTA
        if red_phase_ms >= red_interval then
            red_phase_ms = 0
        end

        if red_phase_ms < RED_BLINK_ON_MS then
            hw.rled(true)
        else
            hw.rled(false)
        end
    end

    hw.delay_ms(TIMER_DELTA)

    timer_ms = timer_ms - TIMER_DELTA
    if timer_ms <= 0 then
        hw.rled(true)

        if escalation_stage == STAGE_RESET then
            pulse(RESET_PIN, RESET_TIME)
            escalation_stage = STAGE_POWER
        else
            pulse(POWER_PIN, POWER_OFF_T1)
            hw.delay_ms(POWER_OFF_DELAY)
            pulse(POWER_PIN, POWER_OFF_T2)
            escalation_stage = STAGE_RESET
        end

        timer_ms = TIMER_MAX
        red_phase_ms = RED_BLINK_ON_MS
        hw.rled(false)
    end
end
  • Ваш контроллер уже с программой, поэтому нужно нажать "Остановить", потом "Скомпилировать".
  • Если ошибок нет, то далее можно "Загрузить", если хотите просто запустить код, либо "Сохранить", если хотите, чтобы он остался в устройстве.
Доступная периферия
  • Два оптоизолированных выхода: RESET_PIN = hw.p6, POWER_PIN = hw.p2
  • Один неизолированный вход-выход с внешней подтяжкой: TEMP_PIN = hw.p9
  • Два светодиода: rled, gled
Шпаргалка по языку
Подробное описание языка и доступные библиотеки доступны по ссылке.
Работа с GPIO
hw.gpio_init(pin, mode)
Устанавливает режим hw.inp, hw.out, hw.pwm, hw.adc, hw.capture и т.д.
hw.gpio_init(hw.p1, hw.out)

hw.gpio_set(pin, value)
Устанавливает логический уровень 0 или 1.
hw.gpio_set(hw.p1, 1)

hw.gpio_get(pin) -> int
Читает уровень 0 или 1.
local level = hw.gpio_get(hw.p1)
Работа с АЦП
hw.gpio_init(hw.p5, hw.adc)
local v = hw.adc_read(hw.p5)
Работа с PWM
hw.pwm_init(pin, frequency_hz)
Инициализирует PWM на заданной частоте.

hw.pwm_set(pin, duty_percent)
Устанавливает duty cycle 0..100.

Пример:
hw.gpio_init(hw.p3, hw.pwm)
hw.pwm_init(hw.p3, 1000)
hw.pwm_set(hw.p3, 50)
Работа с датчиком температуры-влажности DTH22
DHT22
hw.dht_temp(pin) -> int
Температура в десятых долях градуса Цельсия.

hw.dht_hum(pin) -> int
Влажность в десятых долях процента.

hw.gpio_init(hw.p1, hw.dht22)
local t = hw.dht_temp(hw.p1)
local h = hw.dht_hum(hw.p1)
Таймеры
hw.delay_ms(ms)
Задержка в миллисекундах.

hw.uptime() -> int
Секунды с момента старта устройства.

hw.now() -> int
Миллисекунды с момента старта устройства.

hw.timer_after(ms, func[, arg1[, arg2]]) -> int
Однократный запуск таймера через ms.

hw.timer_every(ms, func[, arg1[, arg2]]) -> int
Периодический запуск таймера через ms.

hw.timer_cancel(timer_id)
Отмена таймера.
Индикаторы
hw.rled(on)
Управляет красным светодиодом.

hw.gled(on)
Управляет зелёным светодиодом.

Пример:
hw.rled(true)
hw.gled(false)
Дополнительные ресурсы

  • Большая инструкция USB WatchDog
    В прошивке по-умолчанию устройство частично повторяет поведение USB WatchDog Pro2, поэтому инструкция, ПО и скрипты подходят к обоим типам устройств. Открыть.
  • Описание uLua
    Полное описание возможностей находится по ссылке.