/* * Side Lit 4 digit LED (LIXIE) display that shows time and temperature * Arduino Uno sketch * Rev: May. 16, 2023 G. Forrest Cook * License: GPL V3 * * Control a 4 digit 1-of-10 LED display via three 74HC595 chips * on the SPI port (11)(MOSI) & (13)(SCK). * '595 output latch on digital (10) (SS) * Byte 1 is the +/- signs and decimal points, byte 2 is the left 2 digits, * byte 3 is the right 2 digits. * * Dallas Semiconductor DS18B20 one-wire temp sensor(s) on D8 (port B0) * Sensors work more reliably with VCC on pin 3 instead of parasitic power * Sensor pinout is Gnd (black) Data (red), Vdd (white) * The data line requires a 4.7K pull-up resistor to +5V * read left to right, T092 pins down, flat side forward * * Dallas DS3231 real-time clock chip on the I2C bus. * Time is set via three pushbuttons on digital 5, 6 and 7. * The inputs are pulled up to +5V through 4.7K resistors and grounded * when the buttons are pushed. */ #include #include #include #include "RTClib.h" #define ts1Pin 5 // time set switch #1 #define ts2Pin 6 // time set switch #2 #define ts3Pin 7 // time set switch #3 #define ONE_WIRE_BUS 8 // DS18B20 sensor(s) on Digital 8 pin #define csPin 10 // 74LS595 latch pin (SS), MISO is only good for 8 bits #define DTIME1 60 // speed of start-up decimal point animation #define DTIME2 200 // speed of random digits #define DTIME3 300 // display blanking time #define DTIME4 4000 // time display time #define DTIME5 3000 // number of temp sensors display time #define DTIME6 400 // adjust time loop time #define DTIME7 600 // temperature display time OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); RTC_DS3231 rtc; // Dallas real-time clock byte lobyte, hibyte, extbyte; // global display state byte tsensors; // count of temperature sensors byte units; // 0 for F, 1 for C float temp; // Initialize and start up everything void setup() { static byte startpat[] = {1,2,4,8,32,8,4,2,1,2,4,8,32,8,4,2,1}; byte i; extbyte=0; units=0; // Serial.begin (9600); // Setkup serial for debugging // Serial.println ("Starting"); SPI.setBitOrder(MSBFIRST); SPI.begin(); // beware, SPI initializes port B. pinMode (csPin, OUTPUT); // Repurpose the SS pin for the 595 latch digitalWrite(csPin, LOW); pinMode (ts1Pin, INPUT); // Time set pushbutton #1 pinMode (ts2Pin, INPUT); // Time set pushbutton #2 pinMode (ts3Pin, INPUT); // Time set pushbutton #3 sensors.begin(); // start up the DS18B20 temperature sensors. rtc.begin(); // start up the real-time clock if (rtc.lostPower()) // set the initial date to the compile time. rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); for (i=0; i<=16; i++) // display a moving decimal point sequence { LEDsout (startpat[i], 0xFF, 0xFF); delay (DTIME1); } tsensors = sensors.getDeviceCount(); // show # of temperature sensors LEDint(tsensors, 1, 0); delay (DTIME5); LEDsout (0, 0xFF, 0xFF); // blank the display. } void loop() { byte tloop; BtnCheck (); // check for time set buttons LEDsout(0, 0xFF, 0xFF); // blank the display briefly delay (DTIME3); LEDhourmin (1); // display the time in 24 hour format. delay (DTIME4); // reading the temperature takes about 1 second. // a disconnected temperature sensor returns -196.6 F for (tloop=0; tloop12) hour-=12; else if (hour == 0) hour = 12; } hibyte = hour % 10; hour /= 10; nib4 = (hour % 10) * 16; hibyte |= nib4; LEDsout(extbyte, hibyte, lobyte); } // Send a positive integer to the display, optional leading zero blank and sign. void LEDint (int dval, byte zblank, byte sign) { byte nib2, nib3, nib4; extbyte &= 0x0F; // save the d.p. if (sign) // add +/- if requested { if (dval < 0) // set the +/- sign { extbyte |= 16; dval = 0-dval; } else extbyte |= 32; } lobyte = 0; hibyte = 0; lobyte |= dval % 10; dval /= 10; nib2 = (dval % 10) * 16; lobyte |= nib2; dval /= 10; nib3 = dval % 10; hibyte |= nib3; dval /= 10; nib4 = (dval % 10) * 16; hibyte |= nib4; if (zblank) // leading zero blanking { if (!nib4) { hibyte |= 0xF0; if (!nib3) { hibyte = 0xFF; if (!nib2) lobyte |= 0xF0; } } } LEDsout(extbyte, hibyte, lobyte); } // Send a 2 digit integer to the right side of the display. void LED2dig (int val) { byte nibl; extbyte = 0x00; // turn off +/- and d.p. hibyte = 0xFF; // blank the top 2 digits lobyte = val % 10; val /= 10; nibl = (val % 10) * 16; lobyte |= nibl; LEDsout(extbyte, hibyte, lobyte); } // Store zeros on all four digit memories. void LEDzeros () { lobyte = 0; hibyte = 0; } // Send a nibble to one digit memory, leave other digits as-is void LEDdigit (byte dnum, byte dignib) { byte savnib; switch (dnum) { case 0: savnib = lobyte & 0xF0; lobyte = dignib | savnib; break; case 1: savnib = lobyte & 0x0F; lobyte = (dignib * 16) | savnib; break; case 2: savnib = hibyte & 0xF0; hibyte = dignib | savnib; break; case 3: savnib = hibyte & 0x0F; hibyte = (dignib * 16) | savnib; break; } } // Send a decimal point to the extras memory, 0 for no d.p.. void LEDdp (byte dpnum) { byte savext; savext=extbyte&0x30; // save the +/- state switch (dpnum) { case 0: extbyte=savext; break; case 1: extbyte=savext|1; break; case 2: extbyte=savext|2; break; case 3: extbyte=savext|4; break; case 4: extbyte=savext|8; break; } } // Send a +/- sign to the extras memory, 0 for no sign void LEDsign (byte sign) { byte savext; savext=extbyte&0x0F; switch (sign) { case 0: extbyte=savext; break; case 1: extbyte=savext|16; break; case 2: extbyte=savext|32; break; } } // output to the LED display, decimals/extras, hi digits, lo digits void LEDsout(byte high, byte med, byte low) { SPI.transfer(high); // Shift out decimal points and +/- SPI.transfer(med); // Shift out the high data byte SPI.transfer(low); // Shift out the low data byte digitalWrite(csPin, HIGH); // pulse the '595 output latch pin delayMicroseconds(10); digitalWrite(csPin, LOW); }