Hi Guys,
I’m relatively new to this and thought I’d share my first useful (sorta) sketch.
I’m building a HUGE LED clock, but so far I’ve only built a small display on a breadboard for testing. I’m working on getting the code done first.
I know a clock isn’t particularly exciting or original, but I wanted to do mine without the use of external driver or decoder ICs. I’ve seen lots of videos on youtube of people driving led displays with these ICs and usually doing a fairly useless count up from 0 to 9999.
I have common anode LED modules, the segment cathodes are driven directly by the arduino IO pins. The anodes are also driven by the arduino but via 4 transistors because the current would overload the arduino pins. (Each segment uses about 20mA.)
The multiplexing and INT > BCD > 7 Segment conversion is all done by the arduino so no external ICs (apart from the RTC and DS18B20 temp sensor).
I bought the RTC module via eBay from Hong Kong and it works a treat, and for less than £5 I’m not complaining.
This is still a work in progress so there’s more to come.
Things it does now:
-4 Digit multiplexing
-Reads time from RTC and displays in 24 hour format.
-Reads temperature from DS18B20 and displays in Celsius every 30 seconds.
Things to come:
-Ability to set the RTC via buttons.
-Make temperature scroll on and off the display (to hide the short blank while temperature is being read).
-Light sensor to turn off display at night.
-LCD module to show date and other info.
-Automatic adjustment for DST.
Here’s a youtube video of it working http://www.youtube.com/watch?v=BuRdddTZRdU&list=UUaTyVrg9zu-nz1CJBfIt6EA&index=1&feature=plcp
I don’t know if anyone will find this useful but I thought i’d post it anyway.
Here’s the code. I haven’t done a circuit diagram yet but will at some point. It’s simple anyway so you should be able to work it out.
#include <DallasTemperature.h> // http://www.milesburton.com/?title=Dallas_Temperature_Control_Library
#include <OneWire.h> // http://www.pjrc.com/teensy/td_libs_OneWire.html
#include <SimpleTimer.h> // http://www.arduino.cc/playground/Code/SimpleTimer
#include <Wire.h> //Included with Arduino IDE
#define DS1307_ADDRESS 0x68 //RTC Module Address
#define ONE_WIRE_BUS 14 //DS18B20 temperature sensor connected to analog pin 0.
byte digits[15] = { //Bit pattern for 7 segment display
// -AFBGEDC Segments labelled as per datasheet for Kingbright DA56-11EW dual common anode LED display module.
B10001000, // 0 1 represents segment OFF, 0 is ON
B11011011, // 1 the MSB is not used.
B10010100, // 2
B10010001, // 3
B11000011, // 4
B10100001, // 5
B10100000, // 6
B10011011, // 7
B10000000, // 8
B10000001, // 9
B10000111, // Degree symbol
B10101100, // Letter C
B10100100, // Letter E
B10100110, // Letter F
B11110111 // - Symbol
};
int anodes[4] = {2,3,4,5}; //Common anodes for 7 segment displays connected to these digital outputs via NPN transistors
//Pin 2 is first digit, 3 is second and so on.
int cathodes[7] = {6,7,8,9,10,11,12}; //Cathodes for each segment all tied together and connected to these digital outputs.
//Segment to pin assignment
//6>C, 7>D, 8>E, 9>G, 10>B, 11>F, 12>A
int data[4]; //4 byte array stores value to be displayed.
int startAddress = 0; //Data start address on the DS1307
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
SimpleTimer timer; //Set up timer instance.
OneWire oneWire(ONE_WIRE_BUS); //Start the oneWire bus
DallasTemperature sensors(&oneWire); //Create Dallas Temperature library instance.
void setup()
{
for (int i = 0; i < 4; i++) //Set anode pins mode to output and put them LOW.
{
pinMode(anodes[i], OUTPUT);
digitalWrite(anodes[i], LOW);
}
for (int i = 0; i < 8; i++) //Set cathode pins mode to output and put them HIGH.
{
pinMode(cathodes[i], OUTPUT);
digitalWrite(cathodes[i], HIGH);
}
Wire.begin(); // Start the I2C bus.
sensors.begin(); //Start the Dallas Temperature library.
timer.setInterval(30000, showTemp); //Set to diaplay temperature every 30 seconds.
}
void loop()
{
readTime();
outputDisplay(data);
timer.run();
}
void outputDigit(int seg) //Outputs segment data for an individual digit.
{
for (int s = 0; s < 7; s++) //Read a bit at a time from the selected digit in the digits array and output it to the correct
{ //pin
boolean bitState = bitRead(digits[seg], s); //Read the current bit.
digitalWrite(cathodes[s], bitState); //and output it.
}
}
void outputDisplay(int dig[4]) //Scan the display once with the 4 digit int array passed in.
{
for (int d = 0; d < 4; d++)
{
outputDigit(dig[d]); //Set up the segment pins with the correct data.
digitalWrite(anodes[d], HIGH); //Turn on the digit.
delay(2); //Hold it on for 2ms to improve brightness.
digitalWrite(anodes[d], LOW); //And turn it off again before looping untl all digits have been displayed.
}
}
void showTemp()
{
sensors.requestTemperatures(); //Request temperature from the sensor.
float temp = (sensors.getTempCByIndex(0)); //Read temperature from the first (only) sensor on the bus.
int t = (int) temp; //Convert the temperature to int for display
int starttime = millis();
int endtime = starttime; //Store the internal timer counter value to make this loop run for a set period.
while ((endtime - starttime) <=5000) // do this loop for 5000mS
{
data[0] = (t / 10); //Calculate and store temperature 10s value
data[1] = (t % 10); //Calculate and store temperature 1s value.
data[2] = 10; //Degree symbol
data[3] = 11; //Letter C for Celcius
outputDisplay(data); //Send to diaplay.
endtime = millis(); //Read internal timer counter to see how long this loop has been running.
}
}
void readTime()
{
// Reset the register pointer
Wire.beginTransmission(DS1307_ADDRESS);
Wire.send(startAddress);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
int second = bcdToDec(Wire.receive());
int minute = bcdToDec(Wire.receive());
int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
data[0] = (hour / 10);
data[1] = (hour % 10);
data[2] = (minute / 10);
data[3] = (minute % 10);
}