Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Ардуино-кубик с LED-матрицей: бросок по встряхиванию

Компоненты и материалы

td>1
Компонент Количество
Arduino Nano R3 1
LED-матрица 8×8 с драйвером MAX7219 1
Модуль наклонного датчика (Tilt switch)
Тумблер (Slide Switch) 1
Повышающий DC-DC преобразователь MT3608 (2–24 В → 5/9/12/28 В) 1

Необходимые инструменты

Программное обеспечение и сервисы

О проекте

Примерно год назад мой сын и я собрали электронный кубик на Arduino с несколькими светодиодами. Это по-прежнему идеальный проект для начинающих: понятная функция, простое понимание микроконтроллеров, базовой электроники и программирования.

Версия 2.0

Новый кубик делает шаг вперёд, объединяя несколько направлений. Сегодня для почти любой задачи существуют готовые модули: датчики, кнопки, индикаторы — всё на платах с удобными выводами. Доступные 3D-принтеры (от ~140 €) позволяют создавать любые крепления и корпуса. Наш кубик 2.0 — пример такого подхода.

Датчики наклона (Tilt Sensors)

Бросок реализован иначе: внутри работает Arduino Nano (по соображениям компактности). Кнопки нет — кубик бросают, встряхивая его целиком. Для детектирования встряхивания используются два наклонных датчика, установленных под углом 90° друг к другу. Внутри стеклянной колбы шарик замыкает контакты при движении — этот кратковременный сигнал используется как триггер. Два датчика гарантируют надежное срабатывание при встряхивании в любом направлении.

Прерывания (Interrupts)

Опрос пинов датчиков в основном цикле может пропустить короткие импульсы. Решение — аппаратные прерывания (attachInterrupt) на пинах D2 и D3 Arduino. При срабатывании датчика вызывается подпрограмма, увеличивающая счётчик встряхиваний.

Индикация: LED-матрица 8×8 с MAX7219

Вместо 7 отдельных светодиодов используется компактная матрица 8×8 с драйвером MAX7219. Она дешёва, проста в подключении (SPI-подобный интерфейс) и программировании. При сборке модуля важно правильно ориентировать матрицу в гнезде — при ошибке её достаточно перевернуть на 180°.

Физика движения «глазков»

Матрица не просто показывает результат. Шесть «глазков» кубика движутся по экрану: отскакивают от краёв и плавно теряют скорость. Интенсивность встряхивания (число срабатываний датчиков за секунду) задаёт начальную «скорость» глазков. При остановке встряхивания глазки катятся от случайных позиций к правильным для выпавшего значения.

Питание

Изначально использовались два элемента CR2032 (3 В), но их напряжение садилось через несколько минут. Перешли на две ААА-батарейки (3 В) с повышающим преобразователем MT3608 до 5 В на пин VIN Arduino.

Корпус: 3D-печать

Корпус из трёх частей (верх, низ с держателем батареек, матовой плексигласовый экран) спроектирован в Fusion 360. Матовый плексиглас перед матрицей скрывает негорящие светодиоды и делает картинку контрастнее. Детали соединяются прессовкой (зазор 0,1 мм) — без клея, но надёжно держатся и разбираются для смены батареек.

Сборка электроники

Arduino Nano установлен на гнездовый колодек (какшилд). LED-матрица подключена к пинам 5 (DIN), 6 (CS), 7 (CLK). Питание матрицы — через перемычки на 5V и GND. Два наклонных датчика подключены к пинам 2 и 3 (с подтяжкой к 5V и GND).

Необходимые компоненты (чек-лист)

Программный код (wuerfel8x8.ino)

/* Blog-Artikel: Schüttel-Würfel mit LED Matrix und Bewegungssimulation
   https://techpluscode.de/schuettel-wuerfel-mit-led-matrix-und-bewegungssimulation/
   techpluscode.de Copyright 2019 von Thomas Angielsky */

#include "LedControl.h"

int PinTiltX = 2;
int PinTiltY = 3;
int PinCLK = 7;
int PinCS = 6;
int PinDIN = 5;

LedControl lc = LedControl(PinDIN, PinCLK, PinCS, 1);

// Координаты точек кубика на матрице [значение][точка][x/y]
int DicePic[8][6][2] = {
  { {9,9}, {9,8}, {9,7}, {9,6}, {9,5}, {9,4} }, // 0: пусто/старт
  { {4,4}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} }, // 1
  { {2,2}, {6,6}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} }, // 2
  { {2,6}, {6,2}, {4,4}, {-1,-1}, {-1,-1}, {-1,-1} }, // 3
  { {2,2}, {2,6}, {6,2}, {6,6}, {-1,-1}, {-1,-1} }, // 4
  { {2,2}, {2,6}, {6,2}, {6,6}, {4,4}, {-1,-1} }, // 5
  { {2,1}, {2,4}, {2,7}, {6,1}, {6,4}, {6,7} }, // 6
  { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} } // 7: старт
};

