loading
Picture of Numitron clock & thermometer
SDC12105.JPG
SDC12110.JPG
SDC12111.JPG
I really like nixie and numitron clocks, but I never worked with them before. So I decided to give it a go. I choose numitrons because of 2 reasons: first of all nixies need a higher voltage than numitrons to work. Nixies need around 170V DC and numitrons only 4,5V so they are safer to work with and don't need a special powersupply.

The timekeeping is done by a ds1307 I2C realtime clock and the temperature is measured with a DS18B20 1wire temperaturesensor.



An Atmega48 is used to proces the data and to drive the segments in the numitrons. I used Bascom to write the code and a MyAvr MK2 Programmer to stuff it into the microcontroller. You can find a free Bascom demo here. The only limitation of the demo version is that you can only compile 4Kbytes of code (but the atmega48 has only 4Kbytes so that will work fine.)

I added this instructable to the microcontroller contest, so give it a vote if you like it.
 
Remove these adsRemove these ads by Signing Up

Step 1: The DS1307 realtime clock

Picture of The DS1307 realtime clock
ds1307.png
The timekeeping will be done by a DS1307 IC. This is a handy little IC, because it not only keeps track of time but also of the date and the day of the week.

For this little project we'll only use it to keep track of the time. Therefore it needs a 32.768kHz quartz crystal connected between pins 1 and 2. We can also add a battery with + to pin 3 and - to pin 4. This enables the IC to keep working when the mainpower is switched off. If you don't want to use this feature, you can just connect pin 3 to pin 4 and everything will work fine.

Pin 5 and pin 6 will be used to transfer the data to our microprocessor. They should be connected to the SCL and SDA pins on your microprocessor. These lines need to be pulled high by a 4K7 pullup resistor.


Bascom makes working with I2C devices easy. You only need to know 4 commands:
  1. I2cstart: This commant will startup I2c communications
  2. I2cstop: This command will stop I2c communications
  3. I2crbyte var: This command reads a byte from the device and stores it in 'var' 
  4. I2cwbyte var: This command writes the variable 'var' to the device
Using the write or read command is not enough, we will also have to tell the device whether we want to write to it or read from it. We do this by using the right address. These addresses can be found in the datasheet. The write-address for the DS1307 is D0H and the read-address D1H (the H behind it tell us that these are hexadecimal figures).

The DS1307 sends and wants to receive data in BCD format. This is a variation on binary for diplays where every digit is represented by four bits. More about that here. Luckily converting from BCD to decimal and visa versa is very easy in Bascom.
  • var = Makebcd(var) will convert decimal, hex and binary into BCD
  • var = Makedec(var) will convert hex, binary and BCD into decimal


The data is stored on the IC in register. You can imagine them as those oldfashioned filingcabinets. Each drawer has its number and contains some info:

00H Seconds
01H Minutes
02H Hours
03H Day
04H Date                                               The H tell us that these are hexadecimal figures.
05H Month
06H Year
07H Control
08H to 3FH Ram

If we want to read or store some data we'll first have to tell the device in which drawer we want to be. We can do this by writing the hex code for that drawer to the device. The device then will grant us acces to that drawer. After you write or read something from or to this register the device will automatically jump to the next one. So there is no need to send the location every time

Now lets put this in code:

For this code you will need to dim hours as byte, minutes as byte and seconds as byte.

First, we will set the clock:


Seconds = Makebcd(Seconds)                             We convert our variables into BCD format
Minutes = Makebcd(Minutes)
Hours = Makebcd(Hours)

reset hours.6                                                            We reset bit 6 of the hoursbyte to make sure that
                                                                                    our Clock runs in 24h modus. If bit 6 is 1 then the
                                                                                    clock runs in 12h modus and bit 5 will then 
                                                                                    contain the AM/PM data.


