Things used in this project

Hardware components:
Photon new
Particle Photon
×1
12009 06
SparkFun Logic Level Converter - Bi-Directional
×1
SparkFun RS485 Transceiver
This board does not need a logic level converter as it operates at 3.3V A regular MAX485 breakout board can also be used instead of this, but with a converter to 5V
×1
Alfa Zeta XY5 Flip Dot Display 7x28
×1
24V 0.8A min DC Power Supply
×1
Software apps and online services:
Particle Web IDE

Schematics

Fritzing Diagram
Screen shot 2017 05 05 at 2 54 46 pm tahst4grz5

Code

FlipDotTimeCodeArduino
/*
* Using the Particle Photon to control an Alfa Zeta 7x28 flip dot display.
* The program displays the respective time in either 12 or 24 hour format.
* 
* Hardware Needed:
* - Particle Photon
* - Alfa Zeta flip dot display
* - RS485 converter (5V operating logic! The photon is 3.3V)
* - Logic level converter (optionally a MAX3485 chip for the RS485 converter can be used which operates at 3.3V OR 5V therefore eliminating this component)
* - 24V Power supply
* - 5V Power supply (USB power is fine)
* Date: May 5, 2017
* By: Mariano Elia
*/

//Each number from left to right in the 2D array, is the respective dots from right to left to be lit up 
//
  byte numbersInBinary[][4]{
  {0b111110, 0b100010, 0b100010, 0b111110}, //zero
  {0b111110, 0b000000, 0b000000, 0b000000}, //one
  {0b111010, 0b101010, 0b101010, 0b101110}, //two
  {0b111110, 0b101010, 0b101010, 0b100010}, //three
  {0b001000, 0b111110, 0b001000, 0b111000}, //four
  {0b101110, 0b101010, 0b101010, 0b111010}, //five
  {0b001110, 0b001010, 0b001010, 0b111110}, //six
  {0b111110, 0b100000, 0b100000, 0b110000}, //seven
  {0b111110, 0b101010, 0b101010, 0b111110}, //eight
  {0b111110, 0b101000, 0b101000, 0b111000} //nine

};

