Week 13 - Final Build

Wafibot

Wafibot turns a switch on using wifi.

Wafiperson turns the switch back on using manual labor.

image
image

Challenges

1. Programming the ESP32

Programming the ESP32 took the first 2-3 weeks. Whre my initial plan was to get the bluetooth functionality working, the ESP32 didn’t support it.

So I pivoted into using Wifi over HTML.

2. Programming & Calibrating the Motor

The next 2-3 weeks were spent getting the motor to properly calibrate and build the final design. Instead of mounting the motor to the circuitboard directly.

One design improvement I made involved separating the motor from the circuitboard. This, then, can support more than one motor per circuit board.

Current maximum is 4.

🛠
The limit of 4 is because of the 4 pwm output channels limit. I will have to figure out how to expand or multiplex if I want to support more. Ideally a single circuit board should be able to control 10-12 switches with PWM.

Wins

The switchbot costs $25 if you buy a pack of 4. That’s $25 per switch.

The wafibot costs $10 per switch. If I add additional support. I can reduce the cost to $5 per switch, if I connect 4 to one board.

Losses

Looks incredibly ugly.

Coin Battery not driving enough power. Switched to Lipo battery

Appendix

Board Design

image

Schematic

image

Motor Calibration

This servo wasn’t working with the Esp32Servo.h library so I had to find a way to manually send the pwm signals. I finalized on the following PWM settings

image

Full Arduino Code

/*
  WiFiAccessPoint.ino creates a WiFi access point and provides a web server on it.

  Steps:
  1. Connect to the access point "yourAp"
  2. Point your web browser to http://192.168.4.1/H to turn the LED on or http://192.168.4.1/L to turn it off
     OR
     Run raw TCP "GET /H" and "GET /L" on PuTTY terminal with 192.168.4.1 as IP address and 80 as port

  Created for arduino-esp32 on 04 July, 2018
  by Elochukwu Ifediora (fedy0)
*/

#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <ESP32Servo.h>

#define SERVO 12  // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED

// Set these to your desired credentials.
const char *ssid = "wafiwifi";
const char *password = "wafi1234";

int APin = 12;
ESP32PWM pwm;
int freq = 1000;

const int ServoPin = 12;  /* GPIO16 */

int dutyCycle;

/* Setting PWM Properties */
const int PWMChannel = 0;
const int PWMFreq = 50; /* 50 Hz */
const int PWMResolution = 10;
const int MAX_DUTY_CYCLE = (int)(pow(2, PWMResolution) - 1);



WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");

  // You can remove the password parameter if you want the AP to be open.
  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();

  // Allow allocation of all timers
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);

  // Motor Setup
  Serial.println("Server started");
  ledcSetup(PWMChannel, PWMFreq, PWMResolution);
  ledcAttachPin(SERVO, PWMChannel);
  ledcWrite(PWMChannel, 54);
  delay(2);
}

void loop() {
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("New Client.");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            // the content of the HTTP response follows the header:
            client.print("Version 1 | ");
            client.print("GPIO");
            client.print(SERVO);
            client.print("<br>");
            client.print("Click <a href=\"/H\">here</a> to turn Trigger the switch.<br>");

            // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        // Check to see if the client request was "GET /H" or "GET /L":
        if (currentLine.endsWith("GET /H")) {
          ledcWrite(PWMChannel, 66);
          delay(2500);
          ledcWrite(PWMChannel, 48);
          delay(2500);
        }
      }
    }
    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }
}