I love side projects. They give me the opportunity to flex my creative muscles and tinker with tech like the Internet of Things (IoT) in new ways. Fortunately, I didn't have to look far for my next one; a common conundrum for pet owners fueled this concept for an IoT dog collar.
My dog had been out in the backyard for a while. When I decided it was time to bring him back into the house, I couldn't find him anywhere! After several minutes of searching and calling his name, I found him napping in the shade of a tree. If this scenario sounds all too familiar to you, then this post is for you!
In this tutorial, I'll show you how to set up the hardware you'll need to construct an IoT dog collar. We'll also walk through how to build the front-end and back-end web app that you can use to call and locate your pet. We'll use an Arduino Uno, the Johnny-Five JavaScript Robotics & IoT Platform, Heroku, and a few other components. By the end, you'll be much more comfortable using your JavaScript skills with hardware. And hopefully, you'll have a ton of fun along the way! Ready to begin? Let's go!
Here's a list of the hardware and resources you'll use to build your IoT dog collar:
** Prices change of course.
A great side project gives you the freedom to try things you might not normally do at your job. Keeping in spirit with this principle, the front end of this IoT project is simply a button with some text to turn the buzzer on and off — no need to use a framework like React or Angular. We'll write the code with an HTML file, a CSS file, and a pure JavaScript file.
Keeping the front end simple means you can customize the final output to how you see fit. It's also a fantastic opportunity to go back to the basics and remember what all your code compiles to in the end!
Let's begin. Inside your root folder, create the following three files:
index.html
We'll now start writing the code for the index.html file:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./index.css">
<title>Find My Dog</title>
</head>
<body>
<header>I have no clue where they went.</header>
<main>
<button id='beeper-btn' type="button">Activate the noise</button>
</main>
<script src="./index.js"></script>
</body>
</html>
Pretty easy so far, right? The most important thing here is to have that id attribute on the button element. Other than that, feel free to add more elements to the page so it suits your style.
index.css
Now, let's write the CSS file:
body {
font-family: 'Lato', 'Trebuchet MS', sans-serif;
}
header, main {
text-align: center;
}
header {
font-size: 36px;
}
button {
background-color: rgb(255, 0, 0);
border: unset;
font-size: 24px;
margin-top: 24px;
padding: 12px;
}
button:hover {
background-color: rgba(255, 0, 0, 0.5);
font-size: 24px;
}
If you didn't make any edits to the index.html and index.css files, your page should look like this:
If you did make edits, then your output may look a little different. No worries, though — this is one of the best aspects of side projects! You can use something minimal, like the example shown above, or you can get a little fancier and try out some cool CSS features.
index.js
Now it's time to write some basic JavaScript. The best part? You don't need to install any dependencies!
const beeperBtn = document.querySelector('#beeper-btn');
let isBeeperActivated = false;
const toggleBeeper = () => {
isBeeperActivated = !isBeeperActivated;
isBeeperActivated ?
fetch('http://localhost:3000/api/startBeeper')
.then(console.log)
:
fetch('http://localhost:3000/api/stopBeeper')
.then(console.log)
}
beeperBtn.addEventListener('click', toggleBeeper);
This file only does three things:
I'll be honest... it took me quite a while to remember how to get my JavaScript file to work with my HTML file outside of a framework. This is another reason why side projects are so awesome. Not only do they give you an opportunity to learn new things, but they also allow you to practice some of the basics you might not have used in a while.
If you've made it this far, congratulations — you've completed the entire front end of this project! Now, let's take care of the hardware. In this section, we'll walk through how to set up your breadboard with the Arduino Uno, speaker, and other components.
First, let's make sure your Arduino Uno is ready to work with the Johnny-Five platform. You'll need to upload the Standard Firmata sketch to your board. The easiest way to do this is through the Arduino IDE. If you've never worked with an Arduino before, don't fret; this is a straight-forward click-through type of upload. Here's an amazing walkthrough of this process. It will show you how to find the example Standard Firmata sketch that comes with the Arduino IDE and the process to upload the sketch to your Arduino.
Next, you'll need to get your Arduino working with the HC 05 Bluetooth Module. Here's the tutorial I used for this part. You'll see the schematic for wiring the HC 05 to the Arduino and a sketch you will have to upload to make the HC 05 communicate with the Arduino's serial port. After that step is complete, re-upload the Standard Firmata sketch and connect to Johnny-Five.
Once you've set up your board, you can add power to it with the battery pack and connect your piezo-buzzer. Connect the red wire of your battery pack to the board's Vin pin and its black wire to one of the board's GND pins on the Power side. Your HC 05 Module should be connected to the 5V pin and another GND pin. Finally, you can connect your piezo-buzzer to pin 13 and a GND pin.
Want to keep your wiring cleaner? Try using a breadboard and jumper wires to make it easier to follow your connections. Note: This will change the size of your casing. Speaking of which...
After you've cobbled your components together, you can put them into your casing. Make sure your battery pack is accessible so you can turn it on and off. I chose to put mine in a little bag in a box. Is this the best way to treat hardware? Heck no! But remember, nobody else is going to see this much except you. So feel free to get super creative. I chose to go with a SweetTarts box. (It represents my dog's personality perfectly.)
Whew! If you've made it this far, give yourself a pat on the back — you've just completed the hardware section! Wasn't too hard, was it? Now let's get to the last piece of code for this IoT project: the Node back end.
I chose to deploy my app on Heroku; it's fast, easy, and perhaps most importantly, free for stuff like this. You can sign up for an account here. But feel free to use whatever service you prefer. After you sign up, make sure you have the Heroku CLI installed so you can deploy the app later. You can find the installation instructions here: https://devcenter.heroku.com/articles/heroku-cli#download-and-install
Now open a terminal and check that the Heroku CLI installed correctly with the following command:
heroku --version
Next, you'll need to login to your Heroku account with the command:
heroku login
This will redirect you to a web page where you can login with your GitHub credentials. Now you have everything set up to deploy this app directly to Heroku.
But first, you'll need to install a few packages to get this working. Inside the root folder, create the following new files:
Now, open a terminal and get ready to install all the packages you need. I prefer npm but feel free to use yarn.
npm install cors express johnny-five
These are the only packages you'll need, and it's just like setting up any other Node app.
server.js
You'll need to create two endpoints to control when the beeper is on or off. These are the endpoints you referenced on the front end in those fetch requests. Open your server.js file and add the following code:
const { Board, Led } = require('johnny-five');
const cors = require('cors');
const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const board = new Board({
port: "COM4",
});
let beeper;
board.on("ready", () => {
console.log("Ready!");
beeper = new Led(13);
});
app.get('/api/startBeeper', (req, res) => {
console.log('on');
beeper.on();
res.send({
message: 'on'
});
});
app.get('/api/stopBeeper', (req, res) => {
console.log('off');
beeper.off();
res.send({
message: 'off'
});
});
app.listen(PORT, () => {
console.log(`endpoints running on port ${PORT}`);
});
This code sets up a normal express app and connects it to localhost:3000. It also creates a new instance of the Board object so you can connect to your Arduino and declare a variable representing the beeper. You'll want to get the Bluetooth address and use it in the port option for the board. This will allow you to connect to your board after you deploy to a Heroku server. It then starts up the Board with the on method and the ready option. Inside this code block, you can send a message to the console so you know the board should be on.
Lastly, you need to set the value for beeper. I defined it as an LED because we only need a simple "high/low" signal sent to the board to make it work. When it comes to hardware, it's often better to keep things simple. Beeper is also connected to pin 13, similar to its physical counterpart.
The last part of the back end is writing the two endpoints. Since we're toggling a beeper on and off with the button click on the front end, one endpoint turns it on, and the other turns it off.
I usually don't leave console.log in my code, but these can really help with debugging. Sometimes, the hardware works immediately. Other times, a little tinkering might be necessary to get it all working together. This code prepares you for both scenarios and is everything you need for the beeper to work. You technically don't even need the front end if you remember the endpoint names!
Johnny-Five does some magic with the Board object. When you call the board.on() method, it automatically finds and connects to the Bluetooth address of the HC 05 module as long as there is power to it and the Arduino. Once the code is connected to the physical board, Johnny-Five then looks for the physical beeper based on the pin number you passed to the LED object. When you click the button on the front end, it calls the corresponding endpoint sending either a high or low signal to pin 13, which turns the beeper on or off.
Procfile
Finally, enter the following in the Procfile. This is a file specifically used by Heroku that specifies the commands to be executed by the app on startup. In this case, we define our web process as our server.
web: node server.js
If you want to use just idiomatic Node without any Heroku-specific files, you can use the start field from the package.json file.
Now, you can finally deploy your app so you can find your dog anywhere, any time.
We're almost done! By this point, you've probably put a few hours into this IoT project, so let's make the most of it. Since dogs can disappear anywhere, it's prudent to deploy your app so you can access it anywhere.
I chose to connect my app to Heroku by deploying through the Heroku CLI. Heroku provides great, simple instructions for quickly getting things set up and live. There are several things you need to make sure to change, which include:
{
"name": "dog-locator",
"version": "0.1.0",
"scripts": {
"build": "npm install",
"dev": "npm run build && npm run start",
"start": "node server.js"
},
"dependencies": {
"concurrently": "^5.1.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"johnny-five": "^1.4.0",
"path": "^0.12.7"
}
}
Once you have the settings you need in place, you can deploy your app. The app will search for the HC 05 and find the Bluetooth address to use for the connection. Make sure that your Arduino and HC 05 have power before you deploy or you might run into some errors with the initial connection.
If you want to clone the code for this project, you can get it from GitHub here: https://github.com/flippedcoder/arduino-johnny-five-locator
Now open a terminal and get ready to use the Heroku CLI. Since you already have it installed and you've logged in, you should be able to run the command to make a new, empty application on Heroku:
heroku create
Then run the following command to deploy the project directly to Heroku:
git push heroku master
After pushing the project in the last line, you should see something in your terminal similar to this and then your project will be live!
To be honest, I like deploying side projects on this platform because CI/CD is one of my weak spots, and this is good practice! And having this app live makes it easy for me to find my dog anywhere I go.
Congratulations! You now have a fully functioning IoT dog collar that lets you find your pet anywhere! Now put it to the test. Play hide-and-seek... Run around the backyard... Throw some frisbees around... Do whatever you'd normally do with your dog. The most important thing here is to make sure that your new collar works for you and your pup's lifestyle.
Now that you've completed your IoT dog collar, there's only one question left: What will you build now? These endeavors take time, patience, and perseverance, however, the process is often fun and rewarding. I hope this side project has given you some ideas about what to work on next.
In case you're building something new off this project or just want to review the code, you can find it here. And if you need inspiration for your next IoT project, I highly recommend these resources: