Skip to content

Command Servos via Bluetooth

Most TinyShields can be used with other TinyShields without issue, as can be seen with our compatibility matrix, but there are some that won't work together at all, or need a workaround.

Today's tutorial highlights one of these workarounds to allow the Servo TinyShield to work with the BLE TinyShield, so you can do something cool like use your phone to turn a servo motor across the room. Some applications may include DIY pet (or person) feeders, and tiny robots.

Note that BLE is not the best for high speed, low latency control- for example, what might be needed for a fast radio control plane. Connections typically default to 20 updates per second, which is great for many other applications!

You will probably want to (re)view the TinyZero, BLE TinyShield and the Servo TinyShield tutorials before moving on with this page.




Common Issues:

  • Make sure the battery is connected and charged for the servo motor to work
  • You are sending commands to the correct servo (1, 2, 3, or 4)
  • The processor board is switched to 'ON'
  • The Correct servo address is selected in the program, the default is zero (It will change if you remove some of the resistors on the board, checkout the end of the Servo Tutorial if you'd like more information.)


Step 1

Attach the TinyZero board, Servo TinyShield, and BLE TinyShield together using the 32 pin connectors. Plug in the battery to the Servo TinyShield.

When it comes to plugging in the servo motor to the Servo TinyShield, you may need to do some soldering. Black/brown Ground wire goes to negative(-) labeled symbol, red Voltage wire goes to positive(+) symbol, and the yellow Signal wire goes to the sinusoidal(~) symbol on the board.

Disclaimer: These are the colors on the servos we offer. Most servos will stick to a color scheme like this, but you should always double check the documents of the hardware you're using.

Step 2

Be sure you have the above mentioned libraries downloaded. Then, here is the zip file for the actual program.

With the program open in the Arduino IDE, you should be able to make your Tools selections to connect to the TinyZero:

Tools selections for the TinyZero

Something you may need to note, depending on your computer, is the delay in the setup() loop between the BLEsetup() and servo.begin() function calls. If you get an error in the Serial Monitor that says "Motor driver not detected!" you may need to increase the delay. You may also have a computer where you do not need the delay at all.

Step 3

Once everything is assembled and software is properly downloaded, you can plug in your Micro USB cable from your computer to your TinyZero. Upload the following code by copy/pasting it into the Arduino IDE or by downloading the sketch above.

ST BLE and Servo TinyShield Arduino Sketch
//  TinyCircuits ST BLE and Servo TinyShield Example
//  Last Updated 24 Dec 2018
//  This example combines the UART Passthrough and Servo TinyShield example to
//  control a servo through the Nordic nRF UART app by sending microsecond pulse
//  values from 800 to 2200, such as '1500', through the terminal.
//  Written by Ben Rose, TinyCircuits

#include <SPI.h>
#include <STBLE.h>

#include <Wire.h>
#include <ServoDriver.h>

ServoDriver servo(NO_R_REMOVED);//this value affects the I2C address, which can be changed by
//removing resistors R1-R3. Then the corresponding R1_REMOVED,
//R2_REMOVED, R1_R2_REMOVED, R1_R4_REMOVED and so on can be set.
//Default is NO_R_REMOVED

//Debug output adds extra flash and memory requirements!
#ifndef BLE_DEBUG
#define BLE_DEBUG true

#if defined (ARDUINO_ARCH_AVR)
#define SerialMonitorInterface Serial
#elif defined(ARDUINO_ARCH_SAMD)
#define SerialMonitorInterface SerialUSB

uint8_t ble_rx_buffer[21];
uint8_t ble_rx_buffer_len = 0;
uint8_t ble_connection_state = false;

void setup() {
  while (!SerialMonitorInterface); //This will block until the Serial Monitor is opened on TinyScreen+/TinyZero platform!
  //pinMode(9, OUTPUT);//Pin 9 is the reset pin for the servo controller TinyShield, and the BLE TinyShield
  //digitalWrite(9, LOW);
  //digitalWrite(9, HIGH);
  BLEsetup();//This will toggle the shared reset line
  delay(15); // Not every ycomputer needs this delay between the BLEsetup() and servo.begin()

  if (servo.begin(20000)) {    //Set the period to 20000us or 20ms, correct for driving most servos
    SerialMonitorInterface.println("Motor driver not detected!");
    while (1);
  //The failsafe turns off the PWM output if a command is not sent in a certain amount of time.
  //Failsafe is set in milliseconds- comment or set to 0 to disable

void loop() {
  aci_loop();//Process any ACI commands or events from the NRF8001- main BLE handler, must run often. Keep main loop short.
  if (ble_rx_buffer_len) {//Check if data is available
    SerialMonitorInterface.print(" : ");
    if (ble_rx_buffer_len == 3 || ble_rx_buffer_len == 4) {
      int servoValue = strtol((char*)ble_rx_buffer, NULL, 10);
      if (servoValue >= 800 & servoValue <= 2200) {
        servo.setServo(1, servoValue);
        servo.setServo(2, servoValue);
        servo.setServo(3, servoValue);
        servo.setServo(4, servoValue);
    ble_rx_buffer_len = 0;//clear afer reading
  if (SerialMonitorInterface.available()) {//Check if serial input is available to send
    delay(10);//should catch input
    uint8_t sendBuffer[21];
    uint8_t sendLength = 0;
    while (SerialMonitorInterface.available() && sendLength < 19) {
      sendBuffer[sendLength] =;
    if (SerialMonitorInterface.available()) {
      SerialMonitorInterface.print(F("Input truncated, dropped: "));
      if (SerialMonitorInterface.available()) {
    sendBuffer[sendLength] = '\0'; //Terminate string
    if (!lib_aci_send_data(PIPE_UART_OVER_BTLE_UART_TX_TX, (uint8_t*)sendBuffer, sendLength))
      SerialMonitorInterface.println(F("TX dropped!"));

As the program uploads, you should open your Serial Monitor and see:

Now that the BLE TinyShield is discoverable, you should be able to see it on your app. Open nRF Connect:

What the nRF Connect app looks like (I will definitely get to those emails at some point)

Your device should have the name BlueNRG, click CONNECT:

You should see a new line on the Serial Monitor that looks like "Connected to device:XX-XX-XX-XX-XX-XX". Now you can send commands to the servo with the app by selecting the UART Service, and then selecting the up arrow symbol on the Nordic UART RX option:

The Devices and Characteristics pages on the nRF Connect app

With the text box open, you can now send commands with the app to move the servos. You can send between 800-2200 to the servo:

The Command Value window to send servo values to the BLE board

You should be able to see what commands you've sent by looking at the servo motor itself and the Serial Monitor:

Commands the Bluetooth module has received, displayed on the Serial Monitor

Now you can build a project with the use of these basics and commandable servo(s) at your fingertips!!

Contact Us

If you have any questions or feedback, feel free to email us or make a post on our forum. Show us what you make by tagging @TinyCircuits on Instagram, Twitter, or Facebook so we can feature it.

Thanks for making with us!