Hackster is hosting Hackster Holidays, Ep. 4: Livestream & Giveaway Drawing. Start streaming on Wednesday!Stream Hackster Holidays, Ep. 4 on Wednesday!
Mirko Pavleski
Published © GPL3+

Big LED Matrix Clock

Alarm clock on homemade 24x6 matrix with 144 8mm white LEDs.

IntermediateFull instructions provided7,278
Big LED Matrix Clock

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
HC-05 Bluetooth Module
HC-05 Bluetooth Module
×1
DS3231M - ±5ppm, I2C Real-Time Clock
Maxim Integrated DS3231M - ±5ppm, I2C Real-Time Clock
×1
Tactile Switch, Top Actuated
Tactile Switch, Top Actuated
×3
8mm Strawhat LED
×144
CD4017 IC
×1
74HC595 IC
×3
General Purpose Transistor NPN
General Purpose Transistor NPN
×6
Resistor 221 ohm
Resistor 221 ohm
×24

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Fritzing schematic

matrix driver

matrix

Code

Alarm Clock code

C/C++
/*
 * LED Matrix Alarm Clock with MP3 shield
 * The LED matrix is controlled by shift registers
 * Marek Cermak
 */
#include <SPI.h>
#include <MD_DS1307.h>

//---------------------------------GENERAL-----------------------------------
int allBtnStates;
unsigned long btnTimeStamp = 0;
#define ButtonA 5
#define ButtonB 6
#define ButtonC 7
#define playPin 2
#define stopPlay 3
uint8_t A;
uint8_t B;
uint8_t C;
uint8_t alarmHours = 7;
uint8_t alarmMinutes = 0;
uint8_t i = 0;
bool menuEntered = false;
bool isAlarmSet = false;
bool alarmNow = false;
bool stopAlarm = false;

//--------------------------------LED MATRIX----------------------------------

uint8_t hours;
uint8_t minutes;
uint8_t letA;
uint8_t letB;
uint8_t letC;
uint8_t letD;
//Pin connected to ST_CP of 74HC595
const uint8_t g_nPin_ShiftLatch = 10;
//Pin connected to SH_CP of 74HC595
const uint8_t g_nPin_ShiftClock = 13;
////Pin connected to DS of 74HC595
const uint8_t g_nPin_ShiftData = 11;
const uint8_t g_nPin_CounterClock = 9;
const uint8_t g_nPin_CounterReset = 8;
const uint8_t g_nRows = 6;
const uint8_t g_nColumns = 24;
uint32_t g_pDisplayBuffer[g_nRows] = { 0 };

typedef enum DISPLAY_CHAR : uint8_t
{
  DISPLAY_CHAR_0 = 0,
  DISPLAY_CHAR_1,
  DISPLAY_CHAR_2,
  DISPLAY_CHAR_3,
  DISPLAY_CHAR_4,
  DISPLAY_CHAR_5,
  DISPLAY_CHAR_6,
  DISPLAY_CHAR_7,
  DISPLAY_CHAR_8,
  DISPLAY_CHAR_9,
  DISPLAY_CHAR_A,
  DISPLAY_CHAR_B,
  DISPLAY_CHAR_C,
  DISPLAY_CHAR_D,
  DISPLAY_CHAR_E,
  DISPLAY_CHAR_F,
  DISPLAY_CHAR_G,
  DISPLAY_CHAR_H,
  DISPLAY_CHAR_I,
  DISPLAY_CHAR_J,
  DISPLAY_CHAR_K,
  DISPLAY_CHAR_L,
  DISPLAY_CHAR_M,
  DISPLAY_CHAR_N,
  DISPLAY_CHAR_O,
  DISPLAY_CHAR_P,
  DISPLAY_CHAR_Q,
  DISPLAY_CHAR_R,
  DISPLAY_CHAR_S,
  DISPLAY_CHAR_T,
  DISPLAY_CHAR_U,
  DISPLAY_CHAR_V,
  DISPLAY_CHAR_W,
  DISPLAY_CHAR_X,
  DISPLAY_CHAR_Y,
  DISPLAY_CHAR_Z,
  DISPLAY_CHAR_BLANK,
  DISPLAY_CHAR_FULL,
  DISPLAY_CHAR_DOT,
  DISPLAY_CHAR_DOUBLEDOT,


  DISPLAY_CHAR_COUNT,
} DISPLAY_CHAR;

