Все статьиHardware

Светодиодные песочные часы на Arduino с акселерометром

БА
Бексултан Айтен
CTO, Alashed
3 мая 2025 г.
8 мин чтения
Светодиодные песочные часы на Arduino с акселерометром

Собираем цифровые песочные часы на Arduino с двумя LED-матрицами 8x8 и акселерометром ADXL335. Переворачиваете устройство — и «песок» пересыпается. Полный код, схема и объяснение.

Идея проекта

Обычные песочные часы знакомы всем: перевернул — песок посыпался. А что если вместо песка использовать пиксели на LED-матрицах? Именно так работают цифровые песочные часы на Arduino. Два светодиодных дисплея 8x8 изображают верхнюю и нижнюю колбы. Когда вы переворачиваете устройство, акселерометр определяет ориентацию, и анимация «падающего песка» запускается в нужном направлении.

Проект учит работать с аналоговыми датчиками, управлять LED-матрицами через драйвер MAX7219 и создавать визуальные анимации. Подходит для учеников 8-10 классов. Сборка и программирование занимают 2-3 часа.

LED-матрица 8x8 с модулем MAX7219 для песочных часов
LED-матрица 8x8 с модулем MAX7219 для песочных часов

Список компонентов

Для реализации проекта подготовьте:

  • Arduino Uno или Nano — 1 шт.
  • LED-матрица 8x8 с модулем MAX7219 — 2 шт.
  • Акселерометр ADXL335 (аналоговый, 3 оси) — 1 шт.
  • Макетная плата — 1 шт.
  • Соединительные провода — 15-20 шт.
  • USB-кабель для программирования
  • Батарейный отсек или powerbank (для автономной работы, по желанию)

MAX7219 — это специализированный драйвер, который берёт на себя управление 64 светодиодами матрицы. Arduino общается с ним по трём проводам, что сильно упрощает подключение.

Схема подключения

Первая LED-матрица (MAX7219) к Arduino:

  • DIN — к цифровому пину D5
  • CLK — к цифровому пину D4
  • CS (LOAD) — к цифровому пину D6
  • VCC — к 5V
  • GND — к GND

Вторая LED-матрица подключается каскадно к первой: выход DOUT первого модуля соединяется с DIN второго. Пины CLK и CS идут параллельно — те же провода, что и у первого модуля. Каскадное соединение позволяет управлять обоими дисплеями по одной шине.

Акселерометр ADXL335:

  • VCC — к 3.3V Arduino (важно: ADXL335 работает от 3.3V, не от 5V)
  • GND — к GND
  • X — к аналоговому пину A1
  • Y — к аналоговому пину A2
  • Выход Z не используем в этом проекте

Акселерометр ADXL335 — аналоговый. Он выдаёт напряжение, пропорциональное ускорению по каждой оси. В покое основная сила — гравитация, поэтому по значениям X и Y можно определить, как повёрнуто устройство.

Собранная схема LED-песочных часов на Arduino
Собранная схема LED-песочных часов на Arduino

Установка библиотеки

Откройте Arduino IDE, перейдите в Скетч — Подключить библиотеку — Управлять библиотеками. Найдите и установите библиотеку LedControl от Eberhard Fahle. Она упрощает работу с MAX7219.

Полный код проекта

