Codementor Events

RC airboat with NodeMCU & Arduino

Published Jun 02, 2019Last updated Jun 13, 2019
RC airboat with NodeMCU & Arduino

Hello, my name is Alex. And from time to time I like to small challeges for myself. I've pretty busy schedule so I don't have much time for creative stuff.
So if I want to make something working, I need to make it super fast.

It took me 14 hours to build it, including going to the shopping center to get some styrofoam and wood. I was exicited by this idea - to build some real thing super quickly and have fun with it.

Hardware parts

  • NodeMCU 32-s
  • Arduino Uno
  • Stepper motor 28byj-48
  • Brushless motor
  • LED tape
  • 3.7V x 3 accumulators

That's it. That's all I needed for crafting this thing.

General schema

mycode_bb.jpg

NodeMCU created wi-fi network. So I could reach it's ip and see some super basic web-page with 3 buttons. After clicking each of them it sent GET request to nodeMCU.
2019-06-02 13.51.12.jpg

Here is the code


// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid     = "ESP32-Access-Point";
const char* password = "123456789";

// Set web server port number to 80
WiFiServer server(80);


// Variable to store the HTTP request
String header;
//#include <Servo.h>

//Servo ESC;     // create servo object to control the ESC

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;



void setup() {
  Serial.begin(115200);
  
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  //Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  //Serial.print("AP IP address: ");
  //Serial.println(IP);
    //  ESC.attach(9,1000,2000); // (pin, min pulse width, max pulse width in microseconds) 

  server.begin();
}

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

  if (client) {                             // If a new client connects,
    //Serial.println("New Client.");          // print a message out in 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
        header += c;
        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("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              //Serial.println("GPIO 26 on");
               // ESC.write(50);    // Send the signal to the ESC
              Serial.print("g");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.print("s");
              //Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/left") >= 0) {
               Serial.print("l");
              //Serial.println("GPIO 27 on");
              //output27State = "on";
              //digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/right") >= 0) {
              Serial.print("r");
              //Serial.println("GPIO 27 off");
              //output27State = "off";
              //digitalWrite(output27, LOW);
            } else if (header.indexOf("GET /27/center") >= 0) {
              Serial.print("c");
              //Serial.println("GPIO 27 off");
              //output27State = "off";
              //digitalWrite(output27, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
            // If the output26State is off, it displays the ON button       
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            
            
            
            client.println("<p><a href=\"/27/left\"><button class=\"button button2\">left</button></a></p>");
            client.println("<p><a href=\"/27/center\"><button class=\"button button2\">center</button></a></p>");
            client.println("<p><a href=\"/27/right\"><button class=\"button button2\">right</button></a></p>");
            
            client.println("</body></html>");
            
            // 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
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    //Serial.println("Client disconnected.");
    //Serial.println("");
  }
}

Arduino had control over all motors. It was communicating with NodeMCU via SoftwareSerial. Here is the code

char signal;

#include <SoftwareSerial.h>
#include <Stepper.h>
#include <Servo.h>
Servo ESC;     // create servo object to control the ESC
const byte rxPin = 2;
const byte txPin = 3;

// set up a new serial object
SoftwareSerial mySerial (rxPin, txPin);

const int stepsPerRevolution = 64; // шагов за один оборот

const int IN1 = 4;
const int IN2 = 5;
const int IN3 = 6;
const int IN4 = 7;

void setup() {

   mySerial.begin(115200);
   Serial.begin(9600);
   ESC.attach(9);
   ESC.writeMicroseconds(1000); 
   myStepper.setSpeed(300); 

}

void loop() {
  // put your main code here, to run repeatedly:
if (mySerial.available()) {
      signal = mySerial.read();
      Serial.println(signal);
      if (signal == 'g'){
        Serial.println("yes x");
        ESC.writeMicroseconds(1250); //using val as the signal to esc
      } 
      if (signal == 's'){
        ESC.writeMicroseconds(1000); //using val as the signal to esc
      } 
      if (signal == 'l'){
         myStepper.step(-300);
      } 
      if (signal == 'r'){
         myStepper.step(300);
      } 
}
  
}

Development process

Before starting this model I made some quick measurements. How difficult to build the model. Which parts I know how to do and which are not. And I made it before sleep. It's a good practice to overview a project in your mind to see all narrrow parts.

After this I started to test all hard parts. I mean which connection module to use, and which will be simple enough to work with. It's important to get rid of perfecsionist syndrome to made things done. You see my boat doesn't look pretty inspiring, my I made it fast.

2019-06-02 13.38.25.jpg

Here is the video

https://www.youtube.com/watch?v=qgnqU0r6f7o&feature=youtu.be

Discover and read more posts from Alex Polymath
get started
post commentsBe the first to share your opinion
Show more replies