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

Arduino Flip Clock на матрице 8×8 LED — DIY проект реального времени

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

Arduino Nano R3×1
DS3231M — RTC модуль (I2C, ±5 ppm)×1
Модуль матрицы 8×8 LED с драйвером MAX7219×1
RGB LED (общий анод)×1
Резистор 220 Ом×2
Ротационный энкодер с кнопкой×1

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

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

О проекте

Эти часы на матрице 8×8 LED разработаны Эдрианом Джонсом. Время отображается прокруткой слева направо (или сверху вниз при изменении параметра). Каждая цифра выезжает справа, останавливается в центре, слегка ярче, затем уходит влево, уступая место следующей.

Для вертикального режима («сверху вниз») измените в коде:

static boolean top2bottom = false;
// на:
static boolean top2bottom = true;

Во многих параметрах можно настраивать: скорость прокрутки, количество пустых строк между символами, 12/24-часовой формат, задержку между символами, яркость и др.

Установка времени производится вращательным энкодером. Двухцветный LED индицирует режим настройки (часы, минуты или нормальный). Корпус состоит из двух половин, обеспечивая удобный доступ к внутренностям.

Код

//*****************************************************************************************//
// MATRIX CLOCK
// Adrian Jones, March 2014
// - позволяет прокрутку слева направо и сверху вниз
//*****************************************************************************************//
#include 
#include 

#define max7219_reg_noop 0x00
#define max7219_reg_digit0 0x01
#define max7219_reg_digit1 0x02
#define max7219_reg_digit2 0x03
#define max7219_reg_digit3 0x04
#define max7219_reg_digit4 0x05
#define max7219_reg_digit5 0x06
#define max7219_reg_digit6 0x07
#define max7219_reg_digit7 0x08
#define max7219_reg_decodeMode 0x09
#define max7219_reg_intensity 0x0a
#define max7219_reg_scanLimit 0x0b
#define max7219_reg_shutdown 0x0c
#define max7219_reg_displayTest 0x0f

#define dataIn 12
#define load 10
#define clock 11

char alphanum[][8] = {
  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // пробел
  {0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10}, // !
  // ... (полная таблица символов опущена для краткости)
  {0xE0,0xA0,0xE0,0x80,0x8A,0x15,0x15,0x11}  // pm (~)
};

RTC_DS1307 RTC;

#define enc_PinA 2
#define enc_PinB 4
#define enc_Switch 3
#define mode_Pin 8
#define min_Pin 9

unsigned char enc_A, enc_B, enc_A_prev=0;
static boolean rotating = false, clockwise = false, updateFlag = false;
static int mode = 0;

#define max_array_size 100
char ac[max_array_size] = {};
byte rc[8] = {};
String display_message = "";
int arraylen;

#define delay_line 75
#define delay_char 400
#define delay_mess 500
#define cblanks 1
#define eblanks 0

static boolean top2bottom = false;
static boolean hour24 = false;
static boolean charHI = true;
static boolean doSerial = true;

void setup() {
  Wire.begin();
  Serial.begin(57600);
  if(doSerial) Serial.print("MATRIX Clock - Adrian Jones, Mar. 2014");

  pinMode(dataIn, OUTPUT); pinMode(clock, OUTPUT); pinMode(load, OUTPUT);
  initMatrix();

  pinMode(mode_Pin, OUTPUT); digitalWrite(mode_Pin, 1);
  pinMode(min_Pin, OUTPUT); digitalWrite(min_Pin, 1);

  pinMode(enc_PinA, INPUT_PULLUP); digitalWrite(enc_PinA, HIGH);
  pinMode(enc_PinB, INPUT_PULLUP); digitalWrite(enc_PinB, HIGH);
  pinMode(enc_Switch, INPUT_PULLUP); digitalWrite(enc_Switch, HIGH);

  attachInterrupt(0, rotEncoder, CHANGE);
  attachInterrupt(1, swEncoder, CHANGE);

  RTC.begin();
  if (!RTC.isrunning()) {
    RTC.adjust(DateTime(__DATE__, __TIME__));
    if(doSerial) Serial.println(" (RTC reset)");
  } else {
    if(doSerial) Serial.println(" (RTC running)");
  }
}