```cpp

// Цифровые песочные часы на Arduino

// Две LED-матрицы 8x8 + акселерометр ADXL335

// Переворачиваете устройство — песок пересыпается

#include <LedControl.h>

// Подключение MAX7219: DIN, CLK, CS, количество модулей

LedControl lc = LedControl(5, 4, 6, 2);

// Пины акселерометра

const int xPin = A1;

const int yPin = A2;

// Порог для определения переворота

const int flipThreshold = 400;

// Массив «песчинок» для верхней и нижней матрицы

// Каждый элемент — количество зажжённых пикселей в строке

int topSand[8] = {8, 8, 8, 8, 8, 8, 8, 8}; // Полная — 64 точки

int botSand[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Пустая

// Общее количество песчинок

int totalGrains = 64;

int fallenGrains = 0;

// Интервал падения одной песчинки (мс)

unsigned long grainInterval = 500;

unsigned long lastGrainTime = 0;

// Направление: true = песок сверху вниз

bool topIsUp = true;

bool animationDone = false;

void setup() {

Serial.begin(9600);

// Инициализируем оба модуля MAX7219

for (int i = 0; i < 2; i++) {

lc.shutdown(i, false); // Выходим из спящего режима

lc.setIntensity(i, 4); // Яркость (0-15)

lc.clearDisplay(i); // Очищаем дисплей

}

// Заполняем верхнюю матрицу полностью

fillMatrix(0, true);

clearMatrix(1);

Serial.println("Песочные часы готовы. Переверните устройство!");

}

void loop() {

// Считываем данные акселерометра

int xVal = analogRead(xPin);

int yVal = analogRead(yPin);

// Определяем ориентацию устройства

bool currentOrientation = (yVal > flipThreshold);

// Если устройство перевернули — сбрасываем анимацию

if (currentOrientation != topIsUp) {

topIsUp = currentOrientation;

resetAnimation();

Serial.println("Перевернуто! Запуск анимации.");

}

// Анимация падения песчинок

if (!animationDone) {

unsigned long now = millis();

if (now - lastGrainTime >= grainInterval) {

lastGrainTime = now;

dropGrain();

}

}

}

// Убираем одну песчинку сверху и добавляем снизу

void dropGrain() {

if (fallenGrains >= totalGrains) {

animationDone = true;

Serial.println("Время вышло!");

blinkBothMatrices(3);

return;

}

// Определяем, какая матрица сверху, какая снизу

int topMatrix = topIsUp ? 0 : 1;

int botMatrix = topIsUp ? 1 : 0;

// Находим верхнюю строку с песком и убираем одну точку

for (int row = 7; row >= 0; row--) {

if (topSand[row] > 0) {

topSand[row]--;

break;

}

}

// Находим нижнюю строку с местом и добавляем точку

for (int row = 7; row >= 0; row--) {

if (botSand[row] < 8) {

botSand[row]++;

break;

}

}

fallenGrains++;

// Обновляем отображение на матрицах

updateMatrix(topMatrix, topSand);

updateMatrix(botMatrix, botSand);

}

// Отрисовка массива на матрице

void updateMatrix(int device, int sand[]) {

for (int row = 0; row < 8; row++) {

byte rowData = 0;

// Зажигаем нужное количество пикселей в строке по центру

int start = (8 - sand[row]) / 2;

for (int col = start; col < start + sand[row]; col++) {

bitSet(rowData, col);

}

lc.setRow(device, row, rowData);

}

}

// Заполнение матрицы

void fillMatrix(int device, bool fill) {

byte val = fill ? 0xFF : 0x00;

for (int row = 0; row < 8; row++) {

lc.setRow(device, row, val);

}

}

// Очистка матрицы

void clearMatrix(int device) {

lc.clearDisplay(device);

}

// Сброс анимации при перевороте

void resetAnimation() {

for (int i = 0; i < 8; i++) {

topSand[i] = 8;

botSand[i] = 0;

}

fallenGrains = 0;

animationDone = false;

int topMatrix = topIsUp ? 0 : 1;

int botMatrix = topIsUp ? 1 : 0;

fillMatrix(topMatrix, true);

clearMatrix(botMatrix);

}

// Мигание обеих матриц при завершении

void blinkBothMatrices(int times) {

for (int t = 0; t < times; t++) {

fillMatrix(0, true);

fillMatrix(1, true);

delay(300);

clearMatrix(0);

clearMatrix(1);

delay(300);

}

}

`

Разбор кода

Библиотека LedControl. Она позволяет управлять LED-матрицами через MAX7219 тремя простыми функциями: setRow() задаёт строку, clearDisplay() очищает дисплей, setIntensity() регулирует яркость. Каскадные модули адресуются номером устройства — 0 для первого, 1 для второго.

Аналоговый акселерометр. Функция analogRead() возвращает значения от 0 до 1023. В нейтральном положении акселерометр выдаёт примерно 512 по каждой оси. При наклоне или перевороте значения смещаются. Мы сравниваем показания с порогом, чтобы определить, где «верх».

Логика песка. Массивы topSand и botSand хранят количество горящих пикселей в каждой строке. Функция dropGrain() убирает точку из верхней матрицы и добавляет в нижнюю, создавая иллюзию пересыпания. Пиксели размещаются по центру строки для более реалистичного вида.

Millis вместо delay. Анимация построена на millis(), поэтому Arduino постоянно следит за акселерометром. Если использовать delay(), устройство не заметит переворот во время паузы.

Советы для учителей

Начните урок с демонстрации готового устройства — ученики сразу загорятся интересом, увидев анимацию. Предложите каждому настроить свою скорость пересыпания, изменив переменную grainInterval. Продвинутые ученики могут поменять паттерн заполнения: например, песчинки падают не строками, а случайным образом через random(). Для красивой презентации корпус можно напечатать на 3D-принтере или склеить из картона в форме настоящих песочных часов.

Как Alashed помогает

Платформа Alashed Hardware предоставляет виртуальный симулятор Arduino, где можно протестировать схему и код до покупки компонентов. А в CodeStudio ученики пишут и отлаживают скетчи прямо в браузере, без установки Arduino IDE. Учитель может отслеживать прогресс каждого ученика и давать обратную связь в реальном времени.

Попробуйте Alashed бесплатно

Подключите школу к пилоту. Генерируйте КМЖ за 2 минуты, ведите CodeStudio уроки, заказывайте оборудование — всё в одном месте.

Попробовать бесплатноДемо