//To invert white with black, a ~ is used as a prefix
byte invertedNumbersInBinary[][4]{
  {~0b111110, ~0b100010, ~0b100010, ~0b111110}, //zero
  {~0b111110, ~0b000000, ~0b000000, ~0b000000}, //one
  {~0b111010, ~0b101010, ~0b101010, ~0b101110}, //two
  {~0b111110, ~0b101010, ~0b101010, ~0b100010}, //three
  {~0b001000, ~0b111110, ~0b001000, ~0b111000}, //four
  {~0b101110, ~0b101010, ~0b101010, ~0b111010}, //five
  {~0b001110, ~0b001010, ~0b001010, ~0b111110}, //six
  {~0b111110, ~0b100000, ~0b100000, ~0b110000}, //seven
  {~0b111110, ~0b101010, ~0b101010, ~0b111110}, //eight
  {~0b111110, ~0b101000, ~0b101000, ~0b111000} //nine
};
byte colonOn[]  = {0x0, 0x14, 0x0};
byte colonOff[] = {0x0, 0x0, 0x0};
byte invertedColonOn[] = {0x7F, 0x6D, 0x7F};
byte invertedColonOff[] = {0x7F, 0x7F, 0x7F};
byte space[] = {0x0};
byte invertedSpace[] = {0x7F};
//All pixels white
byte allWhite[] { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}; //equivalent to 0b1111111
//All pixels black
byte allBlack[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //equivalent to 0b0000000

//prepare the display to receive data.
byte startTransmission[] = {0x80, 0x83, 0xFF};
//confirm the end of the bytes sent
byte endTransmission[] = {0x8F};
int colonState = true;
unsigned long previousMillis = 0; 

/*
* Variables to change for customization
*/
const long interval = 1000; //interval in which to flip on and off the colon    
bool inverted = false; //choose to have black as digits, or as blank space
bool flashingColon = true;  //change to false if a static colon is wanted instead
int timeZone = -4; //change time zone


void setup() {
    //Serial is the usb port, Serial1 are the TX/RX pins, and Serial2 are the built in LED pins.
    //Serial1 is being used for this project.
   Serial1.begin(57600);  
   flipBlackAndWhite(); //start with a cool effect
}


void loop() {
    displayTime();
}


/*
* Retrieves the most recent time, and displays it on the flip dot.
* A flashing center colon is optional. 
*/
void displayTime(){

    //Retrieve the most recent time, and separate it up into individual integers
    int currentTime = getTime();
    int thousands = currentTime/1000; 
    int hundreds = currentTime%1000/100;
    int tens = ((currentTime%1000)%100)/10;
    int ones = ((currentTime%1000)%100)%10;
    //The display is 28 columns long. The columns are displayed right to left
    Serial1.write(startTransmission, 3); //send a 3 byte message to start the Serial communication
    displayDigit(-1); //three spaces on the right
    displayDigit(-1);
    displayDigit(-1);
    displayDigit(ones); //each digit is 4 columns long
    displayDigit(-1); //add a space in between digits
    displayDigit(tens);
    displayColon(); // 3 columns long
    displayDigit(hundreds);
    displayDigit(-1);
    displayDigit(thousands);
    displayDigit(-1); //add 4 spaces to the beginning
    displayDigit(-1);
    displayDigit(-1);
    displayDigit(-1);
    Serial1.write(endTransmission, 1); //Tell the flip dots to change
}
/*
* Uses Particle's time library to retrieve internet time. The time zone can be altered.
* Returns an int with the concatinated hour and minute. Ex 12:45 is 1245
*/
int getTime(){
    Time.zone(timeZone);
    //Uncomment if a 24 hour variant is wanted
    //return (Time.hour())*100+Time.minute(); //24 hour
    return (Time.hourFormat12())*100+Time.minute(); //12 hour
}

/*
* A single integer number to be displayed on the flip dots.
* A -1 signifies a space, which is one column wide and all black.
*/
void displayDigit(int num){
    if (!inverted){ 
    if (num == -1){
        Serial1.write(space, 1);
    }
    else{
    Serial1.write(numbersInBinary[num], 4);
    }
    }
    //else if it is inverted
    else {
        if (num == -1){
        Serial1.write(invertedSpace, 1);
    }
    
    else{
    Serial1.write(invertedNumbersInBinary[num], 4);
    }
    }
    
}

/*
* Displays the center colon in a flashing or static manner.
*/
void displayColon(){
     /*
    Instead of using a delay which stops the processor, a much better approach is to use a timer to
    turn on and off the colon separator when the proper time is reached.
    */
    if (flashingColon){ //*hint*, the same as if (flashingColon == true){
     unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) { //use a timer based delay
         previousMillis = currentMillis;
        if (colonState){
            if(!inverted) //if it is not inverted, display a normal colon
            Serial1.write(colonOn, 3);
            else
        Serial1.write(invertedColonOn, 3); //display an inverted colon
        colonState = false;
        }
        else {
            if(!inverted)
        Serial1.write(colonOff, 3);
        else
        Serial1.write(invertedColonOff, 3);
        colonState = true;
        }
    }
    }
    
    else { //choose between a static colon, or no colon
    if (!inverted){
    Serial1.write(colonOn, 3);
    //Serial1.write(colonOff, 3);
    }
    else{
    Serial1.write(invertedColonOn, 3);
    //Serial1.write(invertedColonOff, 3); 
    }
}
}
/*
* An effect which turns all pixels white, delays half a second, then black, then white again.
*/
void flipBlackAndWhite(){
    Serial1.write(startTransmission, 3);
    Serial1.write(allWhite, 28);
    Serial1.write(endTransmission, 1);
    delay(500);
    Serial1.write(startTransmission, 3);
    Serial1.write(allBlack, 28);
    Serial1.write(endTransmission, 1);
    delay(500);
     Serial1.write(startTransmission, 3);
    Serial1.write(allWhite, 28);
    Serial1.write(endTransmission, 1);
    delay(500);
}

Credits

Photo
Mariano Elia

Queen's University: Computer Engineering. RSGC High School

Contact
Thanks to iizukak.

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Arduino on Internal Oscillator Crystal as Clock Source
Intermediate
  • 670
  • 46

Protip

Want to make an Arduino having only an ATmega328 chip and nothing else? Not even the crystal oscillator!

Reducing Arduino Power Consumption
Intermediate
  • 1,097
  • 74

Protip

One the most important feature of portable electronics should be long battery life. We can reduce the current drawn by several ways.

Pi Zero Speaker - DIY Audio HAT and Audio Player
Intermediate
  • 385
  • 6

Work in progress

Convert an old speaker into something cool powered by Pi Zero.

RING PONG
Intermediate
  • 1,292
  • 6

A simple Ping Pong game played on a NeoPixel Ring with Arduino.

An Urban Plant Watering Solution
Intermediate
  • 3,845
  • 17

Full instructions

This is an automatic system controlled by an Arduino 101 that improves plant quality in our modern, urban society.

Simon Says Game Using Android Things
Intermediate
  • 230
  • 4

The classic Simon Says game running on Android Things.

ProjectsCommunitiesTopicsContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login