const uint8_t g_pChar_Blank[] = { B00000000, B00000000, B00000000, B00000000, B00000000, B00000000};
const uint8_t g_pChar_1[] = { B00100000, B01100000, B00100000, B00100000, B00100000, B00000000};
const uint8_t g_pChar_2[] = { B11110000, B00010000, B11110000, B10000000, B11110000, B00000000};
const uint8_t g_pChar_3[] = { B11110000, B00010000, B11110000, B00010000, B11110000, B00000000 };
const uint8_t g_pChar_4[] = { B10010000, B10010000, B11110000, B00010000, B00010000, B00000000 };
const uint8_t g_pChar_5[] = { B11110000, B10000000, B11110000, B00010000, B11110000, B00000000 };
const uint8_t g_pChar_6[] = { B11110000, B10000000, B11110000, B10010000, B11110000, B00000000 };
const uint8_t g_pChar_7[] = { B11110000, B10010000, B00010000, B00010000, B00010000, B00000000 };
const uint8_t g_pChar_8[] = { B11110000, B10010000, B11110000, B10010000, B11110000, B00000000 };
const uint8_t g_pChar_9[] = { B11110000, B10010000, B11110000, B00010000, B11110000, B00000000 };
const uint8_t g_pChar_0[] = { B11110000, B10010000, B10010000, B10010000, B11110000, B00000000 };
const uint8_t g_pChar_A[] = { B01100000, B10010000, B11110000, B10010000, B10010000, B00000000 };
const uint8_t g_pChar_B[] = { B11100000, B10010000, B11100000, B10010000, B11100000, B00000000 };
const uint8_t g_pChar_C[] = { B01100000, B10010000, B10000000, B10010000, B01100000, B00000000 };
const uint8_t g_pChar_D[] = { B11100000, B10010000, B10010000, B10010000, B11100000, B00000000 };
const uint8_t g_pChar_E[] = { B11100000, B10000000, B11000000, B10000000, B11100000, B00000000 };
const uint8_t g_pChar_F[] = { B11100000, B10000000, B11000000, B10000000, B10000000, B00000000 };
const uint8_t g_pChar_G[] = { B01100000, B10000000, B10110000, B10010000, B01100000, B00000000 };
const uint8_t g_pChar_H[] = { B10010000, B10010000, B11110000, B10010000, B10010000, B00000000 };
const uint8_t g_pChar_I[] = { B11100000, B01000000, B01000000, B01000000, B11100000, B00000000 };
const uint8_t g_pChar_J[] = { B11100000, B00100000, B00100000, B10100000, B01000000, B00000000 };
const uint8_t g_pChar_K[] = { B10010000, B10100000, B11000000, B10100000, B10010000, B00000000 };
const uint8_t g_pChar_L[] = { B10000000, B10000000, B10000000, B10000000, B11100000, B00000000 };
const uint8_t g_pChar_M[] = { B10010000, B11110000, B10010000, B10010000, B10010000, B00000000 };
const uint8_t g_pChar_N[] = { B10010000, B11010000, B11110000, B10110000, B10010000, B00000000 };
const uint8_t g_pChar_O[] = { B01100000, B10010000, B10010000, B10010000, B01100000, B00000000 };
const uint8_t g_pChar_P[] = { B11000000, B10100000, B11000000, B10000000, B10000000, B00000000 };
const uint8_t g_pChar_Q[] = { B01100000, B10010000, B10010000, B10100000, B01110000, B00000000 };
const uint8_t g_pChar_R[] = { B11000000, B10100000, B11000000, B10100000, B10100000, B00000000 };
const uint8_t g_pChar_S[] = { B01100000, B10000000, B11000000, B00100000, B11000000, B00000000 };
const uint8_t g_pChar_T[] = { B11100000, B01000000, B01000000, B01000000, B01000000, B00000000 };
const uint8_t g_pChar_U[] = { B10010000, B10010000, B10010000, B10010000, B01100000, B00000000 };
const uint8_t g_pChar_V[] = { B10100000, B10100000, B10100000, B01000000, B01000000, B00000000 };
const uint8_t g_pChar_W[] = { B10010000, B10010000, B11110000, B11110000, B01100000, B00000000 };
//const uint8_t g_pChar_X[] = { B10100000, B10100000, B01000000, B10100000, B10100000, B00000000 };
const uint8_t g_pChar_X[] = { B00000000, B01000000, B00000000, B00000000, B00000000, B00010000 };
const uint8_t g_pChar_Y[] = { B10100000, B10100000, B01000000, B01000000, B01000000, B00000000 };
const uint8_t g_pChar_Z[] = { B11100000, B00100000, B01000000, B10000000, B11100000, B00000000 };
const uint8_t g_pChar_Full[] = { B11110000, B11110000, B11110000, B11110000, B11110000, B11110000 };
const uint8_t g_pChar_Dot[] = { B00000000, B00000000, B00000000, B00000000, B00000000, B00010000 };
const uint8_t g_pChar_DoubleDot[] = { B00000000, B11000000, B00000000, B11000000, B00000000, B00000000 };

