Alexa Controlled Servo
d. bodnar 01-01-2018

 

https://youtu.be/urd_OQhizIw

Introduction
I have a laptop on a shelf in my office that monitors several cameras that are around the outside of my house.  They alert me to deliveries and visitors.  While I can use a web browser to see their images it is easier to just glance at the screen on the laptop from time-to-time to see what's up.

Unfortunately the laptop's screen saver cuts in after 30 minutes and blanks the screen.  That forces me to get off of my chair and press the spacebar or shift key to bring the screen back.

Having a voice activated Alexa controlled "finger" that could touch a key on the keyboard is surely not the simplest solution but it sounded like a fun project.  This servo device places a movable arm just above a key on the keyboard.  The statement "Alexa turn on keyboard" cycles the servo arm, pressing down on the shift key & renewing the screen - nice!

The application presented here is just one way that the servo can be used.  Other applications include throwing a wall switch that turns lights on/off or moving some other device, perhaps a latch on a door or cabinet.  If you come up with other applications please drop me an email and let me know (dave@davebodnar.com).

Hardware
  • Wemos D1 -  from BangGood and Amazon.
  • micro servo - Amazon  and BangGood
  • 3300 uf, 6.3 volt electrolytic capacitor - any fairly high capacity capacitor should work (see notes in article)

The "clamp" that holds it all together is shown here.  The servo goes in the upper right and the Wemos goes into the holes to the left.  The large tapered slot holds it to the side of the laptop.  You will need to be changed the dimensions of that slot to fit your laptop.  Click here to download a PDF or CorelDraw version of this clamp.  The sixteen small holes for the Wemos are not electrically connected to anything - the are just there to help hold the controller in place.

 

Putting it Together
The parts that I used are listed above and shown here. 

All of the connections are made by soldering right to the Wemos D1.  The capacitor and 5 volt power connecting go to the 5v and G pins.  The servo also connects to these pins for power.  The servo's data line (the white wire in this photo) goes to pin D5.  Those are the only connections that are needed.  Power can be supplied from an external 5 volt power supply or, as in this case, by a USB cable plugged into the laptop.  The 3300 uf capacitor was added when the Wemos crashed periodically, probably due to variations in the supply voltage.  Since the cap was added the unit has been very stable.  Other electrolytic caps of 1000 uf or more should work.

Here the Wemos & servo are mounted and the acrylic clamp has been placed on the keyboard.

Using with Alexa
After programming with the code below (be sure to change the SSID and password to match your system) I told Alexa to discover devices.  In a minute or so she reported that she had found a new device called keyboard.  Once that is set the servo can be activated by saying "Alexa turn on keyboard" - note that there is no need to say "Alexa turn OFF keyboard" as the servo arm returns to the off position after pressing a key.
Other Uses
The servo can be used to move other things as well.  Thingiverse.com has several designs for a servo operated light switch including this one that can be 3D printed:
https://www.thingiverse.com/thing:1156995/#comments
Software - file name:  wemos-3-oneLED-SERVO-test-v2-4
The core code is below - you need to download this ZIP file to get the other tabs that are needed.
If you want to change the name that Alexa uses with this device from "keyboard" to something else you need 
  to change the word "keyboard" to your word in a number of places.  
  To simplify this I just changed ALL instances of "keyboard" to the new word 
  using the search and replace function (edit / find).
The code includes a routine that blinks the on-board LED on the Wemos every second.  
  This was added to give the controller a "heart beat" during testing.  
  If you find it unnecessary or distracting  it can be deleted.
Note that a number of libraries must be added to your Arduino IDE for this sketch to compile - 
  They are at the top of the listing in the "#include" statements.
  You also have to add the Wemos to the IDE 
  (see: http://www.instructables.com/id/Wemos-ESP8266-Getting-Started-Guide-Wemos-101/ ) 
 
// working d. bodnar 12-21-2017 
/*
   static const uint8_t D0   = 16;
  static const uint8_t D1   = 5;
  static const uint8_t D2   = 4;
  static const uint8_t D3   = 0;
  static const uint8_t D4   = 2;
  static const uint8_t D5   = 14;
  static const uint8_t D6   = 12;
  static const uint8_t D7   = 13;
  static const uint8_t D8   = 15;
  static const uint8_t RX   = 3;
  static const uint8_t TX = 1;
*/

#include <Servo.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <functional>
#include "switch.h"
#include "UpnpBroadcastResponder.h"
#include "CallbackFunction.h"
unsigned long previousMillis = 0;
const long interval = 1000;
boolean connectWifi();
void shiftkeyOn();
void shiftkeyOff();
// Change this before you flash
const char* ssid = "main2";
const char* password = "pppppppp";
boolean wifiConnected = false;
UpnpBroadcastResponder upnpBroadcastResponder;
Switch *shiftkey = NULL;
Servo myservo;  // create servo object to control a servo
int pos = 0;    // variable to store the servo position

void setup()
{
  pinMode(BUILTIN_LED, OUTPUT);  // set onboard LED as output
  Serial.begin(9600);
  wifiConnected = connectWifi();
  if (wifiConnected) {
    upnpBroadcastResponder.beginUdpMulticast();
    shiftkey = new Switch("shiftkey ", 80, shiftkeyOn, shiftkeyOff);
    Serial.println("Adding switches upnp broadcast responder");
    upnpBroadcastResponder.addDevice(*shiftkey);
  }
}

void loop()
{
  if (wifiConnected) {
    upnpBroadcastResponder.serverLoop();
    shiftkey->serverLoop();
  }
  // unsigned long currentMillis = millis();
  if (millis() - previousMillis >= interval) {
    previousMillis = millis();
    digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED));
  }
}

void shiftkeyOn() {
  myservo.attach(14);  // attaches the servo on pin 12 to the servo object
  Serial.print("Switch 1 turn on ...");
  for (pos = 0; pos <= 90; pos += 1) { // goes from 0 degrees to 180 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    Serial.println(pos);
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 90; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    Serial.println(pos);
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  myservo.detach();  // attaches the servo on pin 12 to the servo object
}

void shiftkeyOff() {
  Serial.print("Switch 1 turn off ...");
}


// connect to wifi  returns true if successful or false if not
boolean connectWifi() {
  boolean state = true;
  int i = 0;
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");
  // Wait for connection
  Serial.print("Connecting ...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (i > 10) {
      state = false;
      break;
    }
    i++;
  }

  if (state) {
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.println("");
    Serial.println("Connection failed.");
  }

  return state;
}