float DiceXpos[6], DiceYpos[6];
float DiceXdir[6], DiceYdir[6];
volatile byte DiceXspeed[6], DiceYspeed[6];
int DiceValue;
unsigned long timestamp;
byte Mode;
volatile int shakes;
int ShakesPerSecond;
int step;

void InterruptChecks() { shakes++; timestamp = millis(); }

void SetSpeedX() { if (Mode==0) for(int i=0;i<6;i++) if(DiceXspeed[i]<255) DiceXspeed[i]+=5; InterruptChecks(); }
void SetSpeedY() { if (Mode==0) for(int i=0;i<6;i++) if(DiceYspeed[i]<255) DiceYspeed[i]+=5; InterruptChecks(); }

void ShowLed(int x, int y, bool on) { if(x<8 && y<8 && x>=0 && y>=0) lc.setLed(0,x,y,on); }
void ShowDot(int x, int y, bool on) {
  ShowLed(x-1,y-1,on); ShowLed(x,y-1,on); ShowLed(x-1,y,on); ShowLed(x,y,on);
}

void ShowDicePic(int value) {
  boolean done;
  for(int i=0;i<6;i++) { DiceXspeed[i]=100; DiceYspeed[i]=100;
    DiceXdir[i]=0; if(int(DiceXpos[i])>DicePic[value][i][0]) DiceXdir[i]=-1; else if(int(DiceXpos[i])DicePic[value][i][1]) DiceYdir[i]=-1; else if(int(DiceYpos[i])7){pos=7; dir*=-1;} if(pos<1){pos=1; dir*=-1;} }
  if(sp>0) sp--;
}

void MoveDots() {
  for(int i=0;i<6;i++) { DoStep(DiceXpos[i],DiceXdir[i],DiceXspeed[i],true); DoStep(DiceYpos[i],DiceYdir[i],DiceYspeed[i],true); }
  lc.clearDisplay(0);
  for(int i=0;i<6;i++) ShowDot(int(DiceXpos[i]),int(DiceYpos[i]),true);
}

void setup() {
  lc.shutdown(0,false); lc.setIntensity(0,8); lc.clearDisplay(0);
  randomSeed(analogRead(0)); DiceValue=0;
  for(int i=0;i<6;i++) {
    DiceXpos[i]=DicePic[7][i][0]; DiceYpos[i]=DicePic[7][i][1];
    DiceXdir[i]=random(3)-1; DiceYdir[i]=random(3)-1;
    DiceXspeed[i]=random(126)+120; DiceYspeed[i]=random(126)+120;
  }
  pinMode(PinTiltX, INPUT_PULLUP); pinMode(PinTiltY, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PinTiltX), SetSpeedX, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PinTiltY), SetSpeedY, CHANGE);
  lc.clearDisplay(0); timestamp=millis(); Mode=1;
  ShowDicePic(6); delay(1000); lc.clearDisplay(0); Mode=0;
  Serial.begin(9600); step=0; shakes=0;
}

void loop() {
  delay(50); step++;
  if(step>20) { step=0; ShakesPerSecond=shakes; shakes=0; }
  if(Mode==0) {
    MoveDots();
    if(millis()-timestamp>2000) { Mode=1; DiceValue=random(6)+1; ShowDicePic(DiceValue); }
  }
  if(ShakesPerSecond>5) Mode=0;
}

Схемы и 3D-модели

Принципиальная схема и файлы для 3D-печати корпуса доступны в разделе проекта.

Производственный процесс

  1. История, дизайн и производство кубиков: от древних инструментов к современным играм
  2. Панель переключателей и LED для Microsoft Flight Simulator 2020 на Arduino
  3. Цифровые кости на Arduino: генератор случайных чисел с LCD-дисплеем и кнопкой
  4. Сборка Bluetooth-робота-шпиона на Arduino с управлением с телефона
  5. FlickMote: жестовое IR-пульт для умного дома на Arduino 101 и ультразвуковом датчике
  6. DIY Arduino TV-B-Gone: универсальный пульт для выключения любого телевизора
  7. Создание пользовательских LED-часов с будильником — видно с 12 метров
  8. Tetris на Arduino Nano: самостоятельная сборка 16×8 LED-матрицы на 74HC595
  9. Find Me: Умный поисковик вещей на Arduino и Bluetooth
  10. Оптимизированные решения питания для проектов на Arduino