const uint8_t* g_pDisplayChars[] =
{
  g_pChar_0,
  g_pChar_1,
  g_pChar_2,
  g_pChar_3,
  g_pChar_4,
  g_pChar_5,
  g_pChar_6,
  g_pChar_7,
  g_pChar_8,
  g_pChar_9,
  g_pChar_A,
  g_pChar_B,
  g_pChar_C,
  g_pChar_D,
  g_pChar_E,
  g_pChar_F,
  g_pChar_G,
  g_pChar_H,
  g_pChar_I,
  g_pChar_J,
  g_pChar_K,
  g_pChar_L,
  g_pChar_M,
  g_pChar_N,
  g_pChar_O,
  g_pChar_P,
  g_pChar_Q,
  g_pChar_R,
  g_pChar_S,
  g_pChar_T,
  g_pChar_U,
  g_pChar_V,
  g_pChar_W,
  g_pChar_X,
  g_pChar_Y,
  g_pChar_Z,
  g_pChar_Blank,
  g_pChar_Full,
  g_pChar_Dot,
  g_pChar_DoubleDot,
};

uint32_t g_nTimer_UpdateDisplay = 0;
const uint8_t g_nTimerPeriod_UpdateDisplay = 1;
uint32_t g_nTimer_UpdateText = 0;
const uint8_t g_nTimerPeriod_UpdateText = 130;
uint8_t g_nCharToDisplay = DISPLAY_CHAR_1;
uint8_t g_nCharPosition = 0;


void ClearDisplay(void)
{
  for (uint8_t i = 0; i < g_nRows; i++)
  {
    g_pDisplayBuffer[i] = 0;
  }
}

void DisplayChar(uint8_t nColumn, uint8_t nChar)
{

  if ((nColumn < g_nColumns) && (nChar < DISPLAY_CHAR_COUNT))
  {
    uint8_t* pChar = (uint8_t*)g_pDisplayChars[nChar];
    for (uint8_t i = 0; i < g_nRows; i++)
    {
      g_pDisplayBuffer[i] |= ((uint32_t)pChar[i]) << (24 - nColumn);
      //  Serial.println(g_pDisplayBuffer[i], BIN);
    }
  }
}