I2cstart
I2cwbyte &HD0                                                         We tell the device that we want to write a byte
2cwbyte &H00                                                           We start at the register for seconds hex 00  
I2cwbyte Seconds                                                    Adding seconds
I2cwbyte Minutes                                                      Adding minutes
I2cwbyte Hours                                                         Adding hours
I2cstop

 Now our clock is set! Lets read from it now.

I2cstart
I2cwbyte &HD0                                                        We tell the device that we want to write a byte.
I2cwbyte &H00                                                         We ask the device to go to the seconds register.
I2cstop
I2cstart                                                                       
I2cwbyte &HD1                                                        We tell the device that we want to read bytes.
I2crbyte Seconds , Ack                                           We read the data and acknowledge that we want 
                                                                                     to read the next byte too.                  

I2crbyte Minutes , Ack
I2crbyte Hours , Nack                                             We don't ackowledge here so the device knows
                                                                                     that we are done reading.

I2cstop

Hours = Hours And &B00111111                        We remove bits 6 and 7 as they contain other
                                                                                    data. If you are in 12h modus, then you need to
                                                                                    remove bit 5 too

Hours = Makedec(Hours)                                      We convert back to decimal format.
Minutes = Makedec(minutes)
Seconds = Makedec(seconds)

Now we know what time it is.

In the next step we will take a closer look at the DS18B20.

Step 2: The DS18B20 temperature sensor

Picture of The DS18B20 temperature sensor
DS18B20.png
The DS18B20 is a so-called 1wire device. Sadly, as with many things in life, this description was made up by some clever salesmen as we need at least two wires for it and in our case even three.

There are two ways to set up a DS18B20:
  1. With parasite power
  2. With external supply

To know more about these options, just check the datasheet.

The data line DQ will need a 4K7 pullup resistor and can be connected to the vast majority of pins on your microcontroller.

Communication with a 1wire device is, again, not very difficult in Bascom. There are some commands but we only need three of them for this project.

  1. 1wreset: This commands resets the communication
  2. 1wwrite var: This command writes 'var' to the device
  3. 1wread var: This command reads from the device into 'var'

We also need to setup the 1wire bus with the following code: config 1wire = pinX.y Where X is the name of the port and y the number of the pin.

Lets try to put this all into code now:

We will use the DS18B20 in 12bit mode (default setting) so every bit corresponds with 0.0625degr C or to put it easier: we will have to divide the result by 16 to get the temperature.

For this code you will need to dim tempdata(9) as byte and temperature as integer.


config 1wire = portd.0                  This tells the microcontroller whereto look for the device
....

1wreset                                          resets and starts the communication
1wwrite &HCC                             This skips transmitting the unique ROM code for the device. This
                                                        code is needed when there are more devices on the same wire
                                                        but we have only one so we can skip it.

1wwrite &H44                              Starts the A/D convertion in the sensor and stores the data into
                                                        the scratchpad

waitms 750                                  The convertion in 10bit mode can take upto 750ms so we wait
                                                        750ms before we start to read the scratchpad.

1wreset
1wwrite &HCC
1wwrite &HBE                              Tells the device that we want to read the scratchpad.
Tempdata(1) = 1wread(9)          We read 9 bytes into tempdata(), starting from tempdata(1).

If tempdata(9) = Crc8(tempdata(1) , 8) Then                       This checks the validity of the data and
Temperature = Makeint(tempdata(1) , tempdata(2))          combines the 2 first bytes into an
                                                                                                       integer.
Temperature = temperature / 16                                             By dividing this integer by 16 we have
                                                                                                       our temperature in degr C.

End If

We have our sensor working now.
In the next step we will talk about the buttons.
 

Step 3: Buttons and interrupts

Picture of Buttons and interrupts
buttons.png
To set the time we need some sort of inputdevice. In this project, we will use two buttons. These buttons are connected to the interrupt -pins on the atmega48 (pind.2 and pind.3).

An interrupt does, as its name suggests, interrupt the program to do a little routine. When the interrupt is done, the program continues where it was interrupted. There are lots of different interrupts triggered by internal events caused by timers, comparators.... but we will use 2 external interrupts triggered by the two buttons.

The buttons connect the interrupt pins with ground while a 1K5 pullup resistor keeps the pin high (the interrupt is triggered when the pin goes low).

At the begining of our code, we'll need to setup the interrupts.

config INT0 = Falling                                  The interrupt is triggered on the falling edge.
On INT0 button1                                          When the interrupt is triggered the program will jump to
                                                                        label button1.

Enable INT0                                                 Enables this interrupt


config INT1 = Falling
On INT1 button2                                          When the interrupt is triggered the program will jump to
                                                                        label button2.

Enable INT1

Enable interrupts                                         Enables the use of all interrupts

At the end of the code, after the End - Statement, we will put the 2 needed labels with the routine.

Button1:

code to set the hour

Return

Button2:

code to set the minutes

Return

One important thing to remember is that you cannot trigger an interrupt inside the routine of another one!

Now that we are able to set the time, we can look at our display aka the numitrons in the next step.

Step 4: The numitrons

Picture of The numitrons
SDC12061.JPG
I bought some IV-9 numitrons rather cheaply, so this clock/thermometer was an ideal opportunity to use 4 of them. They come with long leads so they can be soldered directy onto your pcb. The numitrons came with a very handy Russian datasheet (I really need to learn Russian...). After some testing I found out that they need between 3,5V and 4,5V and that the current per fillament is approx. 20mA.

Numitrons are 7 segment displays, so we need to build up our digits with these segments. There are lots of IC´s to drive 7 segment diplays like the HEF4511 (BCD to 7 segment) but to save space on the pcb, we will drive them directly with the microcontroller. To do so, we will use portb to drive the 7 segments and to the first four pins of portc to multiplex inbetween the four numitrons.

When you use multiplex numitrons, you need to use diodes on all pins, except the common one. This to prevent 'ghost digits' in other numitrons. I used the very common 1N4007 for my clock.

Earlier, I stated that numitrons need between 3,5V and 4,5V. But when we multiplex them, you won't see anything happen. As we enable each numitron for only 5ms at a time, we'll need a higher voltage to make the fillaments glow. Any voltage between 7,5V and 12V will work fine, but I choose 7,5V because I didn't want them to be to bright.

As we use a higher voltage for the numitrons than for our microcontroller, we'll need some transistors too. I used the common 2N3906 PNP-transistor to drive the segments and the BD137 NPN transistor to assist the multiplexing.

Now for some code:

First of all: when we want to display time on four numitrons, we'll need to split it into 4 digits. There are numerous ways to do this, but I do it with this code:

For this code you'll need to dim tube(4) as byte and temp as byte.

The digits are numbered from right to left so the minutes have numitron 1 and 2 and the hours 3 and 4.


Tube(2) = Mins / 10
Temp = Tube(2) * 10
Tube(1) = Mins - Temp
Tube(4) = Hours / 10
Temp = Tube(4) * 10
Tube(3) = Hours - Temp

So if the time is 09:24  :

tube(2) = 24/10  = 2 (the decimals are dropped)
temp = 2*10 = 20
tube(1) = 24-20 = 4
tube(4) = 9/10 = 0
temp = 0*10 = 0
tube(3) = 9-0 = 9


Now that we have the digits, we can multiplex them:

For this code, you need to dim i as byte and j as byte.

For I = 1 To 4

Temp = 7seg(tube(i))
Portb = Temp
J = I -1
Set Portc.j
Waitms 5
Reset Portc.j

Next

This code selects one of the numitrons, converts its corresponding value into 7 segments and enables it to light up by setting the right pin of portc high for 5ms. As the numitrons are numbered 1 to 4 and the pins 0 to 3, variable j will be variable i substracted by 1.

Now last but not least the 7seg-function:

We'll add this funtion in the code to convert the value of the digits into a 7 segment pinout for portb.

First we need to declare the function.

Declare Function 7seg(byval Q As Byte) As Byte

Then at the end of the code we will add the code for the function.

Function 7seg(byval Q As Byte) As Byte

Select Case Q

Case 1 :
7seg = &B01111100

Case 2 :
7seg = &B00010010

Case 3 :
7seg = &B00011000

Case 4 :
7seg = &B00101100

Case 5 :
7seg = &B00001001

Case 6 :
7seg = &B00000001

Case 7 :
7seg = &B01111000

Case 8 :
7seg = &B00000000

Case 9 :
7seg = &B00001000

Case 0 :
7seg = &B01000000

End Select

End Function

Important here is that, as we used PNP transistors, a 0 means that the segment is activated and a 1 that the segment is deactivated. If you wire your munitrons differently to portb, you'll need to find out which bit is needed for each segment.

In the next step we'll look at the brains of our contraption: the atmega48.

Step 5: The atmega48

Picture of The atmega48
atmega48pinout.png
ISP.png
SDC12039.JPG
The atmega48 is the brain of our contraption. It wil collect all the data from the clock and the thermometer and put it onto our display.

We won't use an external crystal for this project but the internal 8MHz oscillator. There are 2 reasons for that. First of all we don't need a very accurate or highspeed timing and secondly we can use portb.6 for our 7 segments.

The only 2 things that our atmega needs is power and a way to program it.
For power, we hook up VCC to 5V and the 2 GND pins to ground (we also add a 100nF capacitor between VCC and GND).

To connect the atmega with you ISP- programmer, you just have to connect MOSI to MOSI, MISO to MISO, SCK to SCK and reset to reset. (I added a schematic in the images)

At the begin of our code, we'll need to tell the compiler a few details about our microcontroller.

 First of all we need to tell which microcontroller we use:

$regfile = "m48def.dat"

Then we need to tell what clockspeed we use (in Hz):

$crystal = 8000000

Then there are some other bits and bobs we need to discribe(I won't go into detail about them here):

$hwstack = 32
$swstack = 8
$framesize = 24

After this, you can start to write your code.


In the next step, we will bring everything together.

Step 6: Schematic and full code

In this step, I added the complete schematic for our project. Below you will find the full code for Bascom in different extentions.

The schematic is split up into 2 parts as it made it on 2 pcb's. I couldn't find a good Eagle library for the IV-9 so I used 8pin sockets instead. (the 2th pin on the numitron is for the decimal dot but we just remove that lead as we don't need it)

I added an image on how to connect the numitron.




In the last step you'll find some details about the casing.

Step 7: The casing

Picture of The casing
SDC12094.JPG
The casing is made out of five layers of 3mm CNC-milled opague acrylate with 3mm spacers between them. Everything is held together with four M4 bolts.

You can find the drawings in a pdf below.

Step 8: Why I would love to win the lasercutter

I really wanted this project to look as nice as possible, so I invested a lot of time in the overall design and building the case. I hope that this build is awesome enough to have a chance in the lasercutter contest as I would love to have one of these machines.

They would allow me to make even nicer looking and more intricate cases and parts. Also making gears would be a lot easier, so I would be able to make complex mechaninical movements. A lasercutter would be the ideal solution, as I work a lot with acrylate and other plastics. It would enable me to make designs that that a CNC-router can't make and I wouldn't have to bother my friends all the time to use theire machines.

It would ofcourse also be great for my friends, who also happen to build a lot of stuff, to have access to such a device. So it would surely boost the creativity of those people around me too ( they would surely pay me a lot more visits ;) ). I have no commercial intensions with the machine, just building stuff and helping people build theire projects and ofcourse sharing everything on Instructables.

gmg1 year ago

Nice case.

But Numitron segments are cathodes. Aren't the diodes backwards in the schematic?

janw (author)  gmg1 year ago

Numitron segments are filaments that light up in either way. The position of the diodes is correct as it allows the filaments to light up when a positive voltage is applied to them but it block them when connected to GND. This is needed When multiplexing otherwise you might get filaments that glow softly when they should be of because of power flowing 'backwards' to the filaments connected to GND.

gmg janw1 year ago

Now I see you're driving them as common cathode. Should have noticed that. Thanks.

I love it, I will try to build mine! :-)
mazzmn1 year ago
Neat design...thanks for info about numitron...I've wanted to work with Nixie tubes before but didn't like the voltage requirements, this looks like the answer!
PICme3 years ago
Hi Janw,
I have the control board built and sourced the IV-9 Numitrons. There is just one point i hope you can make clear. The Numitrons are numbered IC4 to IC1 in your schematic. How does that equate to the the hours and minutes. For example if the time is 09.24 does ic4=0, ic3=9, ic2=2, ic1=4. This is my first Numitron clock and any help would be greatly appreciated.
janw (author)  PICme3 years ago
The order is correct as you mentioned it.
PICme3 years ago
Hi Janw,
Thank you for your prompt reply i understand the pin connections now.
PICme3 years ago
Hi janw,
I would like to build your excellent clock. Could you confirm the numitron pinots. I understand it is as follows:
(8 pin Socket) pin 1=com
2="b"
3="c"
4="a"
5="f"
6="g"
7="d"
8="e"
Also did you include any option to blank the screen at night. Thanks again for a great project.
janw (author)  PICme3 years ago

