Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save somebox/53982aa0b38e804da79193437b9df2dc to your computer and use it in GitHub Desktop.
Save somebox/53982aa0b38e804da79193437b9df2dc to your computer and use it in GitHub Desktop.
#include <Arduino.h>
#include "ESP8266WiFi.h"
#include "SPI.h"
#include <NTPClient.h>
#include <WiFiUdp.h>
/*
A large four digit 7-segment LED clock, controlled by an ESP8266.
The LED modules are quite large, 5" tall, and require high voltage to drive the many
leds in series for each segment (12-14v). To do this, four shift registers are used in
series (TPIC6C596). These chips were purchased on breakout boards, based on a board
design by Sparkfun (https://learn.sparkfun.com/tutorials/large-digit-driver-hookup-guide/all).
It allows each digit of the large seven segments to be controlled with higer voltages.
As the ESP8266 is 3.3v logic, and the TPIC chip requires 5v logic, a level conversion was
required. A four channel 75HTC125N chip does the job here.
There are four connections to the ESP8266. Three for the shift register chips, and one
for the blinky dots (animated with PWM).
*/
char ssid[] = "SSID";
char pass[] = "mypassword";
#define PIN_CLK D6 // Clock on the TPIC6C596
#define PIN_LATCH D5 // Latch
#define PIN_DATA D7 // Serial data
#define PIN_DOTS D2 // Clock dots (colon)
#define PIN_BRIGHTNESS D4 // PWM Enable on TPIC6C596
#define DISPLAY_SIZE 4 // Number of digits
WiFiClient wifi;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 600000); // proto, host, timeOffset, updateInterval
int number = 0;
int t = 0;
int hour = 0;
int minute = 0;
void log_status_info()
{
Serial.print("ESP version: ");
Serial.println(ESP.getFullVersion());
Serial.print(" flash size: ");
Serial.println(ESP.getFlashChipRealSize());
Serial.print(" CPU MHz: ");
Serial.println(ESP.getCpuFreqMHz());
Serial.print(" chip ID: ");
Serial.println(ESP.getChipId());
Serial.print(" sketch size: ");
Serial.println(ESP.getSketchSize());
}
void connect_to_wifi()
{
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WiFiMode::WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
//showNumber(t);
t++;
delay(20);
}
t=0;
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("MAC address: ");
Serial.println(WiFi.macAddress());
Serial.print("RSSI: ");
Serial.print(WiFi.RSSI());
Serial.println("db");
delay(1000);
Serial.println("getting current time...");
timeClient.begin();
timeClient.update();
Serial.println(timeClient.getFormattedTime());
WiFi.mode(WiFiMode::WIFI_OFF);
}
//Given a number, or '-', shifts it out to the display
void postNumber(byte number, boolean decimal)
{
// --- A
// / / F, B
// --- G
// / / E, C
// --- . D, DP
#define a 1<<0
#define b 1<<6
#define c 1<<5
#define d 1<<4
#define e 1<<3
#define f 1<<1
#define g 1<<2
#define dp 1<<7
byte segments = 0;
switch (number)
{
case 1: segments = b | c; break;
case 2: segments = a | b | d | e | g; break;
case 3: segments = a | b | c | d | g; break;
case 4: segments = f | g | b | c; break;
case 5: segments = a | f | g | c | d; break;
case 6: segments = a | f | g | e | c | d; break;
case 7: segments = a | b | c; break;
case 8: segments = a | b | c | d | e | f | g; break;
case 9: segments = a | b | c | d | f | g; break;
case 0: segments = a | b | c | d | e | f; break;
case ' ': segments = 0; break;
case 'c': segments = g | e | d; break;
case '-': segments = g; break;
}
if (decimal) segments |= dp;
shiftOut(PIN_DATA, PIN_CLK, MSBFIRST, segments);
//Clock these bits out to the drivers
// for (byte x = 0 ; x < 8 ; x++)
// {
// digitalWrite(PIN_CLK, LOW);
// digitalWrite(PIN_DATA, segments & 1 << (7 - x));
// digitalWrite(PIN_CLK, HIGH); //Data transfers to the register on the rising edge of SRCK
// }
}
//Takes a number and displays 2 numbers. Displays absolute value (no negatives)
void showNumber(float value)
{
int number = abs(value);
digitalWrite(PIN_LATCH, LOW);
// update all digits of the display
for (byte x = 0 ; x < DISPLAY_SIZE ; x++)
{
int remainder = number % 10;
postNumber(remainder, false);
number /= 10;
}
//Latch the current segment data
digitalWrite(PIN_LATCH, HIGH); //Register moves storage register on the rising edge of RCK
}
void setup()
{
Serial.begin(115200);
Serial.println("Large Digit Driver Example");
pinMode(PIN_CLK, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
pinMode(PIN_LATCH, OUTPUT);
pinMode(PIN_DOTS, OUTPUT);
pinMode(PIN_BRIGHTNESS, OUTPUT);
digitalWrite(PIN_CLK, LOW);
digitalWrite(PIN_DATA, LOW);
digitalWrite(PIN_LATCH, LOW);
log_status_info();
connect_to_wifi();
}
void blankDisplay(){
digitalWrite(PIN_LATCH, LOW);
for (int i=0; i<4; i++){
shiftOut(PIN_DATA, PIN_CLK, MSBFIRST, 0);
}
digitalWrite(PIN_LATCH, HIGH); //Register moves storage register on the rising edge of RCK
}
int pmax = 100000;
int p = pmax;
int brightness = 0;
int bright_levels = 10;
bool debug = true;
int level = 0;
int last_level = 0;
int dot_level = 0;
void loop()
{
if (p++ > pmax){
hour = timeClient.getHours();
minute = timeClient.getMinutes();
p=0;
}
if (p % 3000 == 0){
last_level = level;
brightness = analogRead(A0);
level = map(brightness, 50, 1024, 1024, 0);
level = last_level + (level - last_level)/30; // slew changes, avoid jumps
level = max(50, level);
level = min(1005, level);
analogWrite(PIN_BRIGHTNESS, level);
}
dot_level = abs(map(millis() % 2000, 0, 1999, -1023, 1023));
analogWrite(PIN_DOTS, map(dot_level, 0, 1024, 0, 1024 - level * 0.9));
if (p % 1000) {
showNumber(hour*100+minute);
}
if (debug && p % 1000 == 0) {
Serial.print(" sensor: ");
Serial.print(analogRead(A0));
Serial.print(" level: ");
Serial.println(level);
}
//delayMicroseconds(100);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment