Ever feel like ringing a bell requires too much effort? Ever wish you could automate it to ring when something – like a sale – happens? If you responded "yes" to at least one of these questions, fret not. There is now a solution: BellBot.
This tutorial will guide you through building your own BellBot to automate bell ringing! The BellBot system is made of:
The Arduino Uno is a microcontroller board based on the ATmega328P chip. It's a popular board due to its low cost, ease of use, open-source nature, and strong community. We will use it as the interface between our node.js server and the servo.
A servo is a device that has an output shaft whose angle can be precisely controlled through an input line. Our servo will be responsible for striking the bell. To do so we attach an arm to the servo's output shaft and align its end with the bell, as seen in the video. Using a pencil for the servo's arm is a fast and easy option for prototyping.
Breadboard & Jumper Cables
A small basic breadboard and some jumper cables are perfect for fast prototyping. In this project we'll be using the power rails to provide common +5V and GND (ground) nodes.
We'll be powering the system via USB in this project. Thus, adding smoothing capacitors should help stabilize the circuit and protect against current spikes. A 200uF capacitor works well.
Set up the circuit
Follow the diagram and schematic below to set up the circuit.
- Connect the servo's Vin to the Arduino's +5V pin.
- Connect the servo's GND and any of the Arduino's GND pins to a common ground.
- Connect the servo's control line to one of the digital I/O pins on the Arduino. This tutorial uses pin 8.
- Add a capacitor or two in parallel to the +5V pin and the common GND to protect against possible current spikes. Remember that capacitors, unlike resistors, add up in parallel.
- Finally, connect the Arduino to your computer with A USB cable. This will power up the circuit and enable communication with the host computer.
Note: If you'd rather power the system through an external power supply, read Using an External Power Supply under the Notes section.
Write the Arduino code
The Arduino code will consist of the standard firmata example included in the IDE. The Arduino IDE is the environment in which we write and upload sketch code to the Arduino Uno. You can download the IDE here.
- In the Arduino IDE, go to File > Examples > Firmata to find the standard firmata code. The code implements a communication protocol between the Arduino and any host computer. With this protocol and the Johnny Five module, we can control the Arduino within node.js.
- Save the standard firmata code and then select your board from Tools > Board
- Finally, upload the sketch to the Arduino.
Writing our own Arduino sketch to control the servo is also an option. But, we would lose the abstraction and simplicity of controlling the hardware within node.js. Checkout Sketch code under the Notes section if you're interested in writing your own Arduino code.
Write the node.js code
We will be using node.js as our local web server. It will listen for incoming POST requests to the
- If you haven't already, download Node.js here.
Install project dependencies
- Once node.js is installed, run the following command in your project's directory to create a new
package.jsonfile. This file maintains info about the project and its dependencies.
- Next, install the following node modules into the auto-generated local
node_modulesfolder. By including the
--saveoption in the following commands, npm updates
express - A popular framework we will use to set up a web server.
npm install express --save
body-parser - A tool used by express to parse requests' bodies
npm install body-parser --save
ngrok - A tool to tunnel localhost to a public URL hosted by ngrok
npm install ngrok --save
johnny-five - A vast library to control the Arduino and hardware within node.js
npm install johnny-five --save
If you cloned the latest BellBot code, you only need to run,
npm will look at the
package.json file and install all the required modules.
This module parses command line arguments that we supply. Optional arguments include:
- proto - the application protocol to use. Default: 'http'
- port - the networking port number for the server. Default: 3000
- start - the starting and resting angle of the servo arm. Default: 75.
- strike - the angle of the servo arm when striking the bell. Default: 90
- pin - the arduino output pin that controls the servo's angle. Default: 8
- sdelay - the amount of time in milliseconds to wait before resetting the servo's arm after it has struck the bell. Default: 500.
- pdelay - the amount of time in milliseconds to wait before processing the next command. Default: 1000
- key - the optional key to authenticate request with. Default: null
If the BELLBOT_KEY environment variable exists and no key is supplied in the arguments, the server will authenticate incoming requests using the BELLBOT_KEY. We explain how to set up a BELLBOT_KEY later.
This module creates an object that describes the BellBot's behavior. It uses our args.js module to override default settings. Note that the URL is initially blank. We later set this URL to the unique public URL that ngrok supplies us.
This module provides a constructor for a servo controller. Note that the controller's timeout property corresponds to the processing delay – that is, the delay between sending requested commands.
This is the main entry point of the app. The file:
Require's all the needed components.
- Connects to the Arduino.
- Starts up an ngrok process.
- Starts the express server.
Add a .bellbotrc file
If you want to add some basic authentication to verify requests with a password, create a
.bellbotrc file in your home directory with a specified BELLBOT_KEY:
- Create the .bellbotrc file:
- Add the following line to the .bellbotrc file:
- In the command line, run
to source the newly added environment variable.
Next time you start your BellBot server, it will authenticate requests with that specified password. The incoming POST requests must have a
token body parameter that matches the password.
Test it out
Boot up the BellBot by running
in the command line.
Pass optional arguments if you wish. For example,
node index.js port=3001 pin=9 key=my-secret-key
will start the BellBot with:
- The server listening on port 3001
- The arduino outputting on digital I/O pin 9
- Authentication using my-secret-key as the password
It is important to make sure BellBot is behaving properly before unleashing it upon the world. After starting your BellBot,
- Use curl or a program like Postman to build and send test POST requests. If you are authenticating requests, pass
token:as a body parameter.
- Test locally by sending POST requests to localhost from your machine.
- Next, verify that the public address supplied by ngrok is hitting your local server by using the ngrok URL as the POST destination.
Make it a Slack-controlled BellBot
A neat way to automate bell-ringing is to use Slack. In slack, you can add and configure outgoing webhooks. For example, let's add a webhook that sends a customized POST request whenever a message beginning with
:bell: comes in.
To do this:
- Create a new outgoing webhook: Apps & Integrations > Manage > Custom Integrations > Outgoing WebHooks > Add Configuration.
- Select the slack channel that the webhook will be listening in. For example, a "sales" or "bots" channel.
- Set the trigger word that will cause the POST request to be sent. For example, the
- Set the URL to the public ngrok URL that maps to your local server.
- If your BellBot is configured to require authentication, set the Token to your secret BELLBOT_KEY.
Now all that's left is to make sure that the specified channel receives an automated message that triggers the webhook whenever a sale occurs.
A servo uses error-sensing negative feedback to correct and maintain its shaft's angle. The signal sent to the input is a PWM voltage signal. The width of the pulse is what controls the angle of the shaft. Check out this Seattle Robotics guide for more details.
Using an External Power Supply
Servos are notorious for drawing lots of power. When using USB power only, the 5V output on the Arduino is what powers the servo.The high current drawn during the servo's rotation may exceed the limits of the USB ports (often ~500mA at 5V). When the current exceeds this threshold, the host computer may disable the port. Additionally, the Arduino may reset and behave erratically due to voltage sags. Check the servo's data sheet for its idle, running, and stall currents. You want them to be low enough to be supplied via USB. Adding a capacitor in parallel to the 5V output and ground can help protect against these undesired effects.
To avoid these concerns altogether, follow the diagram and schematic below to set up an externally-powered BellBot.
- Power the servo and Arduino through an external power supply. Four AA 1.5V batteries provides ~6V, which should be enough to power both components reliably.
- Connect the voltage source's output to the Vin input on the Arduino.
- Connect the voltage source's output to the Vin of the servo.
- Connect the voltage source, servo, and Arduino to a common ground.
- Connet the servo's control line to one of the digital I/O pins on the Arduino.
- Connect the Arduino to your computer using a USB cable. The USB connection's role is reduced to serial communication. The Arduino will use the battery power as long as it's switched on, even when the USB is connected. If you switch off the battery, the USB connection will power the Arduino but not the servo.
An alternative option for BellBot's software is to write your own Arduino code. For example, the following sketch listens for the 'R' character to ring the bell.
The node.js server code would need refactoring. It would no longer require the whole Johnny Five module, and would use just the Serialport module to send data to the Arduino in a more barebones fashion.
Enhance your BellBot by implementing these ideas:
Add more routes
More routes to your express server would expand the possible types of requests. For example, a
/sweep route could cause the servo to begin sweeping. Or, if there are many bells and servos, a REST API could allow a user to control each servo.
Create a web interface
A web app or mobile phone app for this project could allow users to monitor or control the states of the servos. Admins or users could analyze or act on statistics and data logs of requests.
Use more hardware
LEDs could light up whenever the servo is working or a request comes in. A network of servos could handle different types of requests. Light sensors could control the operation state of the servos (on if the lights are on). These are just some ideas!
Build a black box
Rather than exposing the system as a prototype, you could build a professional PCB and enclosure to abstract away the system.
Use the Raspberry Pi
It should be straightforward to port this project to a Raspberry Pi. The node.js server would run on the Pi itself, with the servo connected to its GPIO pins. No USB connection would be necessary.
- Electronics - http://www.allaboutcircuits.com/education/
- Arduino - https://www.arduino.cc/en/Guide/HomePage
- Servos - http://www.seattlerobotics.org/guide/servos.html
- Servo & Arduino - https://learn.adafruit.com/adafruit-arduino-lesson-14-servo-motors/overview
- Ngrok - https://ngrok.com/docs
- Sparkfun - https://www.sparkfun.com/
- Express - https://codeforgeek.com/2014/06/express-nodejs-tutorial/