Pin Connection:

1 common
2 right hand deciamal point
3 Segment (b)
4 Segment (c)
5 Segment (a)
6 Segment (f)
7 Segment (g)
8 Segment (d)

I did cut pin 2 because I did't use the decimal point, So i ended up with 8 pins instead of 9.

You don't need a blank out option. You can put a powerswitch on the powercord of the device. The battery of the DS1307 will take over the power for the timekeeping and all other functions are switched off. The battery can power a DS1307 for a few years so no worries there.
sgleason13 years ago
Can you add two more numitrons so it can display a temp with 1 decimal plagce, display the time in seconds and display the date?
janw (author)  sgleason13 years ago
Yes you can but bear in mind that you will need to speed up the multiplexing.
masterbalby3 years ago
I have great difficulty to draw a proper pcb.
Can you send me yours?
thank you in advance
masterbalby3 years ago
hello,
why have connected the 13 pin connector JP1 to +5 V while the pin 13 of the second connector is connected to anything.
thank you
janw (author)  masterbalby3 years ago
When I designed the pcb, I had the intention to add blue LEDs under the tubes for more colour. So a 5V supply was connected to JP1. The LED's never made it to the final design but I forgot to remove the 5V. You can leave it out.
thank you very much
astroboy9074 years ago
Hey- what do you think is an ok price for a numitron? Also, how large are your numitrons? Both the total physical size, and an estimated digit hight/width wold be nice- but its up to you. Great clock! I think im gonna build one for my geek lair :)
janw (author)  astroboy9074 years ago
I paid about 25euro for 12 numitrons. So that's around 2euro for one and I think that this is a reasonable price.

The dimentions are:
11 x 8 mm (0.44" x 0.32") for the digit
32 x 10 mm (1.28" x 0.4") total size.


did u enter it in the clock contest

u could win!!!!!!!!!!!
janw (author)  harry potter rules3 years ago
I can't as this is an old instructable and I an not a US citizen
are you from england
janw (author)  harry potter rules3 years ago
No I am a Belgian who lives in The Netherlands.
k thanks :)
TerryKing4 years ago
How-To Information on the DS18B20 Temperature sensor here:
http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20
CThoma0314 years ago
i love the look and operation of it! If you sold these I would be the first customer.
astroboy9074 years ago
Sweet! Mainly I just like the vintage look of the Numitrons :) Found some on ebay for cheap (2$ each!) so i might buy a few and use them in a project (or replace them for my seven segment displays in my 'ible!)

They would make an awesome desk clock!
F-174 years ago
Thats Pretty neat, 5*
n-2-stuff4 years ago
Awsome. Very nice case....
jeff-o4 years ago
I love the case! Very nice indeed.