Privy Engineering


Building a BellBot

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:

  1. A node.js server hosted on a local machine.
  2. An Arduino Uno connected to the machine via USB.
  3. servo connected to the Arduino.
  4. An ordinary call bell.

Required Hardware

Arduino Uno

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.


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.

  1. Connect the servo’s Vin to the Arduino’s +5V pin.
  2. Connect the servo’s GND and any of the Arduino’s GND pins to a common ground.
  3. Connect the servo’s control line to one of the digital I/O pins on the Arduino. This tutorial uses pin 8.
  4. 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.
  5. Finally, connect the Arduino to your computer with A USB cable. This will power up the circuit and enable communication with the host computer.

Diagram for a USB-powered BellBot.

Diagram for a USB-powered BellBot.

Schematic for a USB-powered BellBot.

Schematic for a USB-powered BellBot.

Note: If you’d rather power the system through an external power supply, read Using an External Power Supply under the Notes section.

BellBot in action

BellBot in action

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.

  1. 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.
  2. Save the standard firmata code and then select your board from Tools > Board
  3. 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

Install node.js

We will be using node.js as our local web server. It will listen for incoming POST requests to the /ring route and relay them to the Arduino. Node.js describes itself as “a JavaScript runtime built on Chrome’s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world.” You can read more about it here.

  1. If you haven’t already, download Node.js here.

Install project dependencies

  1. Once node.js is installed, run the following command in your project’s directory to create a new package.json file. This file maintains info about the project and its dependencies.
    npm init
  2. Next, install the following node modules into the auto-generated local node_modules folder. By including the --save option in the following commands, npm updates package.json automatically.
    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 install

npm will look at the package.json file and install all the required modules.

Write args.js

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.

Write config.js

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.

Write servo_controller.js

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.

Write index.js

This is the main entry point of the app. The file:

  1. Require‘s all the needed components.
  2. Connects to the Arduino.
  3. Starts up an ngrok process.
  4. 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:

  1. Create the .bellbotrc file:
    touch ~/.bellbotrc
  2. Add the following line to the .bellbotrc file:
    export BELLBOT_KEY=<your_password>
  3. In the command line, run
    source ~/.bellbotrc
    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 key or token body parameter that matches the password.

Test it out

Boot up the BellBot by running

node index.js

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:

  1. The server listening on port 3001
  2. The arduino outputting on digital I/O pin 9
  3. 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,

  1. Use curl or a program like Postman to build and send test POST requests. If you are authenticating requests, pass token: <BELLBOT_KEY> as a body parameter.
  2. Test locally by sending POST requests to localhost from your machine.
  3. 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.

Creating a new Slack Outgoing WebHook.

Creating a new Slack Outgoing WebHook.

To do this:

  1. Create a new outgoing webhook: Apps & Integrations > Manage > Custom Integrations > Outgoing WebHooks > Add Configuration.
  2. Select the slack channel that the webhook will be listening in. For example, a “sales” or “bots” channel.
  3. Set the trigger word that will cause the POST request to be sent. For example, the :bell: emoji.
  4. Set the URL to the public ngrok URL that maps to your local server.
  5. 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 sales Slack channel that listens for incoming :bell: messges.

A sales Slack channel that listens for incoming :bell: messages.



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.

  1. 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.
  2. Connect the voltage source’s output to the Vin input on the Arduino.
  3. Connect the voltage source’s output to the Vin of the servo.
  4. Connect the voltage source, servo, and Arduino to a common ground.
  5. Connet the servo’s control line to one of the digital I/O pins on the Arduino.
  6. 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.
Diagram for BellBot running on an External Power Supply.

Diagram for BellBot running on an External Power Supply.

Schematic for BellBot running on an External Power Supply.

Schematic for BellBot running on an External Power Supply.

Sketch code

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.

Estimated cost

Item Cost ($)
Arduino Uno 24.95
Feetech Servo 12.95
Breadboard 4.95
Jumper Pack 1.95
Capacitor Pack 6.95
Total 51.75

Next Steps

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.

Further Reading