GPIO Extender Pro (UnitX Lua)
Очень маленький программируемый контроллер для ваших проектов с упрощенной реализацией Lua.
Для тех, кто хочет быстро менять логику без перепрошивки на C.

Компактный размер. 10 универсальных портов.
USB для управления и программирования.
Какие задачи решает такой контроллер
Большой функционал в минимальном размере
  • Производственные и сервисные сценарии
    • стенды и быстрые тестовые последовательности;
    • диагностика через USB CDC;
    • быстрые тестовые последовательности;
  • Простая промышленная и лабораторная автоматика
    • опрос датчиков;
    • управление GPIO и PWM;
    • пороговая логика;
    • реакция на входные события;
    • обмен через UART и простые текстовые протоколы;
    • Связь с GSM-модемом.
  • Прототипирование
    • быстрые прототипы;
    • отладка прикладной логики до финализации устройства;
    • исследование API будущего продукта.
  • Учебные и демонстрационные проекты
    • удобнее, чем писать на C с нуля;
    • прозрачнее, чем большой контроллер;
    • хорошо показывает границу между языком, VM и "железом".
  • Небольшие standalone-приборы
    • USB-датчики и исполнительные модули;
    • простые контроллеры интерфейсов;
    • небольше шлюзы и адаптеры;
    • интерактивные инсталляции и технические арт-объекты;
    • контроллеры терминалов;
Начало работы
По умолчанию устройство выполняет демонстрационный код (который можно увидеть ниже).

Подключите ваше устройство
  1. Подключите устройство к компьютеру к USB.
  2. Ваш компьютер определит устройство как виртуальный COM-порт (CDC).

Откройте терминал
Запустите любое приложение для работы с последовательным портом:
  • Windows: PuTTY, TeraTerm, Arduino Serial Monitor, pyserial-miniterm.
  • macOS: Screen, Serial, CoolTerm, pyserial-miniterm.
  • Linux: Screen, Minicom, PuTTY, pyserial-miniterm.

Подключитесь к последовательному порту
  • Windows: устройство вида COM3 и т.п.
  • macOS: устройство вида /dev/tty.usbmodem2073306558472 и т.п.
  • Linux: устройство вида /dev/ttyACM0 и т.п.

Вводите команды:
get N — читает уровень пина N (1..9, 0 - это 10)
set N M — выставляет уровень M на выходном пине N (N = 1..5)
rled 1/0 и gled 1/0 для управления светодиодами на плате

Например:
rled 1 (и нажать enter) — должен зажечь красный светодиод
set 1 1 (и нажать enter) — должен выставить вывод 1 в высокий уровень
Характеристики
  1. Интерфейс подключения: USB (CDC)
  2. Питание 5В (от USB).
  3. Рабочие интерфейсы: GPIO, ADC, PWM, CC и др.
  4. Количество выводов: 25, управляемых - 10
  5. Габариты: 54х15х10мм
  6. Работает в Win7/Linux/macOS и других ОС
  7. Встроенный скриптовый язык для самостоятельного программирования логики.
Почему Lua ?

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

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

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


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

Руководство программиста
  • Подключите контроллер к компьютеру по USB
  • Откройте онлайн IDE, нажмите "Подключиться" и выберите порт устройства.
Код для GPIO Extender
Повторим возможности первого GPIO Extender. Этот код идет в устройстве по-умолчанию.
Команды:
get N — читает уровень пина N (1..9, 0 - это 10)
set N M — выставляет уровень M на выходном пине N (N = 1..5)
rled 1/0 и gled 1/0 для управления светодиодами на плате
-- инициализация пинов
for i = 1, 5 do hw.gpio_init(hw.pin(i), hw.out) end
for i = 6, 9 do hw.gpio_init(hw.pin(i), hw.inp) end
hw.gpio_init(hw.p10, hw.inp)

-- парсер команд
while true do
    if cmd.begin() then
        if cmd.word("get") then
            local n = cmd.int()
            if cmd.done() then
                if n >= 0 and n <= 9 then
                    hw.cdc_write(hw.gpio_get(n) .. "\n")
                else
                    hw.cdc_write("ERR pin\n")
                end
            else
                hw.cdc_write("ERR syntax\n")
            end

        elseif cmd.word("set") then
            local n = cmd.int()
            local m = cmd.int()
            if cmd.done() then
                if n >= 1 and n <= 5 then
                    hw.gpio_set(n, m)
                    hw.cdc_write("OK\n")
                else
                    hw.cdc_write("ERR pin\n")
                end
            else
                hw.cdc_write("ERR syntax\n")
            end

        elseif cmd.word("rled") then
            local m = cmd.int()
            if cmd.done() then
                hw.rled(m ~= 0)
                hw.cdc_write("OK\n")
            else
                hw.cdc_write("ERR syntax\n")
            end

        elseif cmd.word("gled") then
            local m = cmd.int()
            if cmd.done() then
                hw.gled(m ~= 0)
                hw.cdc_write("OK\n")
            else
                hw.cdc_write("ERR syntax\n")
            end

        else
            cmd.done()
            hw.cdc_write("ERR unknown\n")
        end
    end
end
  • Ваш контроллер уже с программой, поэтому нужно нажать "Остановить", потом "Скомпилировать".
  • Если ошибок нет, то далее можно "Загрузить", если хотите просто запустить код, либо "Сохранить", если хотите, чтобы он остался в устройстве.
Шпаргалка по языку
Подробное описание языка и доступные библиотеки доступны по ссылке.
Работа с 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)
Работа с захватом
hw.capture_freq(pin) -> int
Возвращает частоту входного сигнала в Гц.

hw.capture_duty(pin) -> int
Возвращает duty cycle в процентах.
Работа с UART
hw.uart_setup(baud, bits, parity, stop)
Настраивает UART2.

Пример:
hw.gpio_init(hw.p2, hw.uart_tx)
hw.gpio_init(hw.p6, hw.uart_rx)
hw.uart_setup(115200, 8, hw.parity_none, 1)

hw.uart_write(str)
Пишет строку в UART.

hw.uart_available() -> int
Возвращает число байт в RX buffer.

hw.uart_read() -> int
Читает один байт или возвращает -1, если данных нет.
Работа с управляемой лентой WS2812
hw.ws2812_write(pin, data)

Отправляет бинарные данные о цвете на ленту. Цвет - код в палитре на 256 цветов. Длина строки ограничена памятью. Если строка - результат конкатенации, то - максимум 128 байт.

hw.gpio_init(hw.p4, hw.ws2812)
hw.ws2812_write(hw.p4, "\x10\x00\x00")
Работа с датчиком температуры-влажности 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)
Дополнительная информация
Полное описание возможностей находится по ссылке.
Надеемся, что данное руководство поможет вам в работе с мини-контроллером. Удачной разработки!