void UpdateDisplay(void)
{
  for (uint8_t nRow = 0; nRow < g_nRows; nRow++)
  {


    digitalWrite(g_nPin_ShiftLatch, LOW);
    SPI.transfer((uint8_t)((g_pDisplayBuffer[nRow] >> 24)));
    SPI.transfer((uint8_t)((g_pDisplayBuffer[nRow] >> 16)));
    SPI.transfer((uint8_t)((g_pDisplayBuffer[nRow] >> 8)));
    digitalWrite(g_nPin_ShiftLatch, HIGH);
    delayMicroseconds(500);
    
    digitalWrite(g_nPin_ShiftLatch, LOW);
    SPI.transfer(0);
    SPI.transfer(0);
    SPI.transfer(0);

    digitalWrite(g_nPin_ShiftLatch, HIGH);  
    digitalWrite(g_nPin_CounterClock, HIGH);  
    digitalWrite(g_nPin_CounterClock, LOW);
   
  }
  digitalWrite(g_nPin_CounterReset, HIGH);
  digitalWrite(g_nPin_CounterReset, LOW);

}


void setup()
{
  Serial.begin(115200);
  if (!RTC.isRunning())
    RTC.control(DS1307_CLOCK_HALT, DS1307_OFF);

  pinMode(g_nPin_ShiftLatch, OUTPUT);
  pinMode(g_nPin_ShiftClock, OUTPUT);
  pinMode(g_nPin_ShiftData, OUTPUT);
  pinMode(g_nPin_CounterClock, OUTPUT);
  pinMode(g_nPin_CounterReset, OUTPUT);
  digitalWrite(g_nPin_CounterReset, HIGH);
  digitalWrite(g_nPin_CounterReset, LOW);

  pinMode(ButtonA, INPUT_PULLUP);
  pinMode(ButtonB, INPUT_PULLUP);
  pinMode(ButtonC, INPUT_PULLUP);
  pinMode(playPin, OUTPUT);
  pinMode(stopPlay, OUTPUT);
  digitalWrite(playPin, HIGH);
  digitalWrite(stopPlay, LOW);

  SPI.begin();
  SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
  ClearDisplay();

  g_nTimer_UpdateDisplay = millis();
  g_nTimer_UpdateText = millis();
}

void ParseTime() {


  if (menuEntered == true) {
    hours = alarmHours;
  }

  //Serial.println(hours);
  if (hours < 10) {
    letB = hours;
    letA = 0;
  }
  else if (hours < 20) {
    letA = 1;
    letB = hours - 10;
  }
  else {
    letA = 2;
    letB = hours - 20;
  }


  if (menuEntered == true) {
    minutes = alarmMinutes;
  }

  if (minutes < 10) {
    letC = 0;
    letD = minutes;
  }
  else if (minutes < 20) {
    letC = 1;
    letD = minutes - 10;
  }
  else if (minutes < 30) {
    letC = 2;
    letD = minutes - 20;
  }
  else if (minutes < 40) {
    letC = 3;
    letD = minutes - 30;
  }
  else if (minutes < 50) {
    letC = 4;
    letD = minutes - 40;
  }
  else {
    letC = 5;
    letD = minutes - 50;
  }
}

void IsButtonPressed() {




  A = 1 - digitalRead(ButtonA);
  B = 1 - digitalRead(ButtonB);
  C = 1 - digitalRead(ButtonC);

  allBtnStates = A + 2 * B + 4 * C;
  if (allBtnStates < 7) { //Any button pressed
    if (btnTimeStamp == 0) btnTimeStamp = millis(); //Create timestamp
    else if (millis() - btnTimeStamp > 250) {
      switch (allBtnStates) {
        case 3: if (menuEntered) { //button to control hours
            if (alarmHours == 24) {
              alarmHours = 0;
            } else {
              alarmHours++;
            }
            ClearDisplay();
          } else if (alarmNow) { // snooze
           // Serial.println("snooze");
            alarmMinutes = alarmMinutes + 1;
            alarmNow = false;
            menuEntered = false;
            digitalWrite(playPin, HIGH); 
            digitalWrite(stopPlay, HIGH);
            if (alarmMinutes > 59) {
              alarmMinutes = alarmMinutes - 60;
            }
          }
          ; break;
        case 5: if (menuEntered) { //button to control minutes

            if (alarmMinutes == 60) {
              alarmMinutes = 0;
            } else {
              alarmMinutes++;
            }
            ClearDisplay();
          } else if (alarmNow) {//end alarm
           // Serial.println("endAlarm");
            alarmNow = false;
            stopAlarm = true;
            isAlarmSet = false;
            menuEntered = false;
            digitalWrite(playPin, HIGH);
            ClearDisplay();
            digitalWrite(stopPlay, HIGH);

          }
          ; break; 
        case 6: if (menuEntered) { // button right  .

            while (1 - digitalRead(ButtonA) == 0) {
              delay(100);
              i++;
              if (i == 15) {
                menuEntered = false;
                isAlarmSet = true;
              }
            }
          }; break;
        case 4: if (menuEntered == false) {//Both Left and Middle button pressed simultanously
            menuEntered = true;
            i = 0; break;

          } else {

            while ((1 - digitalRead(ButtonA) == 0) && (1 - digitalRead(ButtonB) == 0)) {// button right and center pressed together.
              delay(100);
              i++;
              if (i == 15) {
                menuEntered = false;
                isAlarmSet = false;
              }
            }

          }
          ; break;

      }
      btnTimeStamp = 0; //Reset timestamp
    }
  }

  if (menuEntered) {
    ParseTime();
  }

}

