Author Archives: John Boxall

About John Boxall

https://nostarch.com/arduino-workshop-2nd-edition

Blinky the one-eyed Clock

This is a rewrite of a project I created in 2010 which brought me a lot of joy, so I hope you enjoy it too. Please read the entire article before starting your own. You can still make it today, the parts are easily available.

I’ve always enjoyed making Arduino-powered clocks, however over time they tended to become increasingly complex. So to counter this, allow me to introduce you to “Blinky” the one-eyed clock:

It reminds me of the giant killer orb “Rover” from “The Prisoner“… Using a minimal Arduino bootrom system, a DS1307 real time clock IC and an RGB diffused LED, you can make a clock that blinks the time, using the colours of the LED to note different numerical values.

For example, if the time is 12:45, the clock will blink red 12 times, then show blue for a second (think of this as the colon on a digital clock) then blink four times in green (for forty minutes), then blink three times in red for the individual minutes.

If there is a zero, blink blue quickly. Then the clock will not display anything for around forty seconds, then repeat the process. Here he (she, it?) is blinking the time:

Setting the clock is simple. It is set to start at 12:00 upon power up. So for the first use you have to wait until about five seconds before midday or midnight, then power it up. To save cost it doesn’t use a backup lithium battery on the real-time clock IC, but you could add one if required. So let’s get started.

The first thing to do was test the RGB LED for brightness levels, so I just connected it to the digital output pins of my Arduino-compatible board via suitable current-limiting resistors. Red, green and blue to D9, D10 and D11 respectively. Each LED is going to be different, so to ensure maximum brightness without causing any damage you need to calculate the appropriate resistor values.

This is quite easy, the formula is: resistor (ohms) = voltage drop / LED current So if you have a 5V supply, and LED that needs only 2 volts, and draws 20 milliamps (0.2 amps) , the calculation will be: resistor = (5-2)/0.02 = 150 ohms. To be safe I used 180 ohm resistors. The LED was tested with this simple sketch:

/*
blinky LED test
*/
int red = 2;
int green = 3;
int blue = 4;
int d = 300;
void setup()
{
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
}
void loop()
{
digitalWrite(red, HIGH);
delay(d);
digitalWrite(red, LOW);
delay(d);
digitalWrite(green, HIGH);
delay(d);
digitalWrite(green, LOW);
delay(d);
digitalWrite(blue, HIGH);
delay(d);
digitalWrite(blue, LOW);
delay(d);
}

It was interesting to alter the value of d, the delay variable, to get an idea for an appropriate blinking speed. Originally the plan was to have the LED in a photo frame, but it was decided to mount a ping-pong ball over the LED for a retro-style look. Here is a short video of the result of the test:

If you are going to use a ping-pong ball, please be careful when cutting into it with a knife, initially it may require a lot of force, but once the knife cuts through it does so very quickly.

Now it was time to develop the sketch to convert time into blinks. The sketch itself is quite simple. Read the hours and minutes from the DS1307 timer IC; convert the hours to 12 hour time; then blink an LED for the number of hours, display another colour for the colon; divide the minutes by ten and blink that in another colour; then the modulus of minutes and ten to find the individual minutes, and blink those out. Here is the first test sketch:

/*
"blinky" the one-eyed clock
Version beta 1
John Boxall August 2010/6th April 2022 – http://tronixstuff.com
DS1307/i2c timekeeping based on code by Maurice Ribble 17-4-2008 – http://www.glacialwanderer.com/hobbyrobotics
*/
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
int red = 9; // LEDs connected to these pins as you might want to PWM them to alter brightness
int green = 10;
int blue = 11;
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val / 10 * 16) + (val % 10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val / 16 * 10) + (val % 16) );
}
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary) to control register – turns on square wave
Wire.endTransmission();
}
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void blinkLED(int colour, int ondelay, int offdelay, int blinks)
// blinks LED on pin 'colour' for 'blinks' times with on and off delay of 'ondelay', 'offdelay'
// colour: 9 is red, 10 is green, 11 is blue
{
for (int a = 0; a < blinks; a++) {
digitalWrite(colour, HIGH); delay(ondelay); digitalWrite(colour, LOW); delay(offdelay);
}
}
void blinkTime() // blinks the time
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
float aa;
int bb;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
// convert hours from 24 to 12 hour time
if (hour == 0)
{
hour = 12;
}
if (hour > 12)
{
hour = hour – 12;
}
blinkLED(9, 500, 500, hour); // blink hours in red
blinkLED(11, 1000, 500, 1); // show blue for one second
aa = minute;
aa = aa / 10;
bb = int(aa); // find the value of tens of minutes (0~5)
if (bb > 0)
{
blinkLED(10, 500, 500, bb); // blink tens of minutes
}
if (bb == 0) // but if the time is something like 03:02?
{
blinkLED(11, 200, 200, 1); // blink blue quickly for zero
}
aa = minute % 10; // find modulo of minutes to get single minutes
if (bb > 0)
{
blinkLED(9, 500, 500, bb);
}
if (bb == 0)
{
blinkLED(11, 200, 200, 1); // blink blue quickly for zero
}
}
void setup()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
second = 0;
minute = 17;
hour = 4;
dayOfWeek = 6; // these values are moot, but need to store something
dayOfMonth = 28;
month = 5;
year = 10;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
}
void loop()
{
blinkTime();
delay(5000);
}
view raw blinkybeta1.ino hosted with ❤ by GitHub

Finally, the code was tested using the Arduino-compatible board and my home-made DS1307 real time clock shield (hey it was 2010, DS32xx were expensive). It is best to use existing hardware while testing, before committing to purchasing new hardware and so on. So here it is on the breadboard:

Here is the prototype in action:

If you’re wondering why the videos are potato-cam quality, smartphones couldn’t record using 4K Ultra HD in 2010.

But perhaps the first version was a little bland. By using analogWrite() we can control the brightness of the LED segments. So I’ve added two more functions, whiteGlow() and blueGlow(); whose purpose is to make the display “glow” by increasing then decreasing the brightness.

And I’ve scaled back the amount of blinking, to make blinky less obvious. So now the display will glow white to announce the forthcoming display of time, wait a second, blink the time (with a blue glowing colon) then stay dark for ten seconds before repeating the process. Here is a quick demonstration of this display style:

Here is the sketch for the above demonstration, and the final one I will use with the hardware prototype:

/*
"blinky" the one-eyed clock – Version 2.1
John Boxall 04 August 2010/6th April 2022
IDGAF licence
DS1307/i2c timekeeping based on code by Maurice Ribble
17-4-2008 – http://www.glacialwanderer.com/hobbyrobotics
*/
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
int red = 9; // LEDs connected to these pins as you might want to PWM them to alter brightness
int green = 10;
int blue = 11;
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val / 10 * 16) + (val % 10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val / 16 * 10) + (val % 16) );
}
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary) to control register – turns on square wave
Wire.endTransmission();
}
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void blinkLED(int colour, int ondelay, int offdelay, int blinks)
// blinks LED on pin 'colour' for 'blinks' times with on and off delay of 'ondelay', 'offdelay'
// colour: 9 is red, 10 is green, 11 is blue
{
for (int a = 0; a < blinks; a++)
{
digitalWrite(colour, HIGH);
delay(ondelay);
digitalWrite(colour, LOW);
delay(offdelay);
}
}
void blinkTime()
// blinks the time
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
float aa;
int bb;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
// convert hours from 24 to 12 hour time
if (hour == 0)
{
hour = 12;
}
if (hour > 12)
{
hour = hour – 12;
}
blinkLED(9, 500, 500, hour); // blink hours in red
blueGlow(1, 10);
aa = minute;
aa = aa / 10;
bb = int(aa); // find the value of tens of minutes (0~5)
if (bb > 0)
{
blinkLED(10, 500, 500, bb); // blink tens of minutes
}
if (bb == 0) // but if the time is something like 03:02?
{
blinkLED(11, 200, 200, 1); // blink blue quickly for zero
}
aa = minute % 10; // find modulo of minutes to get single minutes
bb = aa;
if (bb > 0)
{
blinkLED(9, 500, 500, bb); // blink tens of minutes
}
if (bb == 0)
{
blinkLED(11, 200, 200, 1); // blink blue quickly for zero
}
}
void whiteGlow(int n, int d)
{
for (int nn = 0; nn < n; nn++)
{
for (int a = 0; a <= 255; a++)
{
analogWrite(red, a);
analogWrite(green, a);
analogWrite(blue, a);
delay(d);
}
for (int a = 255; a >= 0; –a)
{
analogWrite(red, a);
analogWrite(green, a);
analogWrite(blue, a);
delay(d);
}
}
}
void blueGlow(int n, int d)
{
for (int nn = 0; nn < n; nn++)
{
for (int a = 0; a <= 255; a++)
{
analogWrite(blue, a);
delay(d);
}
for (int a = 255; a >= 0; –a)
{
analogWrite(blue, a);
delay(d);
}
}
}
void setup()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
second = 0;
minute = 17;
hour = 4;
dayOfWeek = 6; // these values are moot, but need to store something
dayOfMonth = 28;
month = 5;
year = 10;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // every time blinky has new batteries, it will start from midnight/midday
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
pinMode(blue, OUTPUT);
}
void loop()
{
whiteGlow(1, 10); // glow white – announces that the time will now be shown
delay(1000); // give people a second to focus on blinky
blinkTime();
delay(50000); // wait 50 seconds
}
view raw blinkyV2-1.ino hosted with ❤ by GitHub

Once happy with the sketch, I put a fresh ATmega328P-PU with Arduino bootloader in the board and programmed it with the sketch, to be used in the final version. The next step is to build my own hardware. The last hardware unknown is the amount of current the circuit draws. Once I know this the correct voltage regulator and power supply can be decided upon.

I had a fair idea it would be less than 100 milliamps, so I put a 6V battery onto supply duty via a 78L05 5V regulator (data sheet), and recorded the result:

So it varies, between 20.5 and 46 mA. As it only reaches 46 mA for a short time, we could consider the constant draw to be averaged out at 30 mA. I really want this to be able to run from a battery, but without having an external lead-acid battery lurking around, it will need a plug-pack with an output voltage greater than 7V DC.

Another alternative would be to run it from a USB socket, a nice source of 5V. If doing so, there wouldn’t be a need for the 78L05 regulator. Which brings us to the circuit diagram, which includes the power regulator. I’ve also altered the resistors to suit the RGB LED used, your values may be different:

