Things used in this project

Hardware components:
Photon new
Particle Photon
×1
Moving Coil 100uA
×2
MAX7219 8x8 LED-Matrix driver
×1
Software apps and online services:
Blynk logo avatars
Blynk

Code

OtherClocks.inoArduino
Code for the particle photon to display all 3 clocks (commends are partly in german - translation in progress)
// This #include statement was automatically added by the Particle IDE.

/*
Ausgabe der Uhrzeit auf 3 unterschiedliche Arten:
1. Binary-Clock
2. TIX-Clock
3. Analog mit 2 Drehspulinstrumenten

Die Ansteuerung erfolgt über einen MAX7219/7221 IC.
https://playground.arduino.cc/Main/MAX72XXHardware
http://playground.arduino.cc/Main/LedControl

Die Matrix wird um 90 Grad im Uhrzeigersinn gedreht, damit die Ansteuerung
einfacher realisiert werden kann.

Die Uhrzeit wird 1x am Tag über das Netzwerk synchronisiert


*/

// SYSTEM_MODE(SEMI_AUTOMATIC)     // Manual control of WiFi (start even WiFi ist not available)
// SYSTEM_THREAD(ENABLED)          // process code even Network not available

// def Bit-Operationen
#ifndef bitRead
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#endif


#include "LedControl-MAX7219-MAX7221.h" // Library for MAX7219
#include "blynk.h"                      // Connection to Blynk
#include "privateStuff.h"               // Place, where private Tokens and Passwords are stored


// Definition of WiFi-Connection
const uint32_t msRetryDelay = 5*60000; // retry WiFi-Connection every 5min
const uint32_t msRetryTime  =   30000; // stop trying WiFi-Connect after 30sec

bool retryRunning = false;
Timer retryTimer(msRetryDelay, retryConnect);  // timer to retry connecting
Timer stopTimer(msRetryTime, stopConnect);     // timer to stop a long running try

// create the LedControl 
#define lc_data A5
#define lc_load A4
#define lc_myclock A3

LedControl lc = LedControl(lc_data, lc_myclock, lc_load,1); 

// Pins for Analog-Clock
#define hourPin D0
#define minutePin D1

// Definition of Variables
uint8_t tixWait = 4;        // new Sequence for Tix-Clock all x Seconds

bool showBinary = true; 
bool showTix = true;
bool showAnalog = true;

uint8_t actHour = 0;        // actual Time
uint8_t actHour12 = 0;
uint8_t actMinute = 0;
uint8_t actSecond = 0;
uint8_t actDay = 1;
uint8_t actMonth = 1;
uint8_t actWeekday = 0;
uint8_t row[8];                     // 8 Rows of LED-Matrix
uint8_t sequence[9];                // generated Sequence Tix
uint8_t sequenceMinE[9];            // Sequence Einerstelle Minute Tix
uint8_t sequenceMinZ[6];            // Sequence Zehnerstelle Minute Tix
uint8_t sequenceHourE[9];           // Sequence Einerstelle Hour Tix
uint8_t sequenceHourZ[3];           // Sequence Zehnerstelle Hour Tix
uint8_t oldMinute, oldSecond = 0;   // Buffer of "old Minute" and "old Second"

#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)    // 24 Hours in ms
unsigned long lastSync = millis();


// define Blynk-Buttons (Blynk-Remote on iPhone)
BLYNK_WRITE(V0) {

    int i=param.asInt();
    if (i==1) {
        showBinary = true;
    }
    else {
        showBinary = false;
    }
}

BLYNK_WRITE(V1) {

    int i=param.asInt();
    if (i==1) {
        showTix = true;
    }
    else {
        showTix = false;
    }
}

BLYNK_WRITE(V2) {

    int i=param.asInt();
    if (i==1) {
        showAnalog = true;
    }
    else {
        showAnalog = false;
    }
}

BLYNK_WRITE(V9) {    // Einstellen der Helligkeit
    
    int i=param.asInt();
    lc.setIntensity(0,i);
}



void setup() {
 
    Time.zone(+1);  // Definition of timezone

    // Serial Console
    Serial.begin(9600);

    // wake up the MAX72XX from power-saving mode 
    // set a medium brightness for the Leds (0-15) 
    lc.shutdown(0,false); 
    lc.setIntensity(0,1); 
    
    // Set Pinmode
    pinMode(hourPin, OUTPUT);
    pinMode(minutePin, OUTPUT);


    // Verbinden mit der Cloud --> Synchronisierung der Zeit
    Particle.connect();
    if (!waitFor(Particle.connected, msRetryTime)) {
        Serial.println("Not connected to Cloud");
        WiFi.off();                // no luck, no need for WiFi
    }
    else {
        Serial.println("Connected to Cloud");
    }

//    Time.setTime(1512172680);   // Testzeit

    // activate Blynk
    Blynk.begin(BLYNK_AUTH_TOKEN);  // Code is defined in privateStuff.h
    
}


