Code

Install the WiFiESP Library 

Set up the Arduino IDE
This video explains how to Install the WiFi ESP Library and program your Uno board.

Download the WiFi ESP Library.zip

From the Arduino IDE
Sketch > Include Library > Add .ZIP Library...
Navigate to the WiFiEsp-Library.zip and add it.

Add the following libraries to the top of your program:

Download file Copy to clipboard
1
2
3
4
#include "SoftwareSerial.h"
#include <Servo.h>
#include <WiFiEsp.h>
#include "WiFiEspUdp.h"

This is telling the Arduino IDE what other code your program will need access to when running.
You can use wither <LibraryName.h> or "LibraryName.h" to declare a library in your code.

Set Up WiFi 

The WiFiESP library needs some information to connect your ESP to your WiFi.
Add these three lines right below your library declarations:

Download file Copy to clipboard
1
2
3
char ssid[] = "YourWiFiName";       // The network SSID (name) you are connecting to
char pass[] = "YourWiFiPassword";   // The password of the network you are connecting to
int status = WL_IDLE_STATUS;        // The WiFi radio's status

Put in your WiFi name and Password with the name of your WiFi network as it appears to your phone or laptop.

  • For example if your home WiFi is called NETGEAR 2.4g and the password is ILoveThimble your code should look like this:
Download file Copy to clipboard
1
2
char ssid[] = "NETGEAR 2.4g";  // The network SSID (name) you are connecting to
char pass[] = "ILoveThimble";  // The password of the network you're connecting to

The status is used by the library to determine whether the ESP is connected to a network.
You will not need to change it.

Serial Communication 

To allow the Arduino to talk to the ESP we need to tell it what pins are connected. In the case of the Thimble Light Switch kit, the ESP connects to the A2 and A3 pins.
When looking at the Light Switch Kit schematic you'll notice that pin A2 of the Arduino connects to the RX pin of the ESP, and A3 to the TX pin of the ESP.

  • Serial communication works by connecting the TX of one device to the RX of another
  • In this case we are telling the program what the Arduino's new pins are for TX and RX with this command:
Download file Copy to clipboard
1
SoftwareSerial Serial1(A3, A2); // Arduino's: RX, TX

So the Ardunio A3 pin is the RX pin of the Arduino and gets connected to the TX pin of the ESP.

Setting up the Serial Monitor 

There is one last thing we need to do before we can get the code for connecting the ESP to the WiFi.
Working from inside the setup loop (remember the setup loop only runs once at the start of the program) we need to start the serial communication with the ESP and to the Arduino Serial Monitor on your computer so you can see what is going on.
Add the following lines to your Arduino code in the Setup loop:

Download file Copy to clipboard
1
2
3
4
  Serial.begin(115200); //serial monitor output for debugging
  Serial1.begin(9600);  // Serial for the ESP to talk to the Arduino
  WiFi.init(&Serial1);  // Tell the ESPWiFi library what serial to talk to the ESP
  Serial.println("===== Thimble Remote Control Light Switch =====");

The Serial.begin is what will be used for the Serial Monitor on your computer. The number you see in the parenthesis is the baud rate which is how fast the serial monitor talks to devices. Serial1.begin is for the software serial we set on the page before; this is for the ESP.

Upload the code to your Arduino. Open the serial monitor and set the baud rate to 115200.
You should now see the message from above printed out. If you aren't sure how to do this, watch the video at the beginning of this section.

  • It is important that the baud rate for the ESP (Serial1) is slower than the Serial monitor speed otherwise we will not be able to see the data.
    • Try changing the baud rate in the bottom right of the serial monitor to something different than 115200. Notice what happens to the text when you set it faster or slower.

Connecting to the WiFi 

The following code uses the WiFiESP library to communicate with your ESP.
Copy it into your setup loop; because your ESP only needs to setup the connection to your WiFi once each time the kit is powered on.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
  if (WiFi.status() == WL_NO_SHIELD) {    // Check for the presence of the ESP
    Serial.println("WiFi shield not present");
    while (true);                         // Don't continue, because the ESP isn't connected.
  }

  while ( status != WL_CONNECTED) {       // Attempt to connect to WiFi network
    Serial.print("Attempting to connect to SSID:");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);      // Connect to WPA/WPA2 network
  }
  Serial.println("Successfully connected to WiFi:");
  printWiFiStatus();

The last line printWiFiStatus(); calls a function which shows you information about your WiFi connection.

Adding Functions 

Paste this function from the WiFiESP library, at the very bottom of your program, after the closing brace of your loop. You will not need to change it in this tutorial.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// =========== Functions ===========

void printWiFiStatus() { // Shows information about the WiFi connection:
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Once you upload your code and open the serial monitor you should see something like this (with a different SSID and IP Address):

Download file Copy to clipboard
1
2
3
4
5
6
7
===== Thimble Remote Control Light Switch =====
Attempting to connect to SSID: ThimbleHQ
[WiFiEsp] Connected to ThimbleHQ
Successfully connected to WiFi:
SSID: ThimbleHQ
IP Address: 10.0.10.154
signal strength (RSSI):-51 dBm

The SSID, IP Address and Signal strength are all being printed out by the printWiFiStatus function.

Controlling The Servo 

We will need a way to control our servo; for now lets use the large button on the PCB. Have a look at the schematic to see what pin it's connected to.

If you are having trouble finding the button pin on the schematic, Head to the Troubleshooting Section

Once you figure out the pin, add the following lines to the start of your code before the setup loop. Make sure to to fill in the buttonPin with the correct one for the Arduino.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
Servo ThimbleServo;         // Give our Servo a name
int buttonPin = ;           // Pin the Arduino is reading the button signal
boolean buttonState = HIGH;	// Button pressed state

int center = 85;            // Servo positions 0-180 degrees
int up = 40;
int down = 150;

int switchCase = 0;         // Used for the buttonCase function
int nextCase = 0;

Reading the Button 

To tell the Arduino how to read the state of the button, we need to set the pin function by adding this line in the setup loop of our program.

Download file Copy to clipboard
1
  pinMode(buttonPin, INPUT_PULLUP); // set button pin as an input pin with a pull-up resistor (makes sure that it is high unless connected to ground)

This tells the Arduino that the buttonPin is high until the button is pushed, connecting it to ground, and making it go low.

Now that we have all the setup for the button in place we need to tell the program when to actually take input from the button, and what to do with it.
For that we add this assignment and an if statement to the main loop of our program:

Download file Copy to clipboard
1
2
3
4
  buttonState = digitalRead(buttonPin);	// Read button state
  if (buttonState == LOW) {
    buttonCase();                       // Enter the buttonCase function
  }

This line: buttonState = digitalRead(buttonPin); sets the boolean called buttonState to whatever the button is.
So when the button it's pressed the boolean will be HIGH because the button pin is pulled up to 5v.

There is one final function we need to add, and it is the most important one. This is the function that gets called whenever you press the button. This function contains the actual code the moves the servo to turn the lights on and off.

Add this to the functions section of your code:

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void buttonCase()               // This is what controls the movement of the servo
{
  switch (switchCase)
  {
    case 0:         //  === W A I T ===
      if (nextCase >= 2)        // If the lights were just turned off
        nextCase = 1;           // The next state will be turning them On
      else
        nextCase += 1;          // Otherwise add one to nextState to go to the next state

      if (buttonState == LOW)
        switchCase = nextCase;  // When button is go to the next state
      break;                    // End case 0 (Wait)

    case 1: // ========== L I G H T S  O N ===========
      Serial.println("Turning the lights On.");      
      ThimbleServo.attach(A0);	// Set up the servo on Arduino Pin A0 (for servo 1 header on PCB)

      ThimbleServo.write(40);   // Tell servo to go to UP
      delay(500);               // Wait 1/2 second for the servo to reach the position
      ThimbleServo.write(85);   // tell servo to go to CENTER
      delay(500);

      ThimbleServo.detach();    // turn off the servo to save power.
      switchCase = 0;           // Go back to WAIT case
      break;                    // End Case 1 (lights on)

    case 2: // ========== L I G H T S  O F F ==========
      Serial.println("Turning the Lights Off.");    
      ThimbleServo.attach(A0);

      ThimbleServo.write(150);  // Tell servo to go to DOWN
      delay(500);
      ThimbleServo.write(85);   // Tell servo to go to CENTER
      delay(500);

      ThimbleServo.detach();
      switchCase = 0;
      break;                    // End case 2 (Lights off)

  } // End switch statement
} // End buttonCase function  

This function contains a switch statement. A switch statement can only run from one case at a time.
This switch statement has three cases: 0, 1, 2. Each case does something different.

For example Case 1 does the following in this order:

  • Prints out that it's turning the lights on
  • Attaches the servo to pin A0 (this enables the servo)
  • Moves the servo up
  • Waits for the servo to finish moving
  • Moves back to the middle position
  • Waits for the servo to finish moving
  • Detaches the servo (this turns the servo off to save power)
  • Sets the next switch case to 0 (the wait case)
  • break; exits the current case

You may find that the values here for the servo's up and down position don't quite work for you light switch. You will have to experiment with different values until you find the ones that work for your switch.

Upload the code and watch your serial monitor. When you press the button you should see the servo move up and down! If not, don't worry, go back over the last few steps and double check that you have everything in your code. If you're still stuck, head to the Troubleshooting section for some tips on common mistakes.

UDP Packets 

To allow a computer or mobile phone to control your light switch kit you'll need to add support for your Arduino to receive UDP packets.
Put simply a UDP packet is package of information that contains three main things:

  • Destination IP Address (In this case the IP of the ESP you saw in the serial monitor earlier)
  • Port number
  • Some data (This is the most important part!)

For our code to start accepting UDP packets we need to add a few things. The following four lines will go up top before the setup loop:

Download file Copy to clipboard
1
2
3
4
5
WiFiEspUDP Udp;                         // Start the UDP library

char packetBuffer[255];                 // Buffer to hold incoming packet
char ReplyBuffer[] = "Message Received"; // A string to send back
unsigned int localPort = 10109;         // Local UDP port to listen on

The first line enables the UDP functions from the ESP WiFi library you installed at the beginning of this module. The packetBuffer is the place we will store the message you receive in a packet.

When you get a UDP packet the ESP will send a response to whatever device sent the packet. You can change the Message Received to whatever you like, but keep in mind, too many characters can fill up the buffer of the other device.

Lastly the localPort is exactly what is sounds like. If a UDP packet is sent to the IP of your ESP but a different port it will be ignored, so make sure this is the same port on both the sending device and your ESP. We've chosen port 10109 because it is unlikely to be in use by any other device in your home. You can see a list of port numbers and their uses on Wikipedia here.

We will also need to add this to the setup loop:

Download file Copy to clipboard
1
2
3
4
  Udp.begin(localPort);  // Start listening for incoming UDP packets

  Serial.print("Listening on port ");
  Serial.println(localPort);

This starts the ESP listening on the local port we set above and prints out the port number for reference.

Actions Based on UDP packets 

Now that we have your ESP set up to receive and respond to UDP packets it's time to do something with them!

This might look like a lot of code, but it is very simple once we break it down.
For now, add it to your program loop just after the button reading if statement:

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int packetSize = Udp.parsePacket();       // If there's data available, read a packet
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remoteIp = Udp.remoteIP();  // Tell the program what IP we just received a message from
    Serial.print(remoteIp);
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    int len = Udp.read(packetBuffer, 255); // Read the packet into packetBufffer
    if (len > 0) {
      packetBuffer[len] = 0;
    }
    Serial.print("Message: ");
    Serial.println(packetBuffer);          // Prints out the data we just received in the packet

    if (strcmp(packetBuffer, "On") == 0) { // Checks to see if received packet matches the text string: on
      nextCase = 1;
      switchCase = 1;
      buttonCase();                        // Enter the buttonCase  function
    }
    else if (strcmp(packetBuffer, "Off") == 0) { // Checks to see if received packet matches the text string: off
      nextCase = 2;
      switchCase = 2;
      buttonCase();                        // Enter the buttonCase  function
    }

    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); // send a reply, to the IP address and port the last packet came from
    Udp.write(ReplyBuffer);                // Send the char 'ReplyBuffer' we set at the beginning of the program
    Udp.endPacket();
  }

The first block of Serial.print statements is showing the information about the UDP packet you've received. This can be useful for debugging.

The next block reads the message from the packet into your buffer, then prints it to the serial monitor as well.

The next block of if and else if statements are what acts on the message you receive in the UDP packet. Right now if the UDP packet contains the word "On" the code will set the switchCase to 1 (which is the Lights ON case) and calls the buttonCase .
When this happens the code acts the same as it did when you pressed the button, going right to the servo moving case statement.

After that, the last three lines are what sends the ReplyBuffer message back to the device which sent you the UDP packet.

Set Up Your phone 

Sending UDP packets is very easy, there are many free app that can do this. We recommend UDP Sender for Android, and TCP-UDP Client for iOS devices.

For Android:

Once installed enter the Destination IP as the IP of your ESP from the serial monitor.
Enter the Port from this step.
Set the Text as either On or Off and tap Send to control your lights!

Enter the IP of your ESP from the Serial Monior
Enter the IP of your ESP from the Serial Monior
Set the port number
Set the message text and tap Send

For iOS

Once installed, select UDP Connection.
Enter the IP of your ESP from the serial monitor.
Add the Port number from this step.
Set the Message as either On or Off and tap Send to control your lights!

Tap UDP Connection
Tap UDP Connection
Enter the IP of your ESP from the Serial Monitor
Set the port number
Set the message text and tap Send

