LedBasic — это интерпретируемый BASIC-подобный язык и виртуальная машина (VM) для создания анимаций на адресных светодиодных лентах. Программы пишутся в текстовом виде, компилируются в байт-код прямо на контроллере и выполняются неблокирующим образом — параллельно с остальным кодом Arduino.
Она позволяет писать анимации для светодиодов в виде простого текста (скриптов), компилировать их в компактный байт-код и воспроизводить без блокировки основного цикла микроконтроллера.
Основные возможности:
Особенности языка LedBasic:
Библиотека на - GitVerse
Библиотека с - Яндекс.Диск
Мануалы и справочники - Яндекс.Диск
Дополнительно: Online LedBasic IDE
Она позволяет писать анимации для светодиодов в виде простого текста (скриптов), компилировать их в компактный байт-код и воспроизводить без блокировки основного цикла микроконтроллера.
Основные возможности:
- Неблокирующее выполнение— tick() вызывается из loop(), не мешает другим задачам
- Независимость от типа ленты — подключение через коллбэки (совместимо с любой версией NeoPixelBus)
- Полный язык: переменные A–Z, арифметика, условия, циклы, подпрограммы, функции
- Управление скоростью—setSpeed(percent) масштабирует все задержки без изменения скрипта.
- Встроенные LED-функции: SIN8, COS8, PIXEL, RND, ABS, MIN, MAX
- HSV и RGB— SET_HSVс аппаратной конвертацией без float
- Браузерная IDE — редактор, эмулятор, отладчик, экспорт
- Аппаратная независимость (Hardware Agnostic)
LedBasic ничего не знает о железе. Она не использует напрямую FastLED или NeoPixelBus. При создании объекта вы передаете ей коллбэки (функции обратного вызова) для установки цвета пикселя, вывода буфера на ленту и очистки. Это значит, что вы можете использовать абсолютно любую библиотеку для работы со светодиодами. - Асинхронность (Неблокирующая работа)
Внутри используется конечный автомат (State Machine). Команды WAIT или DELAY не вешают микроконтроллер (ESP8266/ESP32). Функция tick() быстро отрабатывает часть инструкций и отдает управление обратно, что позволяет параллельно работать с Wi-Fi, MQTT или веб-сервером. - Встроенная математика и эффекты
Реализованы собственные таблицы синуса и косинуса (sin8, cos8) и конвертер HSV -> RGB. Библиотеке не нужны тяжелые зависимости. - Компиляция на лету и запуск из памяти
Текстовый скрипт компилируется в компактный бинарный байт-код. Скрипты можно хранить в файловой системе (LittleFS) и запускать прямо оттуда. - Защита от зависаний (Watchdog protection)
За один вызов tick() виртуальная машина выполняет не более 1000 инструкций. Если в BASIC-скрипте написан бесконечный цикл GOTO без пауз, микроконтроллер не зависнет и не уйдет в перезагрузку (Watchdog reset).
Особенности языка LedBasic:
- Переменные и математика: 26 переменных (A-Z), поддерживающих 16-битные целые числа. Доступна базовая математика (+, -, *, /, %).
- LED-команды: SET (RGB цвет), SET_HSV (цвет по тону, насыщенности и яркости), FILL (заливка), CLEAR (очистка), BRIGHT (яркость).
- Отрисовка: Команды SHOW (вывести на ленту), WAIT (вывести и ждать), DELAY (просто пауза).
- Математические функции: Встроены быстрые функции для создания эффектов: RND (случайное число), SIN8 и COS8 (табличные синусы/косинусы для плавных волн), MIN, MAX, ABS.
- Управление потоком: Классические FOR...TO...STEP...NEXT, циклы IF...THEN, переходы GOTO и подпрограммы GOSUB...RETURN.
Библиотека на - GitVerse
Библиотека с - Яндекс.Диск
Мануалы и справочники - Яндекс.Диск
Дополнительно: Online LedBasic IDE
Функции логически разделены на группы: инициализация, загрузка кода, управление выполнением и настройки.
Инициализация объекта:
LedBasic(uint16_t count, LBSetPixel setPixelCb, LBShow showCb, LBClear clearCb)
Конструктор класса. Создает экземпляр виртуальной машины.
Библиотека не привязана к конкретному оборудованию, поэтому при создании объекта вы обязаны передать количество светодиодов и три функции-коллбэка (обычно это лямбда-выражения), которые "объясняют" библиотеке, как управлять вашей лентой.
Подготовка и компиляция скриптов:
bool compileFromText(const char* scriptText)
Компилирует текстовый скрипт на языке BASIC в бинарный байт-код прямо в оперативной памяти (RAM) микроконтроллера.
bool compileBasToBin(const char* basPath, const char* binPath)
Читает текстовый файл BASIC из файловой системы LittleFS, компилирует его построчно и сразу записывает готовый байт-код в другой файл.
bool loadBinFile(const char* path)
Загружает в оперативную память заранее скомпилированный бинарный файл из файловой системы LittleFS.
bool loadBinMemory(const uint8_t* code)
Подключает байт-код напрямую из указателя памяти.
Управление и выполнение:
void play()
Запускает выполнение загруженного скрипта с самой первой строки.
void stop()
Останавливает выполнение скрипта.
void tick()
Главная функция-движок. Ее обязательно нужно поместить внутрь главного цикла loop() вашего скетча, чтобы анимация работала.
bool isRunning() const
Управление скоростью:
Библиотека позволяет "на лету" изменять скорость воспроизведения эффектов, воздействуя на длительность пауз WAIT и DELAY в скриптах, без необходимости переписывать сам код скрипта.
void setSpeed(uint16_t percent)
Устанавливает множитель скорости в процентах (от 1 до 1000).
uint16_t getSpeed() const
Инициализация объекта:
LedBasic(uint16_t count, LBSetPixel setPixelCb, LBShow showCb, LBClear clearCb)
Конструктор класса. Создает экземпляр виртуальной машины.
Библиотека не привязана к конкретному оборудованию, поэтому при создании объекта вы обязаны передать количество светодиодов и три функции-коллбэка (обычно это лямбда-выражения), которые "объясняют" библиотеке, как управлять вашей лентой.
- Аргументы:
- count — общее количество пикселей на вашей ленте.
- setPixelCb — функция вида void(uint16_t pos, uint8_t r, uint8_t g, uint8_t b). Устанавливает цвет конкретного пикселя.
- showCb — функция вида void(). Вызывает обновление ленты (отправку данных из буфера на светодиоды).
- clearCb — функция вида void(). Полностью гасит ленту (заливает черным цветом).
Подготовка и компиляция скриптов:
bool compileFromText(const char* scriptText)
Компилирует текстовый скрипт на языке BASIC в бинарный байт-код прямо в оперативной памяти (RAM) микроконтроллера.
- Аргументы: Строка const char*, содержащая полный текст скрипта (строки должны разделяться символом переноса \n).
- Как работает: Парсит текст, переводит команды в числа (токены), выделяет нужное количество RAM и сохраняет туда байт-код. Строит индекс для быстрых переходов GOTO.
- Возвращает: true при успешной компиляции, false если не хватило памяти.
bool compileBasToBin(const char* basPath, const char* binPath)
Читает текстовый файл BASIC из файловой системы LittleFS, компилирует его построчно и сразу записывает готовый байт-код в другой файл.
- Аргументы:
- basPath — путь к исходному текстовому файлу (например, "/effect.bas").
- binPath — путь, куда сохранить бинарный файл (например, "/effect.bin").
- Особенности: Очень экономит оперативную память, так как не загружает весь текст в RAM. Полезно для предварительной компиляции скриптов.
bool loadBinFile(const char* path)
Загружает в оперативную память заранее скомпилированный бинарный файл из файловой системы LittleFS.
- Аргументы: path — путь к бинарному файлу (например, "/effect.bin").
- Возвращает: true при успехе, false если файл не найден или ошибка чтения.
bool loadBinMemory(const uint8_t* code)
Подключает байт-код напрямую из указателя памяти.
- Аргументы: code — массив uint8_t, содержащий байт-код.
- Особенности: Эта функция не копирует массив в новую память и не вызывает malloc. Она просто сохраняет указатель. Это идеально подходит для хранения жестко зашитых (hardcoded) эффектов во Flash-памяти микроконтроллера с использованием PROGMEM.
Управление и выполнение:
void play()
Запускает выполнение загруженного скрипта с самой первой строки.
- Как работает: Обнуляет все переменные (A-Z), сбрасывает стек вызовов (GOSUB, FOR), переводит виртуальную машину в статус VM_RUNNING. Если скрипт не загружен — функция просто проигнорируется.
void stop()
Останавливает выполнение скрипта.
- Как работает: Переводит машину в статус VM_STOPPED и автоматически вызывает ваш коллбэк clearCb, чтобы выключить все светодиоды на ленте.
void tick()
Главная функция-движок. Ее обязательно нужно поместить внутрь главного цикла loop() вашего скетча, чтобы анимация работала.
- Как работает: За один вызов читает и выполняет порцию инструкций (байт-кода).
- Асинхронность: Если в скрипте встречается команда WAIT 500, функция tick() запоминает время, переводит VM в режим ожидания и сразу же завершает свою работу, отдавая управление основному loop(). При следующих вызовах она будет проверять встроенный таймер (millis()), и продолжит работу только когда время выйдет.
- Безопасность: Чтобы микроконтроллер не завис на конструкции вида 10 GOTO 10, tick() имеет лимит (budget): за один проход она выполняет максимум 1000 инструкций.
bool isRunning() const
- Возвращает: true, если скрипт в данный момент выполняется (включая моменты паузы WAIT/DELAY). Возвращает false, если скрипт остановлен функцией stop() или дошел до конца программы (маркера конца файла).
Управление скоростью:
Библиотека позволяет "на лету" изменять скорость воспроизведения эффектов, воздействуя на длительность пауз WAIT и DELAY в скриптах, без необходимости переписывать сам код скрипта.
void setSpeed(uint16_t percent)
Устанавливает множитель скорости в процентах (от 1 до 1000).
- Аргументы:percent — скорость в процентах.
- 100 — нормальная скорость (по умолчанию, 1 к 1).
- 200 — в 2 раза быстрее (задержка WAIT 100 превратится в 50 мс).
- 50 — в 2 раза медленнее (задержка WAIT 100 превратится в 200 мс).
uint16_t getSpeed() const
- Возвращает: текущую установленную скорость в процентах.
C++:
void setup() {
strip.begin();
// 1. Инициализация (basic создана глобально)
// 2. Компиляция текста из строки
basic.compileFromText("10 SET 0, 255, 0, 0\n20 WAIT 1000\n30 CLEAR\n40 WAIT 1000\n50 GOTO 10\n");
// Можно загрузить из файла: basic.loadBinFile("/blink.bin");
// 3. Запуск программы
basic.play();
}
void loop() {
// 4. Движок программы (не блокирует цикл!)
basic.tick();
// Пример управления на лету:
// Если нажата кнопка, ускорить в 3 раза
if (digitalRead(BTN_PIN) == LOW) {
basic.setSpeed(300);
} else {
basic.setSpeed(100);
}
}
Язык представляет собой классический диалект BASIC с номерами строк.
Типы данных и переменные
Поддерживается приоритет математических операций: +, -, *, /, % (остаток от деления), AND (побитовое И), OR (побитовое ИЛИ).
Встроенные функции:
Типы данных и переменные
- Поддерживается 26 глобальных целочисленных переменных (типа int16_t).
- Имена переменных — одиночные заглавные буквы английского алфавита: от A до Z.
- SET pos, r, g, b — Установить цвет RGB (0-255) для пикселя с индексом pos.
- SET_HSV pos, h, s, v — Установить цвет в формате HSV (Оттенок, Насыщенность, Яркость). Библиотека сама пересчитает это в RGB.
- FILL r, g, b — Залить всю ленту одним цветом.
- CLEAR — Выключить все светодиоды (залить черным).
- SHOW — Отправить данные на ленту (применить изменения).
- WAIT ms — Вызвать SHOW и подождать ms миллисекунд.
- DELAY ms — Просто подождать ms миллисекунд (без обновления ленты).
- BRIGHT val — Команда зарезервирована для изменения глобальной яркости.
- GOTO line — Безусловный переход на строку с номером line.
- GOSUB line ... RETURN — Вызов подпрограммы и возврат (глубина стека до 10 вызовов).
- FOR var = start TO end [STEP step] ... NEXT var — Цикл со счетчиком (глубина вложенности до 8).
- IF условие THEN команда — Условное выполнение. Поддерживаются операторы ==, !=, >, <, >=, <=. Особенность: после THEN может идти только одна команда.
Поддерживается приоритет математических операций: +, -, *, /, % (остаток от деления), AND (побитовое И), OR (побитовое ИЛИ).
Встроенные функции:
- RND(min, max) — Случайное число в диапазоне.
- ABS(x) — Модуль числа.
- MIN(a, b), MAX(a, b) — Минимальное / максимальное значение.
- SIN8(x), COS8(x) — Быстрый синус/косинус (вход 0-255, выход 0-255).
- PIXEL — Возвращает индекс последнего пикселя на ленте (общее количество - 1).
LedBasic IDE — это легковесная, полностью работающая (не без багов конечно, но вполне работает.) в браузере среда разработки (IDE) и эмулятор для написания эффектов адресных светодиодных лент (подобных WS2812b) на Basic подобном языке.
Основные возможности:
Позволяет видеть результат работы кода прямо на экране без подключения реального "железа".
Программа создана не только для развлечения, но и для реального использования в проектах (например, на Arduino или ESP8266/ESP32). Код можно экспортировать в несколько форматов:
Основные возможности:
- Синтаксическая подсветка: Автоматическое окрашивание команд (синий), логики (фиолетовый), математики (желтый), переменных (зеленый) и чисел.
- Автодополнение (Autocomplete): При вводе текста появляются подсказки с шаблонами команд (например, при вводе SET предложит SET_HSV P , C , 255 , 200).
- Анализ ошибок (Линтер): Редактор «на лету» проверяет код. Если допущена ошибка (неизвестная команда, нет номера строки), код подчеркивается красной волнистой линией, а в левом поле появляется значок предупреждения.
- Инструмент «Нумерация»: Так как язык требует номеров строк (10, 20, 30...), этот инструмент позволяет автоматически перенумеровать весь код с заданным шагом.
- Автоформатирование: Кнопка «Формат» автоматически расставляет пробелы вокруг операторов и приводит команды к верхнему регистру для красоты кода.
Позволяет видеть результат работы кода прямо на экране без подключения реального "железа".
- Формы вывода:
Поддерживает 3 режима визуализации:- Полоса (Strip) — классическая прямая лента.
- Кольцо (Ring) — светодиоды по кругу.
- Матрица (Matrix) — прямоугольная 2D-сетка (с настройкой ширины и высоты).
- Настройки: Можно менять количество пикселей (до 1024), масштаб (размер светодиодов).
- Графика: Реалистичное отображение с эффектом "свечения" (Glow) вокруг ярких пикселей.
- Производительность: Показывает реальный FPS работы эмулятора.
- Консоль: Выводит логи компиляции, сообщения об ошибках и статус системы.
- Переменные (Live-мониторинг): В реальном времени показывает текущие значения всех 26 доступных переменных (от A до Z) прямо во время работы анимации! Отличный инструмент для поиска логических ошибок.
- Байт-код: Показывает результат компиляции. Текстовый BASIC переводится в компактные HEX-инструкции, которые можно посмотреть с привязкой к номерам строк.
Программа создана не только для развлечения, но и для реального использования в проектах (например, на Arduino или ESP8266/ESP32). Код можно экспортировать в несколько форматов:
- .bas — исходный текстовый код программы.
- const char* — код в виде C++ строки для вставки прямо в скетч Arduino.
- PROGMEM — код в виде массива символов, хранящегося во флеш-памяти микроконтроллера.
- .bin hex — скомпилированный бинарный байт-код в виде C++ массива (uint8_t), готовый для выполнения на микроконтроллере (самый быстрый и компактный вариант).
- Горячие клавиши: Ctrl+Enter или F5 для запуска кода, Ctrl+S для сохранения.
- Кастомизация UI: Можно изменять высоту нижней панели отладки и ширину левой панели эмулятора перетаскиванием мыши.
- Настройки: Подстройка размера шрифта, размера табуляции (Tab), скорости работы виртуальной машины (setSpeed (%)).
- Локальная работа: Все функции (загрузка, сохранение файлов, компиляция) работают прямо в браузере с использованием HTML5 File API, не требуя сервера.
C++:
// =============================================================
// main_rainbow.cpp — эффект «Радуга со случайными вспышками»
//
// Вся лента показывает полный спектр радуги, равномерно
// распределённый по длине. Радуга медленно вращается.
// Случайные пиксели вспыхивают белым — как искры.
//
// Использует PIXEL — автоматически подстраивается под
// любую длину ленты без изменения скрипта.
//
// Железо: лента WS2812B, ESP8266, DMA-пин GPIO3 (RX)
// =============================================================
#include <Arduino.h>
#include <NeoPixelBus.h>
#include "LedBasic.h"
// --- настройки ---
#define NUM_LEDS 60 // меняй под свою ленту
#define DATA_PIN 3 // DMA: только GPIO3 (RX)
using MyStrip = NeoPixelBus<NeoGrbFeature, NeoEsp8266DmaWs2812xMethod>;
MyStrip strip(NUM_LEDS, DATA_PIN);
LedBasic basic(
NUM_LEDS,
[](uint16_t pos, uint8_t r, uint8_t g, uint8_t b) {
strip.SetPixelColor(pos, RgbColor(r, g, b));
},
[]{ strip.Show(); },
[]{ strip.ClearTo(RgbColor(0, 0, 0)); strip.Show(); }
);
// =============================================================
// Скрипт: радуга + случайные белые вспышки
//
// H — смещение оттенка (анимация вращения)
// P — текущий пиксель
// C — оттенок пикселя P
// S — случайное число для вспышки (0..14)
//
// Каждый пиксель получает оттенок H + P * 256 / PIXEL —
// это равномерно растягивает весь спектр по ленте.
// С вероятностью 1/15 пиксель вспыхивает белым.
// =============================================================
const char* scriptText =
"10 H = 0\n" // начальное смещение оттенка
// --- кадр: рисуем радугу пиксель за пикселем ---
"100 P = 0\n"
"110 C = H + P * 256 / PIXEL\n" // оттенок: смещение + шаг по позиции
"120 SET_HSV P , C , 255 , 170\n"
// с вероятностью 1/15 — белая вспышка поверх
"130 S = RND 0 , 14\n"
"140 IF S == 0 THEN SET P , 255 , 255 , 220\n"
"150 P = P + 1\n"
"160 IF P <= PIXEL THEN GOTO 110\n"
// показать кадр и прокрутить радугу
"170 WAIT 25\n"
"180 H = H + 4\n"
"190 IF H > 255 THEN H = H - 256\n"
"200 GOTO 100\n";
// =============================================================
void setup() {
strip.Begin();
strip.Show();
basic.compileFromText(scriptText);
basic.play();
}
void loop() {
basic.tick();
}
| 0 | 00 0a | 7 | 30 07 40 31 00 00 01 | 10 H = 0 | стр 10 |
| 10 | 00 14 | 10 | 10 30 08 40 31 00 00 11 66 01 | 20 FOR I = 0 TO PIXEL | стр 20 |
| 23 | 00 1e | 15 | 30 02 40 30 07 50 30 08 52 31 01 00 53 66 01 | 30 C = H + I * 256 / PIXEL | стр 30 |
| 41 | 00 28 | 15 | 23 30 08 02 30 02 02 31 00 ff 02 31 00 b4 01 | 40 SET_HSV I , C , 255 , 180 | стр 40 |
| 59 | 00 32 | 4 | 13 30 08 01 | 50 NEXT I | стр 50 |
| 66 | 00 3c | 5 | 24 31 00 1e 01 | 60 WAIT 30 | стр 60 |
| 74 | 00 46 | 10 | 30 07 40 30 07 50 31 00 02 01 | 70 H = H + 2 | стр 70 |
| 87 | 00 50 | 18 | 14 30 07 43 31 00 ff 15 30 07 40 30 07 51 31 01 00 01 | 80 IF H > 255 THEN H = H - 256 | стр 80 |
| 108 | 00 5a | 5 | 16 31 00 14 01 | 90 GOTO 20 | стр 90 |
C++:
// 118 bytes
const uint8_t rainbow_bin[] PROGMEM = {
0x00, 0x0a, 0x07, 0x30, 0x07, 0x40, 0x31, 0x00,
0x00, 0x01, 0x00, 0x14, 0x0a, 0x10, 0x30, 0x08,
0x40, 0x31, 0x00, 0x00, 0x11, 0x66, 0x01, 0x00,
0x1e, 0x0f, 0x30, 0x02, 0x40, 0x30, 0x07, 0x50,
0x30, 0x08, 0x52, 0x31, 0x01, 0x00, 0x53, 0x66,
0x01, 0x00, 0x28, 0x0f, 0x23, 0x30, 0x08, 0x02,
0x30, 0x02, 0x02, 0x31, 0x00, 0xff, 0x02, 0x31,
0x00, 0xb4, 0x01, 0x00, 0x32, 0x04, 0x13, 0x30,
0x08, 0x01, 0x00, 0x3c, 0x05, 0x24, 0x31, 0x00,
0x1e, 0x01, 0x00, 0x46, 0x0a, 0x30, 0x07, 0x40,
0x30, 0x07, 0x50, 0x31, 0x00, 0x02, 0x01, 0x00,
0x50, 0x12, 0x14, 0x30, 0x07, 0x43, 0x31, 0x00,
0xff, 0x15, 0x30, 0x07, 0x40, 0x30, 0x07, 0x51,
0x31, 0x01, 0x00, 0x01, 0x00, 0x5a, 0x05, 0x16,
0x31, 0x00, 0x14, 0x01, 0x00, 0x00,
};
const uint8_t rainbow_bin_size = 118;
Если коротко:
Оперативная память (RAM):
Постоянная память (Flash):
| Ресурс | ESP8266 | ESP32 |
| RAM (Общая) | ~1.5Kb | ~2Kb |
| Flash | ~6 - 10Kb | ~8 - 12Kb |
| Скорость (tick) | Очень высокая | Мгновенная |
Оперативная память (RAM):
- Статические:
- Переменные A - Z: Массив занимает 52 байта.
- Индекс строк: Массив LineEntry lineIndex[MAX_LINES]. Если MAX_LINES равен 128, при размере структуры 4 байта это займет 512 байт.
- Стек вызовов: Массивы для FOR и GOSUB (стек возвратов и состояний циклов) еще 100 - 200 байт.
- Служебные поля: Переменные состояния около 20 - 30 байт.
- Динамические:
- Байт-код: Зависит от размера вашего скрипта.
- Коллбэки: std::function для вывода на ленту добавляет еще около 32 - 64 байт.
Постоянная память (Flash):
- Таблицы в PROGMEM:
- _sin8_table: 256 байт.
- Логика интерпретатора - займет примерно 4–8 КБ Flash.
- Скрипты: Если вы храните их как текстовые исходники в коде, они занимают место как обычные строки.
- ESP32: Нет необходимости.
- ESP8266: Лучше поднять до 160MHz
INI:
; PlatformIO Project Configuration File
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:d1]
platform = espressif8266
board = d1
framework = arduino
board_build.f_cpu = 160000000L
board_build.filesystem = littlefs
board_build.flash_size = 4MB
board_build.flash_mode = qio
board_build.ldscript = eagle.flash.4m2m.ld
monitor_speed = 115200
lib_deps =
makuna/NeoPixelBus@^2.8.4
Изменено:
