void loop()
{


  //DisplayChar(1, DISPLAY_CHAR_DOT);
  if (millis() > g_nTimer_UpdateDisplay)
  {
    IsButtonPressed();
    RTC.readTime();

    if (RTC.m != minutes && menuEntered == false) {
      hours = RTC.h;
      minutes = RTC.m;
      ClearDisplay();
      ParseTime();
      stopAlarm = false;
      digitalWrite(stopPlay, LOW);
    }

    DisplayChar(1, letA);
    DisplayChar(6, letB);
    DisplayChar(11, DISPLAY_CHAR_DOUBLEDOT);
    DisplayChar(14, letC);
    DisplayChar(19, letD);

    if (isAlarmSet) {

      DisplayChar(20, DISPLAY_CHAR_DOT);
      if (hours == alarmHours && minutes == alarmMinutes && stopAlarm == false && menuEntered == false) {
        alarmNow = true;
        digitalWrite(playPin, LOW);
      }
    }

    g_nTimer_UpdateText += g_nTimerPeriod_UpdateText;

    UpdateDisplay();
    g_nTimer_UpdateDisplay += g_nTimerPeriod_UpdateDisplay;
  }
}

Bluetooth moving text code

C/C++
#define BA {B01110000,B10001000,B10001000,B11111000,B10001000,B10001000}
#define BB {B11110000,B10001000,B10001000,B11110000,B10001000,B11111000}
#define BC {B11111000,B10000000,B10000000,B10000000,B10000000,B11111000}
#define BD {B11110000,B10001000,B10001000,B10001000,B10001000,B11110000}
#define BE {B11111000,B10000000,B10000000,B11110000,B10000000,B11111000}
#define BF {B11111000,B10000000,B10000000,B11110000,B10000000,B10000000}
#define BG {B01110000,B10001000,B10000000,B10011000,B10001000,B01110000}
#define BH {B10001000,B10001000,B11111000,B10001000,B10001000,B10001000}
#define BI {B11111000,B00100000,B00100000,B00100000,B00100000,B11111000}
#define BJ {B00111000,B00010000,B00010000,B00010000,B10010000,B01100000}
#define BM {B10001000,B11011000,B10101000,B10101000,B10001000,B10001000}
#define BN {B10001000,B11001000,B10101000,B10101000,B10011000,B10001000}
#define BL {B10000000,B10000000,B10000000,B10000000,B10000000,B11111000}
#define BO {B01110000,B10001000,B10001000,B10001000,B10001000,B01110000}
#define BP {B11110000,B10001000,B10001000,B11110000,B10000000,B10000000}
#define BQ {B01110000,B10001000,B10101000,B10011000,B01111000,B00001000}
#define BR {B11110000,B10001000,B10001000,B11110000,B10001000,B10001000}
#define BS {B01110000,B10001000,B01100000,B00010000,B10001000,B01110000}
#define BK {B10001000,B10010000,B11100000,B11100000,B10010000,B10001000}
#define BT {B11111000,B00100000,B00100000,B00100000,B00100000,B00100000}
#define BU {B10001000,B10001000,B10001000,B10001000,B10001000,B01110000}
#define BV {B10001000,B10001000,B10001000,B10001000,B01010000,B00100000}
#define BW {B10001000,B10001000,B10101000,B10101000,B10101000,B01010000}
#define BX {B10001000,B01010000,B00100000,B00100000,B01010000,B10001000}
#define BY {B10001000,B01010000,B00100000,B00100000,B00100000,B00100000}
#define BZ {B11111000,B00001000,B00110000,B01100000,B10000000,B11111000}
#define LA{B00000000,B01110000,B00001000,B01111000,B10001000,B01111000}
#define LB{B10000000,B10000000,B10110000,B11001000,B10001000,B11110000}
#define LC{B00000000,B01110000,B10000000,B10000000,B10001000,B01110000}
#define LD{B00001000,B00001000,B01111000,B10001000,B10001000,B01111000}
#define LE{B00000000,B01110000,B10001000,B11111000,B10000000,B01110000}
#define LF{B00110000,B01001000,B01000000,B11100000,B01000000,B01000000}
#define LG{B00000000,B01111000,B10001000,B01111000,B00001000,B01110000}
#define LH{B10000000,B10000000,B10110000,B11001000,B10001000,B10001000}
#define LI{B00100000,B00000000,B01100000,B00100000,B00100000,B01111000}
#define LJ{B00010000,B00000000,B00111000,B00010000,B10010000,B01100000}
#define LK{B10000000,B10010000,B10100000,B11000000,B10100000,B10010000}
#define LL{B01100000,B00100000,B00100000,B00100000,B00100000,B01111000}
#define LM{B00000000,B00000000,B11010000,B10101000,B10101000,B10001000}
#define LN{B00000000,B00000000,B10110000,B11001000,B10001000,B10001000}
#define LO{B00000000,B01110000,B10001000,B10001000,B10001000,B01110000}
#define LP{B00000000,B11110000,B10001000,B11110000,B10000000,B10000000}
#define LQ{B00000000,B01101000,B10011000,B01111000,B00001000,B00001000}
#define LR{B00000000,B00000000,B10110000,B11001000,B10000000,B10000000}
#define LS{B00000000,B01110000,B10000000,B01110000,B00001000,B11110000}
#define LT{B01000000,B01000000,B11100000,B01000000,B01001000,B00110000}
#define LU{B00000000,B00000000,B10001000,B10001000,B10011000,B01101000}
#define LV{B00000000,B00000000,B10001000,B10001000,B01010000,B00100000}
#define LW{B00000000,B00000000,B10001000,B10101000,B10101000,B01010000}
#define LX{B00000000,B10001000,B01010000,B00100000,B01010000,B10001000}
#define LY{B00000000,B10001000,B10001000,B01111000,B00001000,B01110000}
#define LZ{B00000000,B11111000,B00010000,B00100000,B01000000,B11111000}
#define SPACE{B00000000,B00000000,B00000000,B00000000,B00000000,B00000000}
#define NUM0{B01110000,B10011000,B10101000,B10101000,B11001000,B01110000}
#define NUM1{B00100000,B01100000,B10100000,B00100000,B00100000,B01110000}
#define NUM2{B01110000,B10001000,B00001000,B01110000,B10000000,B11111000}
#define NUM3{B11110000,B00001000,B00001000,B01111000,B00001000,B11110000}
#define NUM4{B10001000,B10001000,B10001000,B11111000,B00001000,B00001000}
#define NUM5{B11111000,B10000000,B11110000,B00001000,B10001000,B01110000}
#define NUM6{B11111000,B10000000,B11111000,B10001000,B10001000,B11111000}
#define NUM7{B11111000,B00001000,B00001000,B01111000,B00001000,B00001000}
#define NUM8{B11111000,B10001000,B11111000,B10001000,B10001000,B11111000}
#define NUM9{B11111000,B10001000,B11111000,B00001000,B00001000,B11111000}
#define DEVIDE{B00001000,B00010000,B00100000,B00100000,B01000000,B10000000}
#define TWODOTS{B01100000,B01100000,B00000000,B00000000,B01100000,B01100000}
#define DOT{B00000000,B00000000,B00000000,B00000000,B01100000,B01100000}
#define COMA{B00000000,B00000000,B00000000,B00110000,B00110000,B01100000}
#define LINE{B00000000,B00000000,B11111000,B11111000,B00000000,B00000000}
#define QUASTION{B01110000,B10001000,B00010000,B00100000,B00000000,B00100000}
#define MARK{B00100000,B01110000,B01110000,B00100000,B00000000,B00100000}

