The scope of this project was to mimic the functionality of a Church or Town Hall Bell, which sounds on the hour with a number of “gongs” equal to the hour and with one “gong” on the half hour .
The project was originally intended for a “live sculpture”, which the project sponsor, a construction artist, wanted to present at an art exhibition. In that sense, the LCD display would remain out of sight and only a signal would be created that would drive the bell actuator, a solenoid electromagnet which would hit a bell. The reason for mentioning this, is because the clock does not have the full functionality that would normally be expected, but is rather generic. The focus of the project was on the ringing part, so the elementary clock functionality was not considered an issue at the time.
On the other hand, the programming methods for creating pulses with duration of several seconds, far beyond the period of a normal Arduino loop, may be found useful by the community. That was the main reason for deciding to publish this article.
Pictures of the prototype are shown below.
LiquidCrystal I2C version 1.2 Author Frank de Brabander Maintainer Marco Schwartz Website https://github.com/marcoschwartz/LiquidCrystal_I2C which I downloaded from https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
RTClib by NeiroN by JeeLabs (http://news.jeelabs.org/code/), neiroN (email@example.com) Version 1.5.4. The library supports both DS3231 and DS1307. Select the appropriate in the code.
For presenting custom characters to the LCD, I used the designs from https://lastminuteengineers.com/arduino-1602-character-lcd-tutorial/
You shall also need the RTC library MD_DS3231 by majicDesigns Version 1.2.0 for another sketch that I use to set the initial time of the real-time clock.
Handmade schematic? See why..
The Arduino Nano is connected via the I2C bus to the RTC and the PCF8574A. The PCF8574A chip demultiplexes the I2C signals and controls the 7 pins required by the LCD (D4-D7, RS, RW and E). The chip is installed below the LCD display with the purpose of keeping short the wiring between its pins and the display socket pins.
The potentiometer controls the LCD contrast. Set it to a value that provides a balance between the maximum brightness of the characters, without having the pixel background show that much.
The NPN transistor BC337 is driven by Arduino Nano pin D7 and controls a relay. This relay will drive the actuator which rings the bell.
Three micro-switches are connected to Arduino pins D4, D5 and D6. They are used for correcting the time, after it has shifted significantly from the correct time. These switches are marked H, M and S and correct hours, minutes and seconds respectively.
One header pin wired to GND and D3 serves for the wiring of an external “night-mode” switch. Details on its operation are presented below.
A peculiar circuit is built around a PNP transistor BC557C. One would immediately notice that the transistor is redundant because it always allows the flow of current without exercising any control. This is true. The reason for the existence of this circuit block is because for this project I used an existing prototype board that I have built for another project, a few months before. In that project, I was using a different library for driving the display which was also called LiquidCrystal_I2C, but it was using the pins of PCF8574A in a different manner. The wiring was similar to the one used by library LiquidCrystal_PCF8574 by Mattias Hertel http://www.mathertel.de/Arduino/LiquidCrystal_PCF8574.aspx. Pins RS, RW and E of the LCD were wired to pins P6, P5 and P4 of PCF8574A and the data pins D4, D5, D6, D7 of the LCD were wired to pins P0, P1, P2 and P3 of PCF8574A. Additionally, the LCD backlight was driven by pin P7, with a negative logic. This means that when the library wanted to activate the LCD backlight, it sent 0 to P7. The LiquidCrystal_I2C library that I am using in this project instead, activates pin P3 for backlighting, probably with a positive logic. In this new project, the display is supposed to be always on, so I did not bother to spend time on this issue and connected one end of the 4.7K resistor to ground, as a minimal immediate fix that would not disturb the existing circuit too much. Who knows, I may re-use it in the future!
Unfortunately, the old library was lost when the hard disk crashed and it was not possible to recover it. I tried several libraries that I could find on the internet but perhaps there were differences in the software that also did not work with my LCD. I guess these are problems happening when one uses unofficial Arduino libraries! I finally end up with the library of Frank de Brabander, which required rewiring of several pins, as it is shown on the schematic.
Going back to hardware issues, please note that backlighting of the LCD is performed by internal diodes, whose operating current should be less than 25mA according to the manufacturer specification. My testing showed that 5mA were enough for proper lighting. Pin A is the Anode and pin K the cathode. Note that these pins must be driven by current - not voltage. The Vf between A and K is approx. 3V, so to keep the current at a reasonable value of 5mA, we need a series resistor of (5-3)/0,005 =~ 390 Ohms. The 1N4148 in the schematic is also redundant.
To cut a long story short, if I built the circuit again, I would use a single 390 or 330 Ohm resistor from +5V to pin A of the LCD. Even better, I would buy an LCD display with a piggyback PCF8574 module, such as this or this, at almost the same price as a regular LCD and save all the wiring effort. Just set the module address, wire four pins and that's about it. Another option would be to buy an OLED module such as this. These modules are beautiful but their libraries occupy a large amount of the limited arduino RAM, leaving too little for our code. Anyway, the project sponsor liked better the old-fashioned LCD, so the issue was immediately solved.
The relay is used to drive the bell actuator. When I started the project, the sponsor have not yet decided on the bell and the associated type of actuator, so I installed an 8A/250V contact relay activated by a 5V coil. Should I have the specs of the actuator beforehand, I would design using transistors or MOSFETs. Yet the relay provides a more generic solution.
One barrel 5.5×2.1 mm connector for the PCB and alternatively a block connector are used for providing power to the board. Note that 5.5 mm refers to the outer diameter (OD) of the plug and 2.1mm to the inside diameter (ID). There are also in the market 5.5×2.5 mm. Match the socket with the plug so that they are of same specifications.
A 1N5819 schottky diode is used to allow us to program the Arduino nano via the USB cable while the circuit is powered at the same time by the power supply. I cover this issue in detail in another post.
The Arduino Nano, the RTC module and the LCD display module are not soldered directly on the board. I am using socket pins, like the ones shown at the top of the picture (those are not used in this circuit). I then insert the module header pins into the main board socket pins. Sometimes, in case the module arrives with the pins soldered on the “wrong”side of the board, I may have to de-solder them very carefully, trying to avoid damage to the PCB. The de-soldered pins are thrown away, the board holes are opened with a small drill bit and finally, new header pins are soldered at the proper side of the module board.
The most notable thing in the code is the measure of time. Several issues that caused drifting were discovered using an oscilloscope and the code was developed in order to ensure precise timing.
When the time is exactly on the hour, the system produces a number of “hour” pulses. Especially for hours after 12 (p.m for USA), 12 is subtracted from the 24hour number. So at 13:00 the bell sounds once, at 14:00 the bells sound twice, etc.
The value of TIME_BELL_ON defines the time the relay will be at the ON state. Because we want to send a short pulse to the actuator, such as a mini solenoid electromagnet, 100 milliseconds are OK. The value of TIME_BELL_ON is multiplied by 100 to produce the number of milliseconds.
The value of TIME_BELL_OFF defines the time the relay will be at the ON state. We want the bell to reverberate for a while, so the value of 35 produces 3500 milliseconds which is 3.5 seconds.
Example for ringing hour 02:00:00 and 14:00:00 (num_bells = 2) ______________ ______________ I I I I I I I I ______I I____________I I____________ <--bell_on--><---bell_off-><--bell_on--><--bell_off-> <------------------ ring_on = true ----------------->
The Real Time Clock module synchronizes time every minute. The synchronization takes place 10 seconds before completing a minute. I selected 10 seconds before because usually programmed events take place exactly on the hour and I wished to avoid several things happenning at the same time.
One safety feature is that, if the clock has sounded the hour and for some reason the synchronization sets the time back, the same hour will not sound again.
Finally, the Night Mode keeps the device silent after hours. This means that if Night Mode is active, the bell will sound only at normal working hours. Night Mode is the default mode, provided that the pin headers are not wired together. The silent hours are defined in array silent_hours.
A copy of the code is shown at the end of this document. I will try to post same on Github when I find the time
Install a CR2032 coin battery into the RTC socket.
When powering the device for the first time, the RTC will have an undefined date and time. Load any example sketch that will allow you to set it manually. I used the one provided with the MD_3231 library. Most important is to set the date, because we will not be able to correct it via the switches.
Of course, it will not be possible to set the exact time with this method. You will definitely be off, at least by a few seconds.
After setting the RTC, load the sketch of the project. The date will appear at the first line and the time at the second line. You can now fix the time precisely using the switches.
Here is how the switches operate:
When the two pins of Night Mode are wired together, Night Mode is deactivated. A bell symbol appears in the far right column of the first line of the display to signify that the bell will sound each and every hour during day and night.
The last column of the second line of the LCD presents a music note symbol if the current hour is non-silent. No symbol appears for silent hours.
Although at first the concept appeared easy - a simple clock and something to do on the hour - it proved to be a detailed work, needing to examine several Arduino features regarding the handling of timer functions and timer interrupts, as well as the system behaviour during the loops. Minor time drifts would add up and cause significant variations over time. Several solutions were examined originally, even the use of two arduinos, one to handle time and the second to handle ringing. Another solution was to implement custom hardware for ringing.
Yet, since the whole project involved the notion of “time”, enough time was invested to implement it with the most simple architecture.
Finally, after lots of testing and debugging, the prototype was ready to be delivered to the project sponsor and subsequently to the open source community.
If you have any feedback, please contact me via this contact form
The source code of the project can be found here.