It has been a long while since the last post. Amongst other things, the clock has been a work-in-progress. Each time I made some progress, I found some new reason to create a revision. The initial revisions where based on issues and oversights. I am finding that as the project matures, the nature of the revisions are changing. Earlier on I was focused on just seeing things working i.e. how to program the micro with the ISP, how to get the modules to communicate. The earlier boards were either bound to the original dev-board, bread board or both. Now, I have the display module and the main-board untethered from the bread board and they are happily working with each other. Each step of the way I learn something new and those earlier issues are no longer the obstacles that they were. So much so that the problems and challenges I face now are more functional and mechanical.
I now have a basic board layout for the controller and the display that I am happy to progress with. These are certainly not the cheapest options, but as I may have mentioned before, they offer a way for me to learn about and demonstrate inter processor communication as well as dealing with multiple voltages in the one application. My focus now was to get the job finished. I see two basic challenges. 1. Getting everything into the case and 2. Getting the alarm working!
Low Profile 7-Segment Display
The seven segment displays I had been using would not allow me to mount the display in the case. It was time to search for a better solution. I discovered some thin profile seven segment displays. They are perfect for the job, though they are a bit tricky to solder since they do not have any leads. I worked around that with a piece of lead wire inserted in two of the holes in my board. This enabled my to apply light pressure on the display in the direction of the leads to hold them firm in position for soldering. Then allowed all the displays to be identical.
The alarm buzzer then became my biggest challenge and something new to learn about.The clock originally had a Piezo buzzer. Since the goal is to restore the clock, I was hoping to use a Piezo again. However the results from testing were not what I had expected. It was really difficult to get any sort of appreciable sound. Admittedly, the simple Piezo need to be properly mounted in order to resonate correctly. This I could not really achieve with my test set-up.
Testing the Piezo and looking generally at buzzers was opening up a new avenue of concepts to learn. I found the theory simple enough and meant I still had some design decisions to make. The first thing was to understand what direction to take. Since this was new territory, I saw no other avenue but to order some different types and just try them out. The basic criteria I set was capable of handling at least 5V and in around the 90dB range. I have to admit, I had no idea what 90dB was going to give me.
|Description||Manufacturer||Part Number||Digi-Key part Number|
|Zero-Peak Signal Buzzer Single Tone 2.67kHz Magnetic 0~5V 88dB @ 3V, 10cm||TDK Corporation||CSQG703BP||445-4832-1-ND|
|Zero-Peak Signal Buzzer Single Tone 2kHz Magnetic 2~4V 85dB @ 3V, 5cm||CUI Inc.||SDR08540M3-01||102-1286-ND|
|Zero-Peak Signal Buzzer Single Tone 2.4kHz Magnetic 3~8V 87dB @ 5V, 10cm||CUI Inc.||CT-1205-SMT-TR||102-1199-1-ND|
In choosing, I had the choice to use a device that need no external driver or to drive the buzzer myself. I opted for the second to also learn how to integrate the PWM feature of the micro into the solution. In testing the buzzers, I could mount the CSQG703BP directly on my bread board. For the other two I created a (rough) test harness and used a Gabotronics Xminilab as my signal source – I don’t possess a bench signal generator yet.
The CSQG703BP tested OK but the tone was quite weak. I could not get a tone out of the SDR08540M3-01 at all but that could be related to the set-up I had. Although the CT-1205-SMT-TR was quite bulky in comparison to the others, it delivered the best results.
I made the final revision to the board to take the CT-1205-SMT-TR on the underside over the place where the Piezo was originally. The case had a moulding that gave more than enough space for this part, so I was lucky there.
In “bringing up” the buzzer, I had to learn about PWM control and what that meant. I created a test program to only operate the buzzer and not worry about the whole clock functionality yet. In the end I thought it would be cute if the alarm would not simply make the traditional chirps but send the message “WAKE UP” in Morse code.
Buzzer Alias Portb.1 Config Buzzer = Output ' CTC-Mode for ~ 2.5kHz Config Timer1 = Timer , Compare A = Toggle , Prescale = 1 , Clear Timer = 1 Const Timer0_startvalue = 100 ' 0.001 seconds Config Timer0 = Timer , Prescale = 64 Timer0 = Timer0_startvalue On Timer0 Timer0_isr Enable Timer0 Start Timer0 Enable Interrupts Heartbeat Alias Portc.3 ' LED indicator Config Heartbeat = Output : Heartbeat = 0 Const Tone_pitch = 200 Dim Tone As Byte Dim Tone_length As Integer Dim Tone_idx As Byte Dim Song(40) As Byte Dim Songlen As Byte Dim Song_finished As Bit Const Base_length = 7 ' Load the song - Songlen should be used to know the length afterwards. Wait 5 Songlen = 0 Restore Melody Do Read Tone If Tone <> &HFF Then Incr Songlen Song(songlen) = Tone End If Loop Until Tone = &HFF Tone_length = 1 ' A wake up signal. Illuminate the LED for one second. Set Heartbeat Wait 1 Reset Heartbeat ' Play the "song" every 10 seconds Do If Song_finished = 1 Then Wait 10 Tone_idx = 0 Reset Song_finished End If Loop End Buzzer_on: Compare1a = Tone_pitch Tccr1a.6 = 1 Return Buzzer_off: Tccr1a.6 = 0 Return ' ISR for timer 0. This will traverse the "melody" playing each tone, and pause ' in turn until the end of the song. ' The Melody is a series of data values. Since there is only one tone from the ' buzzer, only the length is given. There is a base length and the tone length is ' a multiple of that. Basically this comes from Morse code that the dots are three ' units long and the dashes are seven. Anything greater than &H80 is considered ' a pause. Timer0_isr: Timer0 = Timer0_startvalue If Tone_length > 0 Then Decr Tone_length If Tone_length <= Base_length Then Gosub Buzzer_off End If Else Toggle Heartbeat If Tone_idx < Songlen Then Incr Tone_idx ' Get the next tone Tone = Song(tone_idx) Tone_length = Tone And &H0F ' Get the tone length Tone_length = Base_length * Tone_length ' Factor the tone buy the base length Tone_length = Tone_length + Base_length ' Build in a unit gap at the end If Tone > &H80 Then Gosub Buzzer_off Else Gosub Buzzer_on End If Else Set Song_finished End If End If Return Melody: ' Wake up - Morse code Data &H01 , &H03 , &H03 , &H83 , &H01 , &H03 , &H83 , &H03 , &H01 , &H03 , &H83 , &H01 , &H87 , &H01 , &H01 , &H03 , &H83 , &H01 , &H03 , &H03 , &H01 , &HFF
It was easy enough to integrate the alarm-tone code into the main-board code since since the 16-bit Timer0 was not in use. I could configure the Timer0 for CTC-Mode (Clear Timer on Compare) to deliver the 2.5kHz which produced the best results. I did attempt other PWM configurations but the results were not what I was expecting or wanted.
Config Timer1 = Timer , Compare A = Toggle , Prescale = 1 , Clear Timer = 1 Const Tone_pitch = 200
In my original design, I had anticipated to utilise the alarm interrupt (address $E) that the RTC-DFC supports – or is meant to support. I actually found that this does not work. When the alarm is programmed, it can be seen to be fired since the indicator LED on the module will illuminate. However, the Alarm Interrupt line is not brought low and therefore not detected in my code. I have two modules to try this out on and neither would pull the interrupt line low – even after upgrading to the latest firmware.
After chatting with my tutor, Chris Gammell from Contextual Electronics, I came to realise the workaround. In addition to the Interrupt line, it is possible to detect the alarm in the interrupt status register. This works. So I modified the code not to rely on the interrupt line but to, instead, query the Interrupt Status Register and invoke the alarm if the alarm bit is set.
Read_dfc_interrupt_flag: Reset Dfc_ss Mosi(1) = &HCE Spiout Mosi(1) , 1 Spiin Mosi(1) , 1 Set Dfc_ss Interrupt_register = Mosi(1) If Alarm_disabled = 0 Then Temp = Interrupt_register And &B00000100 If Temp = &B00000100 Then Set Alarm_fired End If End If Return
I was keen to get this project into a finished state. The enabling of the alarm was one of the last stages. All was needed then was to clean up the code a bit and implement an “alarm cancel”. There is a push-button on one of the front feet so that the alarm can be cancelled by tapping the top of the clock.
So here it is, the renovated clock. I utilised the BOM feature of KiCad to perform a cost analysis of the two modules. The Clock module comes to a BOM cost of 41.46€ (including the RTC-DFC from ELV) and the display module comes to a BOM cost of 35.14€. I have already mentioned that this implementation is a bit over the top in terms of components etc. but it is more about the learning exercise rather than making a cost effective clock and display module.
Just to recap on what I have learned in this exercise:
- Circuit design
- PCB layout
- PCB Manufacturing
- Improved through-hole soldering
- Programming through an ISP (to a development board and my own board)
- Inter module programming using I²C and SPI
- Trouble shooting using a logic analyser and oscilloscope
When I set out on this project, I anticipated to learn a bit about UML – SysML in particular. I did start out that way but with everything else I had to learn on the way, it sort of went by the way. However the block diagrams that I created ended up being an valuable reference of what I had intended the pin allocations to be. That is something will try to utilise more for the next project.
Now that the clock has been running a week or so, I was thinking about how it is able to pick up the time signal better in some places than others. I was made think about this further when the ELV Journal showcased an external antenna for the RTC-DCF. I realised that all this time, I have been treating the DFC-RTF as a black box an literally taking it for granted. That approach certainly helped to get the job done. It was time to take a closer look. The RTC-DFC is a module in two parts. A DCF77 receiver module and a micro based RTC. It turns out that I really had a bit of luck with the positioning of the antenna on the main board. In certain locations the clock can (eventually) receive a signal, in others not at all. Looking at the data signal from the DCF77, I could clearly see the one second pulses when the antenna was about 5cm from the board. Bring the antenna closer and the signal is disrupted as the images below show.
It was not a light decision to take to add the external antenna to the clock as I had to make a slight modification to the case for the antenna cable. The performance of the clock as improved immensely. It now sits, as a trophy, on my Lab windowsill.