int latchPin = 10;
int clockPin = 13;
int dataPin = 11;
int clock = 9;
int Reset = 8;
int latchPinPORTB = latchPin - 8;
int clockPinPORTB = clockPin - 8;
int dataPinPORTB = dataPin - 8;
int i = 0;
int incomingByte[44];
long scrolling_word[6];
int array_turn=0;

boolean novZbor=false;

byte patterns[100][6];
byte dummy_array[70][6] ={BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,BM,BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,SPACE,NUM0,NUM1,NUM2,NUM3,NUM4,NUM5,NUM6,NUM7,NUM8,NUM9,DEVIDE,TWODOTS,DOT,COMA,LINE,QUASTION,MARK,LA,LB,LC,LD,LE,LF,LG,LH,LI,LJ,LK,LL,LM,LN,LO,LP,LQ,LR,LS,LT,LU,LV,LW,LX,LY,LZ};
void setup(){
  Serial.begin(9600);
  pinMode(dataPin,OUTPUT);
  pinMode(clockPin,OUTPUT);
  pinMode(latchPin,OUTPUT);
  pinMode(clock,OUTPUT);
  pinMode(Reset,OUTPUT);
  digitalWrite(Reset,HIGH);
  digitalWrite(Reset,LOW);
  setupSPI();
}