void loop() {

    Blynk.run();    //start Blynk

    if (millis() - lastSync > ONE_DAY_MILLIS && Particle.connected()) { 
        // Request time synchronization from the Particle Cloud once a day
        Particle.syncTime();
        lastSync = millis();
    }

    // Get the current time
    actHour = Time.hour();
    actHour12 = Time.hourFormat12();
    actMinute = Time.minute();
    actSecond = Time.second();
    actDay = Time.day();
    actMonth = Time.month();
    actWeekday = Time.weekday() - 1;  // Sonntag = 0; Montag = 1; ... Samstag = 6

    checkSummertime();
    

    // clear Array (löscht die LED-Matrix)
    memset(row,0,sizeof(row));

    
    // generate Binary-Clock
    if (showBinary == true) {
        BinaryClock();
    }
    
    // generate Tix-Clock
    if (showTix == true) {
        TixClock();
    }

    // generate Analog-Clock
    if (showAnalog == true) {
        AnalogClock();
    }


    // Show on 8x8 LED-Matrix
    for(int i = 0; i <= 7; i++) {
        lc.setRow(0,i,row[i]);
    }



    // Reconnect to WiFi if not available in the past
    if (!retryRunning && !Particle.connected()) { // if we have not already scheduled a retry and are not connected
        Serial.println("schedule");
        stopTimer.start();         // set timeout for auto-retry by system
        retryRunning = true;
        retryTimer.start();        // schedul a retry
    }
}



// **************************
// *****  Binary Clock  *****
// **************************
void BinaryClock() {

    // zerlegen in Zehner- und Einer-Stellen
    row[5] = numZ(actHour);
    row[4] = numE(actHour);
    row[3] = numZ(actMinute);
    row[2] = numE(actMinute);
    row[1] = numZ(actSecond);
    row[0] = numE(actSecond);
}


// ***********************
// *****  Tix Clock  *****
// ***********************
void TixClock() {
        
    int i;

    // generieren einer neuen Sequenz alle "tixWait" Sekunden
    if(actSecond % tixWait == 0 && oldSecond != actSecond) {

        // Einerstelle Minuten
        generateSequence(9);
        for(i = 0; i < 9; i++) {
            sequenceMinE[i] = sequence[i];
        }
        
        // Zehnerstelle Minuten
        generateSequence(6);
        for(i = 0; i < 6; i++) {
            sequenceMinZ[i] = sequence[i];
        }
        
        // Einerstelle Stunden
        generateSequence(9);
        for(i = 0; i < 9; i++) {
            sequenceHourE[i] = sequence[i];
        }
        
        // Zehnerstelle Stunden
        generateSequence(3);
        for(i = 0; i < 3; i++) {
            sequenceHourZ[i] = sequence[i];
        }
        
        oldSecond = actSecond;      // maximal 1x pro Sekunde eine neue Sequenz
    }
    

    // Aktivieren Anzahl LEDs Einer-Stelle Minuten    
    for(i = 0; i < numE(actMinute); i++) {
        bitSet(row[sequenceMinE[i]/3], 7-sequenceMinE[i]%3);
    }
        
    // Aktivieren Anzahl LEDs Zehner-Stelle Minuten    
    for(i = 0; i < numZ(actMinute); i++) {
        bitSet(row[sequenceMinZ[i]/3+3], 7-sequenceMinZ[i]%3);
    }
    
    // Aktivieren Anzahl LEDs Einer-Stelle Stunden    
    for(i = 0; i < numE(actHour); i++) {
        bitSet(row[sequenceHourE[i]/3+5], 7-sequenceHourE[i]%3);
    }
    
    // Aktivieren Anzahl LEDs Zehner-Stelle Stunden
    for(i = 0; i < numZ(actHour); i++) {
        bitSet(row[sequenceHourZ[i]/3+7], 2-sequenceHourZ[i]%3);
    }
}


// **************************
// *****  Analog Clock  *****
// **************************
void AnalogClock() {

    analogWrite(hourPin, actHour12*20);
    analogWrite(minutePin, actMinute*4);

    
}



// *******************************************************************
// *****  Funktionenen zum Zerlegen in Zehner- und Einerstellen  *****
// *******************************************************************
int numZ(int num) {   // Zehnerstelle berechnen 
    num = num / 10; // Integer division by 10 (discard remainder) 
    return num; 
}
    