Select Your Switch type 

The next two steps will guide you through attaching the WiFi Light Switch kit to both kinds of US light switches. Follow the step that matches your switch style.

Click here if you have a toggle switch like this one below:

Click here if you have a paddle switch like this one below:

Attachment To Toggle Switch 

Attach to a Toggle Switch Assembly
This video explains how to attach your kit to a Toggle Style light switch.

Double check that your servo is calibrated to the middle position from the Controlling The Servo step.

Carefully remove both the flat head screws of your light switch plate, but do not take the plate off! It may help to use some painters tape to hold it to the wall for the next few steps.
Place the screws in a bag from your kit so they don't get lost.

Carefully remove the screws holding your switch plate to the wall
Carefully remove the screws holding your switch plate to the wall
Carefully remove the screws holding your switch plate to the wall
Don't lose these screws! Stash them in your Thimble kit box for safe keeping

Screw the top screw into the hole where your switch plate screw was just removed. For now a couple of turns is enough, you will tighten it later.
Line up the light switch toggle with the large rectangular hole in the middle of your actuator plate.
Screw the bottom long screw into the other hole in your switch plate.
Attach the servo horn to your servo so it is as roughly straight across, you may need to adjust this later.
You should now be able to tighten both screws until the PCB no longer wobbles.

Line up the top screw
Line up the top screw
A few turns to the top screw of your kit should hold it to the wall for now
Line up the toggle switch with the rectangular hole on the actuator plate
Turn the bottom screw of your kit to attach it to the wall
Tighten the top screw until it is firm but not too tight
Attach the servo horn to the servo and tighten the bottom screw
Attach the servo arm facing to the right

Test Your Toggle Switch 

Your kit should now be mounted to the wall; you should be able to move the actuator plate slowly by hand with very little resistance except for that from the servo.
If that's not the case, you may have attached the bottom mounting screw too tightly, or have forgotten the washer. If you're still stuck, have a look at the Troubleshooting section for some solutions to common mistakes.

Attachment To Paddle Switch 

Attach to a Paddle Switch
This video explains how to attach your kit to a Paddle Style light switch.

Carefully remove both the flat head screws of your light switch plate, but do not take the plate off! It may help to use some painters tape to hold it to the wall for the next few steps.
Place the screws in a bag from your kit so they don't get lost.

Carefully remove the screws holding your switch plate to the wall
Carefully remove the screws holding your switch plate to the wall
Carefully remove the screws holding your switch plate to the wall
Don't lose these screws! Stash them in your Thimble kit box for safe keeping

Double check that your servo is calibrated to the middle position from the Controlling The Servo step.
If it is, go ahead and click the servo horn into the servo so it is facing to the right.
Screw the top screw into the hole where your light switch screw was just removed. For now a couple of turns is enough, you will tighten it later.
Screw the bottom long screw into the other hole in your light switch.
You should now be able to tighten both screws until the PCB no longer wobbles.

Attach the servo arm facing to the right
Attach the servo arm facing to the right
Line up the top screw to your light switch plate
A few turns to the top screw of your kit should hold it to the wall for now
Line up the bottom screw
Turn the bottom screw of your kit to attach it to the wall
Tighten both screws until they are firm but not too tight

Test Your Paddle Switch 

You're done with the assembly! Your kit should now be mounted to the wall; you should be able to move the actuator plate slowly by hand with very little resistance except for that from the servo. If that's not the case, you may have attached the mounting screws too tightly, or have forgotten the washer. If you're still stuck, have a look at the Troubleshooting section for some solutions to common mistakes.

Line up your Arduino
Line up your Arduino
Give it power
You can use a phone charger to power your kit if it's close to an outlet
Discussion and Comments for the Code block