void display_word(int loops,byte word_print[][6],int num_patterns,int delay_langth){// this function displays your symbols
  i = 0;// resets the counter fot the 4017
  for(int g=0;g<6;g++)//resets the the long int where your word goes
    scrolling_word[g] = 0;
  for(int x=0;x<num_patterns;x++){//main loop, goes over your symbols
   // you will need to find a better way to make the symbols scroll my way is limited for 24 columns

   for(int r=0;r<6;r++)//puts the buildes the first symbol
      scrolling_word[r] |= word_print[x][r]; 
    for (int z=0;z<6;z++){//the sctolling action
        for(int p=0;p<6;p++)
          scrolling_word[p] = scrolling_word[p] << 1;
// end of the scrolling funcion
      for(int t=0;t<delay_langth;t++){// delay function, it just loops over the same display
        for(int y=0;y<6;y++){// scaning the display
          if(i == 6){// counting up to 6 with the 4017
            digitalWrite(Reset,HIGH);
            digitalWrite(Reset,LOW);
            i = 0;
          }
          latchOff();
          spi_transfer(make_word(0x01000000,y));// sending the data
          spi_transfer(make_word(0x00010000,y));
          spi_transfer(make_word(0x00000100,y));
          latchOn();
          delayMicroseconds(800);//waiting a bit
          latchOff();
          spi_transfer(0);// clearing the data
          spi_transfer(0);
          spi_transfer(0);
          latchOn();
          digitalWrite(clock,HIGH);//counting up with the 4017
          digitalWrite(clock,LOW);
          i++;
        }
      }
    }
  }
  finish_scroll(delay_langth);
}