int numE(int num) {   // Einerstelle berechnen  
    num = num % 10; // Modulo division by 10 (keep remainder only) 
    return num; 
} 


// ****************************************************
// *****  Funktion zur Ermittlung der Sommerzeit  *****
// ****************************************************
void checkSummertime() {
    
    if ( ( actMonth > 3 && actMonth < 10 ) ||                                       // April - September
         ( actMonth == 3 && actDay >= 25 && actWeekday == 0  && actHour >= 2 ) ||   // letzter Sonntag im März, ab 2 Uhr
         ( actMonth == 3 && actDay - actWeekday >= 25 && actWeekday > 0 ) ||        // Tag liegt nach dem letzten Sonntag im März
         ( actMonth == 10 && actDay >= 25 && actWeekday == 0 && actHour < 2 ) ||    // letzter Sonntag im Oktober, bis 2 Uhr
         ( actMonth == 10 && actDay - actWeekday < 25 ) ) {                         // Tag liegt vor dem letzten Sonntag im Oktober

        Time.beginDST();    // Sommerzeit
    } else {
        Time.endDST();      // keine Sommerzeit
    }
}


// ************************************************************
// *****  Ausgabe der Uhrzeit auf serielle Schnittstelle  *****
// ************************************************************
void printKonsole() {

    Serial.print(actHour);
    Serial.print(":");
    Serial.print(actMinute);

    Serial.print(" (DST: ");
    Serial.print(Time.isDST());
    Serial.print(")");
    
    Serial.print(" Wochentag: ");
    Serial.print(actWeekday);
    
    Serial.println();
}


// **********************************************************
// *****  generate Sequence (0 to n-1 in random order)  *****
// **********************************************************
void generateSequence(int n) {

    int i, j, temp;
 
    // generate sorted sequence from 0 to n-1
    for (i = 0; i < n; i++) {    
        sequence[i] = i;
    }

    // random permutation (algorithm by Ronald Fisher and Frank Yates)  
    //  randomSeed(millis());         // really random
    for (i = n-1; i > 0; i--) {
        j = random(0, i+1);
        temp = sequence[i];         // swap sequence[i] with sequence[j]
        sequence[i] = sequence[j];
        sequence[j] = temp;
    }
}




// ******************************************
// *****  Routinen für WLAN-Verbindung  *****
// ******************************************
void retryConnect() {

    if (!Particle.connected()) {   // if not connected to cloud
        Serial.println("reconnect");
        stopTimer.start();         // set of the timout time
        WiFi.on();
        Particle.connect();        // start a reconnection attempt
    }
    else {                        // if already connected
        Serial.println("connected");
        retryTimer.stop();         // no further attempts required
        retryRunning = false;
    }
}

void stopConnect()
{
    Serial.println("stopped");

    if (!Particle.connected()) // if after retryTime no connection
      WiFi.off();              // stop trying and swith off WiFi
    stopTimer.stop();
}
privateStuff.hArduino
In this file all secret numbers are stored. Add this code to the original-code or put it in an additional file.
https://docs.particle.io/guide/getting-started/build/photon/#adding-files-to-your-app
/*
AUTH_TOKEN.h

Store private tokens in AUTH_TOKEN.h and add that
file to .gitignore so personal data is not shared

*/

// #define BLYNK_AUTH_TOKEN "store-real-blynk-token-here"
#define BLYNK_AUTH_TOKEN "store-real-blynk-token-here"

Credits

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

Particle Photon Based Security System with Alerting
Intermediate
  • 1,345
  • 20

Full instructions

Be alerted to any door or window opening and closing in your house on your smart phone.

Happy Plant Notifier
Intermediate
  • 290
  • 5

Full instructions

Get a text or call if your plant is getting too dry, along with a nice LCD display giving information regarding your plant's health.

My Guardian for the Workshop
Intermediate
  • 196
  • 4

Full instructions

Device will send emails if the door or window has been opened, and will monitor the temperature and humidity of the place.

Smart and Safe Outdoor Plant Watering System
Intermediate
  • 2,526
  • 18

Monitors soil moisture and weather forecasts to give plants just the water they need. Safe garden hose hookup for season long watering.

Christmas Gift Box
Intermediate
  • 3,684
  • 595

Full instructions

Christmas Gift Box plays music and sends an email when it is opened.

Carbon Fiber Vacuum Chamber
Intermediate
  • 3,035
  • 94

Full instructions

Our project is a carbon fiber vacuum chamber that is monitored by multiple particle photons and various sensors.

Add projectSign up / Login