Close

From RaspberryPi (Python) to NodeMCU (Arduino)

A project log for Balambér

a robotic handpuppet

borazsloborazslo 12/20/2016 at 13:451 Comment

Balambér has worked well with the Raspberry Pi, but I needed a lightweight solution as well so as to be able to run Balambér on battery only. So I bought a NodeMcu ESP8266 V3 WIFI Internet Development Board. It is a nice and small arduino compatible board with wifi module so I can continue to give orders to Balambér through a webpage.

Hardware

I followed the simple steps of this guide on instructables.com, and my LED began to blink easily. So I could begin to work with PCA9685 16 Channel PWM Servo motor Driver. Adafruit has an easy to follow step by step guide to use this driver with any arduinoish boards.

I connected the NodeMCU's D4 pin to the drives's SDA, D3 to SCL, and 3V to VCC. This last one is very important as my servos should not consume current from the NodeMCU but from the power supply. And where is GND? I use the same power source (a homemade DC 5V voltage regulator) to power the NodeMCU and the servos. In this way the NodeMCU's GND and the motor driver's GND has already connected.


The Code

As the hardware was ready the time to rewrite the code has come. I installed the ESP8266Wifi module and the Adafruit_PWMServoDrive as I learnt from the guides above.

The script after connect2wifi() waits for an user input from the browser. Looking at the serial monitor you can find out the IP address of the NodeMCU. When getHttp() returns with a code of a command, we run the proper command like yes, now, bow, or clap.

Here you can check out the new code. If you have any problem understanding or adapting it, please give me a comment and I am ready to try to help you.

#include <Wire.h>
#include <ESP8266WiFi.h>
#include <Adafruit_PWMServoDriver.h>

const char* ssid = "ssid";
const char* password = "passwordForSsid";

WiFiServer server(80);

#define pwmSda D4
#define pwmScl D3

#define servoHeadVertical 0
#define servoHeadHorizontal 2
#define servoLeftArm 3
#define servoRightArm 1

void moveServo(int servo, int servoFrom, int servoTo, int servoDelay) {
  int servoStep = 5;
  
  if(servoTo > servoFrom) {
    for (uint16_t pulselen = servoFrom; pulselen <= servoTo; pulselen = pulselen + servoStep) {
      pwm.setPWM(servo, 0, pulselen);
      delay(servoDelay);
    }
  } else {
    for (uint16_t pulselen = servoFrom; pulselen >= servoTo; pulselen = pulselen - servoStep) {
      pwm.setPWM(servo, 0, pulselen);
      delay(servoDelay);
    } 
  }
}

void commandYes() { 
  moveServo(servoHeadVertical,440,370,15);
  moveServo(servoHeadVertical,370,480,15);
  moveServo(servoHeadVertical,480,440,15);
}

void commandBow() { 
  moveServo(servoHeadVertical,440,280,80);
  moveServo(servoHeadVertical,280,440,60);
}

void commandNo() { 
  moveServo(servoHeadHorizontal,300,450,10);
  moveServo(servoHeadHorizontal,450,150,10);
  moveServo(servoHeadHorizontal,150,300,10);
}

void commandNod() {
    pwm.setPWM(servoHeadVertical, 0, 410);
    delay(300);
    pwm.setPWM(servoHeadVertical, 0, 450);
}

void commandClap() {
  int servoStep = 3;
  int stepCount = 75;

  for (uint16_t stepstep = 0; stepstep < stepCount; stepstep++) {      
      pwm.setPWM(servoRightArm, 0, 210 + ( stepstep * servoStep) );
      pwm.setPWM(servoLeftArm, 0, 170 + (servoStep * stepCount) - (stepstep * servoStep));
      delay(2);
   }
  for (uint16_t stepstep = stepCount; stepstep > 0; stepstep--) {      
      pwm.setPWM(servoRightArm, 0, 210 + ( stepstep * servoStep) );
      pwm.setPWM(servoLeftArm, 0, 170 + (servoStep * stepCount) - (stepstep * servoStep));
      delay(2);
   }
  
}

void connect2wifi(int timeout) {
  WiFi.mode(WIFI_OFF);
  delay(100);
  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);
  Serial.println(ssid);
  Serial.println(password);
  
  int endTime = millis() + timeout;
  while (WiFi.status() != WL_CONNECTED && millis() < endTime ) {
    delay(500);
    Serial.print(".");
  }
  if(WiFi.status() != WL_CONNECTED) {
    Serial.println("Could not connect to " + String(ssid) );
    commandNo();
    return;
  } else {
    Serial.println("");
    Serial.println("WiFi connected");
    
    // Start the server
    server.begin();
    Serial.println("Server started");
  
    // Print the IP address
    Serial.println(WiFi.localIP()); 
    commandYes();
  }
}

int getHttp() {
  WiFiClient client = server.available();
  if (!client) {
    //Serial.println("Server?");
    delay(2);
    return 0;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    Serial.println("Waiting the client sends some data.");
    delay(1);
  }
  
  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nEnjoy:<br/>";
  s += "<a href=\"/c/1\">/c/1</a> clap<br/>\r\n";
  s += "<a href=\"/c/2\">/c/2</a> bow<br/>\r\n";
  s += "<a href=\"/c/4\">/c/4</a> no<br/>\r\n";
  s += "<a href=\"/c/8\">/c/8</a> yes<br/>\r\n";
  //s += (val)?"high":"low";
  s += "</html>\n";


  // Match the request
  int val;
  if (req.indexOf("/c/1") != -1)
    val = 1;
  else if (req.indexOf("/c/2") != -1)
    val = 2;
  else if (req.indexOf("/c/4") != -1)
    val = 4;
  else if (req.indexOf("/c/8") != -1)
    val = 8;
  else {
    Serial.println("invalid request");
    client.print(s);
    client.stop();
    return 0;
  }
  
  client.flush();

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");

  return val;
  // The client will actually be disconnected 
  // when the function returns and 'client' object is detroyed  
}

void servoOff() {
  pwm.setPWM(servoHeadVertical, 0, 0);
  pwm.setPWM(servoHeadHorizontal, 0, 0);
  pwm.setPWM(servoRightArm, 0, 0);
  pwm.setPWM(servoLeftArm, 0, 0);
}

void setup() {
  Wire.begin(pwmSda, pwmScl); //sda scl
  pwm.begin();
  pwm.setPWMFreq(60);
  Serial.begin(9600);
  
  //commandClap();
  commandNod();
  connect2wifi(5000);
  servoOff();  
}

void loop() {
  int code = 0;
  
  code = getHttp();
  
  if(code > 0) {
    switch (code) {
      case 8:
        Serial.println("Yes");
        commandYes();
        break;
      case 4:
        Serial.println("No");
        commandNo();
        break;
      case 2:
        Serial.println("Bow");
        commandBow();
        break;
      case 1:
        Serial.println("Clap");
        commandClap();
        commandClap();
        break;
      case 6:
        Serial.println("Connect to " + String(ssid) + "...");
        commandNod();
        connect2wifi(20000);
        break;
      default: 
        Serial.print("\nThere is no command to inputCode " + String(inputCode) + ".");
      break;
    }
    servoOff();
  }
}

Discussions

de∫hipu wrote 12/20/2016 at 15:44 point

You know that you can also use Python on the ESP8266?

  Are you sure? yes | no