And since it’s 2022, not 2010 – I’ve replaced the DS1307 circuit with a RTC module. Y1 is a three pin 16MHz ceramic resonator, we used those in 2010 as they were cheaper and easier than a crystal and two 22pF capacitors.

The circuit does not allow for uploading code, so you will need to program the microcontroller on another Arduino or compatible board, then transfer it to the blinky circuit board as described above. At this stage you should test it again – but using a solderless breadboard. In doing so you can make final hardware checks, and generally make sure everything works as it should. This is also a good stage to double-check you are happy with the display behaviour, default time and so on.

Used the Duemilanove as a lazy 5V for testing.

Time to solder up the circuit on some stripboard. Blank stripboard varies, but luckily I found this and a nice box to hold it in:

Stripboard does vary between retailers and so on, so you will need to work out the layout with your own board. In doing so, please double-check your work – follow the layout against the schematic and so on.

Have a break, then check it again. There is nothing worse than soldering away to realise you are one strip too far over or something. My hand-eye coordination is not the best, therefore my soldering isn’t pretty, but it works:

Note that the images above are using the 2010 circuit – which had a DS1307 sub-circuit.

One would say that there is a good argument for making your own PCBs… and I would agree with that. In 2010 it wasn’t that easy or inexpensive. Now you have KiCAD and Chinese PCB fabs tripping over themselves to give you cheap boards.

The LED is soldered to some short leads to give it a bit of play, and some heatshrink over the legs to keep them isolated:

And finally, to add a DC socket to feed blinky some power:

The last thing was to check the soldering once more under natural light, to check for bridges or shorts, then have a cup of tea. Upon my return I drilled out a hole in the enclosure lid for the LED, and one one the side for the DC socket, and fitted the lot together… and success! It worked.

I hope you enjoyed making this or at least reading about it. If you find this sort of thing interesting, please consider ordering one or both of my books from No Starch Press, or other book sellers:

  • Arduino Workshop, 2nd Edition – a hands-on introduction to electronics and Arduino with 65 projects
  • AVR Workshop – A comprehensive introduction to working with electronics and the Microchip AVR 8-bit family of microcontrollers with over 55 projects

And as always, have fun and make something.

Build a simple WFH Messaging System

Working from home – either you enjoy it, or doing so has been thrust upon you. As a world-class introvert I’ve always enjoyed being self-employed and working from my own office. However others do not, as they have missed out on the activity and interacting with other people in their workplace.

I was recently asked by an associate to make up a simple messaging system, that would allow them to indicate their work status and also request a coffee or whatnot from their husband, which has resulted in the simple messaging system described in this article – which you can build too.

Being somewhat lazy efficient I needed a simple WiFi-based solution that allowed for simple control of some digital output pins from a web page. A bit of research resulted with the Particle Photon, a compact WiFi-enabled microcontroller that includes all the Internet-connectivity without any hard work or recurring payments.

After consultation it was decided that there should be five messages that can be sent and will need to be indicated to the receiver:

  • “I’m in a meeting, do not disturb”
  • “I’m working alone, so I can be disturbed”
  • Bring coffee
  • Bring Water
  • “I’ve finished work for the day”

So that would need the control of five LEDs, and a buzzer to alert the receiver of new messages. Six digital outputs in total to be controlled remotely. Easily done with the Photon.

All the digital outputs on the Photon are 3.3V, and you can power the lot via the micro USB socket. Now let’s get started. I’ll go through the hardware first, then the software and connectivity.

Hardware

First, let’s consider the hardware. We’ll need:

The whole thing is a minimalist design, as shown below:

The PCB shown in this article was made for a buzzer with 16mm between the pins, as it was available locally. If soldering is new to you, or you need a refresher – watch Dave Jones’ video.

This is a simple circuit you can knock out on a solderless breadboard or your own PCB with KiCAD). Click here for the Photon KiCAD library. Click here if you want the gerber files to order your own PCB. You can view the gerbers using tools such as gerblook.

At the time of writing this I have a few PCBs left over… if you live in Australia I’ll send you one for free – email admin@tronixstuff.com.

In my infinite wisdom I forgot to get some inline header sockets (as you don’t really want to directly solder the Photon to the PCB). However having hundreds spare, a work around was to use six 8 pin IC sockets, and trim one side of the pins off from each socket. Which worked …well enough:

Fitting the rest of the parts was a doddle, and resulted with the following board:

The messages were purposely not printed on the PCB silkscreen, instead all that white space is for the users to apply their own labels – as they may want to change the messages later on.

The M3 threaded spacers and nuts are fitted to the holes on the PCB to give it some legs to stand up on. So now that the hardware is finished, it’s time to get all this working with the code and connectivity.

Software and Connectivity

There are a few steps for you to complete in order to build this system, and I’ll run through them in order now.

First, follow the instructions provided by Particle which will involve you setting up a Particle account, registering and testing your Photon. During this process you will be given your “device ID” – save this as you’ll need it later. It will also save the WiFi access point details into the Photon, so do this step using the WiFi network that will host the messaging system.