void loop() {
  DateTime now = RTC.now();
  display_message = createMessage(now);
  arraylen = initDisplayString(display_message);
  if(updateFlag) { show_time_and_date(now); updateFlag = false; }

  while(rotating) {
    delay(1);
    adjTime(now, clockwise);
    show_time_and_date(RTC.now());
    display_message = createMessage(now);
    arraylen = initDisplayString(display_message);
    delay(1);
    rotating = false;
  }
  delay(5);

  for(int i=0; i < (arraylen-7); i++) {
    for(int j=1; j<9; j++) maxSingle(j, ac[i+8-j]);
    if(i % (8+cblanks) == 0) {
      if(charHI) maxSingle(max7219_reg_intensity, 0x01);
      newDelay(delay_char);
    } else {
      maxSingle(max7219_reg_intensity, 0x00);
      newDelay(delay_line);
    }
  }
  if(mode == 0) newDelay(delay_mess);
}

void rotEncoder() {
  delay(1);
  enc_A = digitalRead(enc_PinA);
  enc_B = digitalRead(enc_PinB);
  if(!enc_A && enc_A_prev) {
    clockwise = (!enc_A && enc_B);
    if(mode != 0) rotating = true;
  }
  enc_A_prev = enc_A;
}

void swEncoder() {
  delay(1);
  if(digitalRead(enc_Switch) != LOW) return;
  delay(1);
  if(digitalRead(enc_Switch) != LOW) return;
  mode = (mode + 1) % 3;
  digitalWrite(mode_Pin, !(mode == 1));
  digitalWrite(min_Pin, !(mode == 2));
  updateFlag = true;
}

void newDelay(int dly) {
  for(int z=1; z= 25) h = 1; }
    else { if(h == 0) h = 24; if(--h <= 0) h = 24; }
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), h, now.minute(), now.second()));
  }
  if(mode == 2) {
    int m = now.minute();
    if(dir) { if(++m >= 60) m = 0; }
    else { if(--m < 0) m = 59; }
    RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), m, now.second()));
  }
}

byte rotChar(char inLetter) {
  int ind = int(inLetter) - 0x20;
  for(int col=0; col<8; col++) {
    byte mask = 0x01 << (7-col);
    for(int row=0; row<8; row++) bitWrite(rc[col], 7-row, (alphanum[ind][row] & mask));
  }
}

void show_time_and_date(DateTime dt) {
  if(doSerial) {
    int h = dt.hour(); if(h==0) h=24;
    int m = dt.minute(), s = dt.second();
    String te = "Current date/time: " + String(dt.year()) + "/" + dt.month() + "/" + dt.day() + " ";
    if(h<10) te += "0"; te += h; te += ":";
    if(m<10) te += "0"; te += m; te += ":";
    if(s<10) te += "0"; te += s;
    Serial.println(te);
  }
}

String createMessage(DateTime dt) {
  String msg = " ";
  int hr = dt.hour() % 24; if(hr==0) hr=24;
  int mn = dt.minute();
  if(mode == 0) {
    if(hour24) msg += hr; else msg += (hr>12? hr-12:hr);
    msg += ':'; if(mn<10) msg += '0'; msg += mn;
    if(!hour24) msg += (hr>12? "~" : "^");
  }
  if(mode == 1) msg += hr;
  if(mode == 2) { if(mn<10) msg += '0'; msg += mn; }
  return msg;
}

int initDisplayString(String message) {
  int x=0;
  for(int y=0; y0; i--) {
    mask = 0x01 << (i-1);
    digitalWrite(clock, LOW);
    digitalWrite(dataIn, (data & mask) ? HIGH : LOW);
    digitalWrite(clock, HIGH);
  }
}

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

Схема показывает подключение матрицы MAX7219 (DIN=12, CLK=11, CS=10), RTC DS3231 (SDA=A4, SCL=A5), энкодера (A=2, B=4, SW=3) и индикаторных LED (mode=8, min=9).

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

  1. Arduino POV-часы: сборка дисплея на эффекте сохранения образа
  2. Ретро-часы на индикаторах Numitron с Arduino: просто, надёжно, экономно
  3. Создание пользовательских LED-часов с будильником — видно с 12 метров
  4. Tetris на Arduino Nano: самостоятельная сборка 16×8 LED-матрицы на 74HC595
  5. MotionSense: умная система обнаружения проникновения на Arduino и ESP8266
  6. Интерактивный LED-дисплей в двери с PIR-датчиком — новогоднее приветствие на Arduino
  7. Пошаговое руководство: сборка умного четырёхногого робота на Arduino
  8. Бесшовное управление яркостью светодиодов с помощью Bolt IoT и Arduino UNO
  9. Веб-управляемый IoT-индикатор на Arduino, Yaler и IFTTT
  10. Магнитная левитация на отталкивании с Arduino: Простая схема и DIY-руководство