void finish_scroll(int delay_scroll){// this function is the same as the funcion above, it just finishing scrolling
  for (int n=0;n<24;n++){
        for(int h=0;h<6;h++)
          scrolling_word[h] = scrolling_word[h] << 1;
      for(int w=0;w<delay_scroll;w++){
        for(int k=0;k<6;k++){
          if(i == 6){
            digitalWrite(Reset,HIGH);
            digitalWrite(Reset,LOW);
            i = 0;
          }
          latchOff();
          spi_transfer(make_word(0x01000000,k));
          spi_transfer(make_word(0x00010000,k));
          spi_transfer(make_word(0x00000100,k));
          latchOn();
          delayMicroseconds(800);
          latchOff();
          spi_transfer(0);
          spi_transfer(0);
          spi_transfer(0);
          latchOn();
          digitalWrite(clock,HIGH);
          digitalWrite(clock,LOW);
          i++;
        }
      }
    }
}

byte make_word (long posistion,byte turn){
  byte dummy_word = 0;
  for(int q=0;q<8;q++){
    if(scrolling_word[turn] & (posistion<<q))
      dummy_word |= 0x01<<q;
  }
  return dummy_word;
}   


  void loop() {

	// send data only when you receive data:
	if(Serial.available() > 0){
		
                if (novZbor == true){
			array_turn=0;
			novZbor = false;
		}
		
		delay(100);
		incomingByte[array_turn] = Serial.read();
                array_turn++;
	}
           else{
            
             if(array_turn != 0){ 
				novZbor = true;
               for(int az=0;az<array_turn;az++){
                 if((incomingByte[az] > 64 && incomingByte[az] < 91) || (incomingByte[az] > 96 && incomingByte[az] < 123)){
                  if(incomingByte[az] > 64 && incomingByte[az] < 91){
                   for(int lal=0;lal<6;lal++)                 
                 patterns[az][lal] = dummy_array[incomingByte[az] - 65][lal];
               }
               else{
                 for(int lal=0;lal<6;lal++)                 
                 patterns[az][lal] = dummy_array[incomingByte[az] - 53][lal];
               }}
               else{
                 switch(incomingByte[az]){
                case 32://space
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[26][lol];
                 break;
                case 33://mark
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[43][lol];
                 break;
                case 45://line
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[41][lol];
                 break;                 
                 case 44://coma
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[40][lol];
                 break;
                 case 46://dot
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[39][lol];
                 break;
                 case 47://dvide
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[37][lol];
                 break;
                 case 48://0
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[27][lol];
                 break;
                 case 49://1
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[28][lol];
                 break;
                 case 50://2
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[29][lol];
                 break;
                 case 51://3
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[30][lol];
                 break;
                 case 52://4
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[31][lol];
                 break;
                 case 53://5
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[32][lol];
                 break;
                 case 54://6
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[33][lol];
                 break;
                 case 55://7
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[34][lol];
                 break;
                 case 56://8
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[35][lol];
                 break;
                 case 57://9
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[36][lol];
                 break;
                 case 58://tow dots
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[38][lol];
                 break;
                 case 63://quastion
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[42][lol];
                 break;
                 default:
                 for(int lol=0;lol<6;lol++)                 
                 patterns[az][lol] = dummy_array[26][lol];
                 break; 
                 }
               }               
             }
           }
          
          
          display_word(1,patterns,array_turn,15);
          
          novZbor = true;
          // array_turn =0; 
         
       
     } 
      
     }
  
  //display_word(1,patterns,43,15);// calls for the display_pattern function and says that int loop = 15(if you do more loop the pattern whould scrrol slower).

void latchOn(){
  bitSet(PORTB,latchPinPORTB);
}

void latchOff(){
  bitClear(PORTB,latchPinPORTB);
}


void setupSPI(){
  byte clr;
  SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
  //SPCR |= ( (1<<SPR1) | (1<<SPR0) ); // set prescaler bits
  SPCR &= ~( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
  clr=SPSR; // clear SPI status reg
  clr=SPDR; // clear SPI data reg
  SPSR |= (1<<SPI2X); // set prescaler bits
  //SPSR &= ~(1<<SPI2X); // clear prescaler bits

  delay(10);
}
byte spi_transfer(byte data)
{
  SPDR = data;			  // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;			  // return the received byte, we don't need that
}

Credits

Mirko Pavleski

Mirko Pavleski

153 projects • 1299 followers

Comments