Next, install the Particle CLI (Command Line Interface). It is available for Windows, Linux and MacOS. This takes about five minutes, so get up and have a stretch.

Now you need an access token, a unique identifier for your Particle account. Open the terminal on your computer and run the command “particle token create –never-expires“. You’ll be prompted for your Particle account email address and password, then presented with the token (the long random string of text). Save the token for later.

I’ve blocked out my email address and part of the token to keep troublemakers at bay.

The next step is to build the web page that contains the buttons to be pressed to send the required messages. Open a text editor and save the following as an HTML file:

<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/particle-api-js@8/dist/particle.min.js"></script>
<script>
var particle = new Particle();
// This is incredibly insecure, and only ideal for local tasks of no consequence if things go wrong.
const accessToken = 'ENTER YOUR ACCESS TOKEN HERE';
const deviceId = 'ENTER YOUR DEVICE ID HERE';
function ledControl(cmd) {
// Used to turn on or off the LED by using the Particle.function "led"
document.getElementById("statusSpan").innerHTML = '';
particle.callFunction({deviceId, name:'led', argument: cmd, auth:accessToken}).then(
function(data) {
document.getElementById("statusSpan").innerHTML = 'Message sent.';
},
function(err) {
document.getElementById("statusSpan").innerHTML = 'Error calling device: ' + err;
}
);
}
</script>
</head>
<body>
<div id="mainDiv">
<h3>WFH Messaging System</h3>
<p><button id="ledOnButton" onclick="ledControl('D1On')">Working Alone.</button>&nbsp;
<button id="ledOffButton" onclick="ledControl('D0On')">In a meeting – DND.</button></p>
<button id="ledOnButton" onclick="ledControl('D2On')">I need coffee!</button>&nbsp;
<button id="ledOffButton" onclick="ledControl('D3On')">Please bring me some water.</button></p>
<button id="ledOnButton" onclick="ledControl('D4On')">Finished for the day.</button>&nbsp;
<p>&nbsp;</p>
<p><span id="statusSpan"></span></p>
</div>
</body>
</html>
view raw hello.html hosted with ❤ by GitHub

Enter your access token and device ID as noted in the HTML file. Just for the record, this system is incredibly insecure and shouldn’t be used for anything of any consequence, so if you modify this to control your door locks or alarm system, that’s on you.

You don’t need to be an expert on HTML, however if you’re not sure about it check out this great HTML tutorial site.

Now open the file using a web browser, and make it a bookmark for the user to easily fine. You will be presented with a simple interface:

You can easily change the text on each button, just edit the HTML and save the file. Now review the HTML, and note that for each button there’s the text (for example):

onclick=”ledControl(‘D1On’)”>Working Alone.

This snippet will send the text “D1On” back to the Photon when the button “Working Alone.” is pressed. The idea is that we need all the buttons to send back a unique message to the Photon, so it knows what to do with the LEDs and/or buzzer. Take note that each button press sends a different piece of text back to the Photon.

Moving on, we now need to enter and upload the code to the Photon. In a web browser, visit https://build.particle.io/build/new. You may need to log in to your Particle account during this process. After a moment, you’ll be presented with a text editor that may look familiar to anyone working with Arduino. Photon code is based off the Arduino plaform, so Arduino users or AVR C users will have a head start.

Give your project a title, then copy and paste the following code into the editor:

// WFH Messaging system.
// Modified version of code provided by particle.io documentation.
// Use at your own risk.
int led0 = D0;
int led1 = D1;
int led2 = D2;
int led3 = D3;
int led4 = D4;
int buzzer = D5;
void setup()
{
// set pins connected to LEDs and buzzer as outputs
pinMode(led0, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(buzzer, OUTPUT);
// We are also going to declare a Particle.function so that we can turn the LEDs on and off from the cloud.
Particle.function("led",ledToggle);
// This is saying that when we ask the cloud for the function "led", it will employ the function ledToggle() from this app.
// Turn off LEDs upon reset
digitalWrite(led0, LOW);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
digitalWrite(buzzer, LOW);
}
void loop()
{
// Nothing to do here as waiting for text from control webpage
}
void soundAlert()
{
digitalWrite(buzzer, HIGH);
delay(1000);
digitalWrite(buzzer, LOW);
}
void coffeeAlert()
{
for (int i=0; i<5; i++)
{
digitalWrite(buzzer, HIGH);
delay(100);
digitalWrite(buzzer, LOW);
delay(100);
}
}
void waterAlert()
{
for (int i=0; i<2; i++)
{
digitalWrite(buzzer, HIGH);
delay(500);
digitalWrite(buzzer, LOW);
delay(100);
}
}
int ledToggle(String command) {
// function receives a string from control webpage (the commands such as D0On) and acts on them
if (command=="D0On") {
digitalWrite(led0,HIGH); // in a meeting – DND
digitalWrite(led1,LOW); // turn off working alone LED
digitalWrite(led4,LOW); // turn off finished for the day LED
soundAlert();
return 1;
}
else if (command=="D1On") {
digitalWrite(led1,HIGH); // working alone
digitalWrite(led0,LOW); // turn off DND LED
digitalWrite(led4,LOW); // turn off finished for the day LED
soundAlert();
return 0;
}
else if (command=="D2On") {
digitalWrite(led2,HIGH); // coffee request
coffeeAlert();
delay(2000);
digitalWrite(led2,LOW);
return 0;
}
else if (command=="D3On") {
digitalWrite(led3,HIGH); // water request
waterAlert();
delay(2000);
digitalWrite(led3,LOW);
return 0;
}
else if (command=="D4On") {
digitalWrite(led4,HIGH); // finished for the day
digitalWrite(led0,LOW); // cancel DND LED if on
digitalWrite(led1,LOW); // cancel working alone LED if on
soundAlert();
return 0;
}
else {
return1;
}
}

This code configures the digital output pins for the LEDs and buzzer from lines 5 to 10, which are then set to outputs from lines 15 to 20. We then turn them all off from lines 27 to 32, so every time the Photon is reset or turned on after a power off, no LEDs or the buzzer are on.

On line 23 we have the following:

Particle.function("led",ledToggle);

This the link between the code on the HTML page you created earlier, and the function starting from line 70 in the Photon code. “led” is linked in the HTML line with “particle.callFunction”, and “ledToggle” is the function in the Photon code.

So whenever a button is pressed, the message (such as “D4On”) winds its way from the web browser via the magic of the Internet to the Photon, and then compared against the “if” statements in the function from line 73.

For example, when “D4On” is received, it is matched at line 101 by the Photon, which then turns on LED number 4 (for “Finished for today”), and also turns off the “DND” and “Working Alone” LEDs.

For all the other messages you can follow the code from line 73 to see how each button press on the webpage controls various combinations of LEDs and buzzer outputs. To save time there’s three custom buzzer functions that are used for differents audible alerts, so the message recipient can hear if the sender’s status has changed, or if they want a coffee or water. Pity the end user of this.

Finally, when you’ve entered the code in the Photon editor, click the little folder a the top-left of the screen which saves your code in the online storage provided by Particle:

Then you can upload the code to the Photon by clicking the lightning bolt. If there are no errors in the code, it will be compiled and shot off to the Photon. During this process, the LED on the Photon will blink slowly then quickly, then “breathe” on and off when it’s ready to go.

This could take up to a minute depending on your Internet connection. However if there’s something wrong, this will be shown in the bottom of the Photon editor page. Follow the messages to determine what’s wrong, then save and try again.

By now it should all be working. Now add labels next to the LEDs for the recipient to know what the sender is trying to say or demand, and you’re finished. A quick demonstration is shown in the following video:

So there you have it. On a broader sense, this can also be considered a demonstration of how to easily control things from a distance using a Particle Photon and a web-enabled device.

I hope you enjoyed making this or at least reading about it. If you find this sort of thing interesting, please consider ordering one or both of my books from No Starch Press, or other book sellers:

  • Arduino Workshop, 2nd Edition – a hands-on introduction to electronics and Arduino with 65 projects
  • AVR Workshop – A comprehensive introduction to working with electronics and the Microchip AVR 8-bit family of microcontrollers with over 55 projects

And as always, have fun and make something.

Learn Arduino with “Arduino Workshop, 2nd Edition: A Hands-on Introduction with 65 Projects”

After eight years and much feedback from various readers, I’m proud to offer the second edition of my first book “Arduino Workshop”, from No Starch Press. This is a revised update to this very popular book which is aimed at any person who wants to make electronic devices using the Arduino platform – but has no experience in electronics, programming or microcontrollers.

The reader doesn’t need to buy or read any other book first to get started, from the beginning they are introduced to the basic concepts, required software installation and then introduced to various topics from blinking an LED to controlling devices remotely via a cellular phone.

Contents include:

Chapter 1: Getting Started
Chapter 2: Exploring the Arduino Board and the IDE
Chapter 3: First Steps
Chapter 4: Building Blocks
Chapter 5: Working with Functions
Chapter 6: Numbers, Variables, and Arithmetic
Chapter 7: Expanding Your Arduino
Chapter 8: LED Numeric Displays and Matrices
Chapter 9: Liquid Crystal Displays
Chapter 10: Creating your own Arduino Libraries
Chapter 11: Numeric Keypads
Chapter 12: Accepting User Input with Touchscreens
Chapter 13: Meet the Arduino Family
Chapter 14: Motors and Movement
Chapter 15: Using GPS with Your Arduino
Chapter 16: Wireless Data
Chapter 17: Infrared Remote Control
Chapter 18: Reading RFID Tags
Chapter 19: Data Buses
Chapter 20: Real-time Clocks
Chapter 21: The Internet
Chapter 22: Cellular Communications

You can also review the entire book index from here.

Once the reader has progressed through “Arduino Workshop”, I have found that many people use it as a reference guide for various topics, and saves them time and effort. Instead of searching randomly for various videos, web pages or whatnot – this book offers solid, tried-and-tested information that can be relied on without worry.

Readers of the first edition will also be introduced to new chapters in this edition, such as learning how to create your own Arduino libraries, introduction to the new v2.0 IDE, using new types of LED displays, remote control of devices with LoRA wireless shields, an updated cellular chapter that uses contemporary 3G wireless, and more.

The book is printed using a convenient lie-flat technology, so you can have the book open to your side and not worry about the pages flapping about and losing your position while working on your projects. All the required code (or Arduino “sketches”) are included in the book, however you can also download them along with a list of parts and supplier information from the book’s website.

The Arduino platform in my opinion is still the easiest and most approachable way of learning about electronics and microcontrollers, and opens up a whole new world of creativity or even the pathway to a career in technology, and a copy of “Arduino Workshop” is the best guide to this world.

You can learn more about the book and order from the No Starch Press online store, amazon, kindle, or your preferred bookseller. Orders from No Starch Press also include a free electronic copy so you can get started immediately.

And whatever you do, have fun and make something!

LED Real Time Clock Temperature Sensor Shield for Arduino

Tutorial – LED Real Time Clock Temperature Sensor Shield for Arduino

In this tutorial we look at how to use the neat LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way. That’s a bit of a mouthful, however the shield does offer the following:

  • four digit, seven-segment LED display
  • DS1307 real-time clock IC
  • three buttons
  • four LEDs
  • a active buzzer
  • a light-dependent resistor (LDR)
  • and a thermistor for measuring ambient temperature

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-1

The shield also arrives fully-assembled , so you can just plug it into your Arduino Uno or compatible board. Neat, beginners will love that. So let’s get started, by showing how each function can be used – then some example projects. In no particular order…

The buzzer

A high-pitched active buzzer is connected to digital pin D6 – which can be turned on and off with a simple digitalWrite() function. So let’s do that now, for example:

void setup() {
  // buzzer on digital pin 6
  pinMode(6, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(6, HIGH);   // turn the buzzer on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(6, LOW);    // turn the buzzer off by making the voltage LOW
  delay(1000);                       // wait for a second
}

If there is a white sticker over your buzzer, remove it before uploading the sketch. Now for a quick video demonstration. Turn down your volume before playback.

The LEDs

Our shield has four LEDs, as shown below:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-LEDs

They’re labelled D1 through to D4, with D1 on the right-hand side. They are wired to digital outputs D2, D3, D4 and D5 respectively. Again, they can be used with digitalWrite() – so let’s do that now with a quick demonstration of some blinky goodness. Our sketch turns the LEDs on and off in sequential order. You can change the delay by altering the variable x:

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(2, OUTPUT); // LED 1
  pinMode(3, OUTPUT); // LED 2
  pinMode(4, OUTPUT); // LED 3
  pinMode(5, OUTPUT); // LED 4
}

int x = 200;

void loop() {
  digitalWrite(2, HIGH);    // turn on LED1
  delay(x);
  digitalWrite(2, LOW);    // turn off LED1. Process repeats for the other three LEDs
  digitalWrite(3, HIGH);
  delay(x);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(x);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(x);
  digitalWrite(5, LOW);
}

And in action:

The Buttons

It is now time to pay attention to the three large buttons on the bottom-left of the shield. They look imposing however are just normal buttons, and from right-to-left are connected to digital pins D9, D10 and D11:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way

They are, however, wired without external pull-up or pull-down resistors so when initialising them in your Arduino sketch you need to activate the digital input’s internal pull-up resistor inside the microcontroller using:

pinMode(pin, INPUT_PULLUP);

Due to this, buttons are by default HIGH when not pressed. So when you press a button, they return LOW. The following sketch demonstrates the use of the buttons by lighting LEDs when pressed:

void setup() {
  // initalise digital pins for LEDs as outputs
  pinMode(2, OUTPUT); // LED 1
  pinMode(3, OUTPUT); // LED 2
  pinMode(4, OUTPUT); // LED 3

  // initalise digital pins for buttons as inputs
  // and initialise internal pullups
  pinMode(9, INPUT_PULLUP); // button K1
  pinMode(10, INPUT_PULLUP); // button K2
  pinMode(11, INPUT_PULLUP); // button K3
}

void loop()
{
  if (digitalRead(9) == LOW)
  {
    digitalWrite(2, HIGH);
    delay(10);
    digitalWrite(2, LOW);
  }

  if (digitalRead(10) == LOW)
  {
    digitalWrite(3, HIGH);
    delay(10);
    digitalWrite(3, LOW);
  }

  if (digitalRead(11) == LOW)
  {
    digitalWrite(4, HIGH);
    delay(10);
    digitalWrite(4, LOW);
  }
}

You can see these in action via the following video:

The Numerical LED Display

Our shield has a nice red four-digit, seven-segment LED clock display. We call it a clock display as there are colon LEDs between the second and third digit, just as a digital clock would usually have:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way with free delivery worldwide

The display is controlled by a special IC, the Titan Micro TM1636:

TM1636 Numerical LED Display Driver IC from PMD Way with free delivery worldwide

The TM1636 itself is an interesting part, so we’ll explain that in a separate tutorial in the near future. For now, back to the shield.

To control the LED display we need to install an Arduino library. In fact the shield needs four, so you can install them all at once now. Download the .zip file from here. Then expand that into your local download directory – it contains four library folders. You can then install them one at a time using the Arduino IDE’s Sketch > Include library > Add .zip library… command:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way with free delivery worldwide

The supplied library offers five functions used to control the display.

.num(x);

…this displays a positive integer (whole number) between 0 and 9999.

.display(p,d);

… this shows a digit d in location p (locations from left to right are 3, 2, 1, 0)

.time(h,m)

… this is used to display time data (hours, minutes) easily. h is hours, m is minutes

.pointOn();
.pointOff();

… these turn the colon on … and off. And finally:

.clear();

… which clears the display to all off. At the start of the sketch, we need to use the library and initiate the instance of the display by inserting the following lines:

#include <TTSDisplay.h>
TTSDisplay rtcshield;

Don’t panic – the following sketch demonstrates the five functions described above:

#include <TTSDisplay.h>
TTSDisplay rtcshield;

int a = 0;
int b = 0;

void setup() {}

void loop()
{
  // display some numbers
  for (a = 4921; a < 5101; a++)
  {
    rtcshield.num(a);
    delay(10);
  }

  // clear display
  rtcshield.clear();

  // display individual digits
  for (a = 3; a >= 0; --a)
  {
    rtcshield.display(a, a);
    delay(1000);
    rtcshield.clear();
  }
  for (a = 3; a >= 0; --a)
  {
    rtcshield.display(a, a);
    delay(1000);
    rtcshield.clear();
  }

  // turn the colon and off
  for (a = 0; a < 5; a++)
  {
    rtcshield.pointOn();
    delay(500);
    rtcshield.pointOff();
    delay(500);
  }

  // demo the time display function
  rtcshield.pointOn();
  rtcshield.time(11, 57);
  delay(1000);
  rtcshield.time(11, 58);
  delay(1000);
  rtcshield.time(11, 59);
  delay(1000);
  rtcshield.time(12, 00);
  delay(1000);
}

And you can see it in action through the video below:

The LDR (Light Dependent Resistor)

LDRs are useful for giving basic light level measurements, and our shield has one connected to analog input pin A1. It’s the two-legged item with the squiggle on top as shown below:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-LDR

The resistance of LDRs change with light levels – the greater the light, the less the resistance. Thus by measuring the voltage of a current through the LDR with an analog input pin – you can get a numerical value proportional to the ambient light level. And that’s just what the following sketch does:

#include <TTSDisplay.h>
TTSDisplay rtcshield;

int a = 0;

void setup() {}
void loop()
{
  // read value of analog input
  a = analogRead(A1);
  // show value on display
  rtcshield.num(a);
  delay(100);
}

The Thermistor

A thermistor is a resistor whose resistance is relative to the ambient temperature. As the temperature increases, their resistance decreases. It’s the black part to the left of the LDR in the image below:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-LDR

We can use this relationship between temperature and resistance to determine the ambient temperature. To keep things simple we won’t go into the theory – instead, just show you how to get a reading.

The thermistor circuit on our shield has the output connected to analog input zero, and we can use the library installed earlier to take care of the mathematics. Which just leaves us with the functions.

At the start of the sketch, we need to use the library and initiate the instance of the thermistor by inserting the following lines:

#include <TTSTemp.h>
TTSTemp temp;

… then use the following which returns a positive integer containing the temperature (so no freezing cold environments):

.get();

For our example, we’ll get the temperature and show it on the numerical display:

#include <TTSDisplay.h>
#include <TTSTemp.h>

TTSTemp temp;
TTSDisplay rtcshield;

int a = 0;

void setup() {}

void loop() {

  a = temp.get();
  rtcshield.num(a);
  delay(500);
}

And our thermometer in action. No video this time… a nice 24 degrees C in the office:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-thermometer

The Real-Time Clock 

Our shield is fitted with a DS1307 real-time clock IC circuit and backup battery holder. If you insert a CR1220 battery, the RTC will remember the settings even if you remove the shield from the Arduino or if there’s a power blackout, board reset etc:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way with free delivery worldwide

The DS1307 is incredibly popular and used in many projects and found on many inexpensive breakout boards. We have a separate tutorial on how to use the DS1307, so instead of repeating ourselves – please visit our specific DS1307 Arduino tutorial, then return when finished.

Where to from here? 

We can image there are many practical uses for this shield, which will not only improve your Arduino coding skills but also have some useful applications. An example is given below, that you can use for learning or fun.

Temperature Alarm

This projects turns the shield into a temperature monitor – you can select a lower and upper temperature, and if the temperature goes outside that range the buzzer can sound until you press it.

Here’s the sketch:

#include <TTSDisplay.h>
#include <TTSTemp.h>

TTSTemp temp;
TTSDisplay rtcshield;

boolean alarmOnOff = false;
int highTemp = 40;
int lowTemp = 10;
int currentTemp;

void LEDsoff()
{
  // function to turn all alarm high/low LEDs off
  digitalWrite(2, LOW);
  digitalWrite(4, LOW);
}

void setup() {
  // initalise digital pins for LEDs and buzzer as outputs
  pinMode(2, OUTPUT); // LED 1
  pinMode(3, OUTPUT); // LED 2
  pinMode(4, OUTPUT); // LED 3
  pinMode(5, OUTPUT); // LED 4
  pinMode(6, OUTPUT); // buzzer

  // initalise digital pins for buttons as inputs
  // and initialise internal pullups
  pinMode(9, INPUT_PULLUP); // button K1
  pinMode(10, INPUT_PULLUP); // button K2
  pinMode(11, INPUT_PULLUP); // button K3
}

void loop()
{
  // get current temperature
  currentTemp = temp.get();

  // if current temperature is within set limts
  // show temperature on display

  if (currentTemp >= lowTemp || currentTemp <= highTemp)
    // if ambient temperature is less than high boundary
    // OR if ambient temperature is grater than low boundary
    // all is well
  {
    LEDsoff(); // turn off LEDs
    rtcshield.num(currentTemp);
  }

  // if current temperature is above set high bounday, show red LED and
  // show temperature on display
  // turn on buzzer if alarm is set to on (button K3)

  if (currentTemp > highTemp)
  {
    LEDsoff(); // turn off LEDs
    digitalWrite(4, HIGH); // turn on red LED
    rtcshield.num(currentTemp);
    if (alarmOnOff == true) {
      digitalWrite(6, HIGH); // buzzer on }
    }
  }

  // if current temperature is below set lower boundary, show blue LED and
  // show temperature on display
  // turn on buzzer if alarm is set to on (button K3)

  if (currentTemp < lowTemp)
  {
    LEDsoff(); // turn off LEDs
    digitalWrite(2, HIGH); // turn on blue LED
    rtcshield.num(currentTemp);
    if (alarmOnOff == true)
    {
      digitalWrite(6, HIGH); // buzzer on }
    }
  }
  // --------turn alarm on or off-----------------------------------------------------
  if (digitalRead(11) == LOW) // turn alarm on or off
  {
    alarmOnOff = !alarmOnOff;
    if (alarmOnOff == 0) {
      digitalWrite(6, LOW); // turn off buzzer
      digitalWrite(5, LOW); // turn off alarm on LED
    }
    // if alarm is set to on, turn LED on to indicate this
    if (alarmOnOff == 1)
    {
      digitalWrite(5, HIGH);
    }
    delay(300); // software debounce
  }
  // --------set low temperature------------------------------------------------------
  if (digitalRead(10) == LOW) // set low temperature. If temp falls below this value, activate alarm
  {
    // clear display and turn on blue LED to indicate user is setting lower boundary
    rtcshield.clear();
    digitalWrite(2, HIGH); // turn on blue LED
    rtcshield.num(lowTemp);

    // user can press buttons K2 and K1 to decrease/increase lower boundary.
    // once user presses button K3, lower boundary is locked in and unit goes
    // back to normal state

    while (digitalRead(11) != LOW)
      // repeat the following code until the user presses button K3
    {
      if (digitalRead(10) == LOW) // if button K2 pressed
      {
        --lowTemp; // subtract one from lower boundary
        // display new value. If this falls below zero, won't display. You can add checks for this yourself :)
        rtcshield.num(lowTemp);
      }
      if (digitalRead(9) == LOW) // if button K3 pressed
      {
        lowTemp++; // add one to lower boundary
        // display new value. If this exceeds 9999, won't display. You can add checks for this yourself :)
        rtcshield.num(lowTemp);
      }
      delay(300); // for switch debounce
    }
    digitalWrite(2, LOW); // turn off blue LED
  }
  // --------set high temperature-----------------------------------------------------
  if (digitalRead(9) == LOW) // set high temperature. If temp exceeds this value, activate alarm
  {

    // clear display and turn on red LED to indicate user is setting lower boundary
    rtcshield.clear();
    digitalWrite(4, HIGH); // turn on red LED
    rtcshield.num(highTemp);

    // user can press buttons K2 and K1 to decrease/increase upper boundary.
    // once user presses button K3, upper boundary is locked in and unit goes
    // back to normal state

    while (digitalRead(11) != LOW)
      // repeat the following code until the user presses button K3
    {
      if (digitalRead(10) == LOW) // if button K2 pressed
      {
        --highTemp; // subtract one from upper boundary
        // display new value. If this falls below zero, won't display. You can add checks for this yourself :)
        rtcshield.num(highTemp);
      }
      if (digitalRead(9) == LOW) // if button K3 pressed
      {
        highTemp++; // add one to upper boundary
        // display new value. If this exceeds 9999, won't display. You can add checks for this yourself :)
        rtcshield.num(highTemp);
      }
      delay(300); // for switch debounce
    }
    digitalWrite(4, LOW); // turn off red LED
  }
}

Operating instructions:

  • To set lower temperature, – press button K2. Blue LED turns on. Use buttons K2 and K1 to select temperature, then press K3 to lock it in. Blue LED turns off.
  • To set upper temperature – press button K1. Red LED turns on. Use buttons K2 and K1 to select temperature, then press K3 to lock it in. Red LED turns off.
  • If temperature drops below lower or exceeds upper temperature, the blue or red LED will come on.
  • You can have the buzzer sound when the alarm activates – to do this, press K3. When the buzzer mode is on, LED D4 will be on. You can turn buzzer off after it activates by pressing K3.
  • Display will show ambient temperature during normal operation.

You can see this in action via the video below:

Conclusion

This is a fun and useful shield – especially for beginners. It offers a lot of fun and options without any difficult coding or soldering – it’s easy to find success with the shield and increase your motivation to learn more and make more.

You can be serious with a clock, or annoy people with the buzzer. And at the time of writing you can have one for US$14.95, delivered. So go forth and create something.

A little research has shown that this shield was based from a product by Seeed, who discontinued it from sale. I’d like to thank them for the library.

This post brought to you by pmdway.com – everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.