Microcontroller projects

last updated: 09/06/19

!! NEW software using slider and websockets !!

Creative-lab space mining rover: Snyder 1

Einleitung / Introduction

Der Rover lässt sich über das Wifi Netz mit einem PC oder Handy steuern. Er wurde von Jean Daubenfeld und mir für das creative-lab entwickelt und schon 35x auf dem Luxemburgischen Makerfest aufgebaut. Das nächste Makerfest findet im Dezember 2018 in Luxemburg statt.

The rover is WLAN controlled by a computer or phone. The rover was developed by Jean Daubenfeld and myself for the creative-lab and was build 35 times on the 2 Luxemburgish Makerfest. The next Makerfest is in december 2018.

rover handy

Die Anleitung wurde hauptsächlich von Jean-Claude Feltes erstellt und ist als pdf verfügbar. Jean claude hat auch zwei interessante Dokumente zu Software (Englisch) geschrieben, die hier erhältlich sind:

The assembly instructions were written mostly by Jean-Claude Feltes and are available as pdf. Jean claude has also written 2 interesting documents covering the software:

Montageanleitung / Assembly instructions

Materiallliste / Bill of materials (BOM)

Mechanische Teile montieren / Mechanics

Achtung: Bei den meisten Teilen ist es wichtig, in welche Richtung man sie dreht! Um frustrierendes Wieder-Auseinandernehmen zu vermeiden, sollte man jeden Schritt genau überlegen.

Most parts have to be mounted in the right direction. It is frustrating to unmount parts that are not mounted the right way, so stay concentrated and look twice at the pictures.

Dein Bausatz sollte diese Teile enthalten (parts from your kit:):

bom

motor mount

wheel mount frontwheel

battery holder battery holder bottom

Platine bestücken und löten / PCB assembling and soldering

Löten / Soldering

Zum Löten gibt es viele gute Seiten und Videos im Netz. Hier eine gute Einführung:
There are many sites and videos on the net, so I will not reinvent the wheel. Here is a good link, explaining soldering: https://www.sciencebuddies.org/science-fair-projects/references/how-to-solder

pcb pcb populated

wemos_header wemos 1

Connecting the motors

motorsoldering motorwiring

Batterie und Schalter anschließen / Connecting the battery holder and the switch

Fertigstellung / Finish

Erster Test / First Test

rover url

New software with slider and websockets

Die neue Software nutzt Websockets und reagiert wesentlich schneller. Zwei Schieberegler für Geschwindigkeit und Winkel (Steuerrad) ermöglichen eine intuitive und einfache Steuerung. Besonders gut funktioniert das mit dem Chrome Browser (Android) oder Safari Browser (iOS)!
Das Programm besteht aus 2 Dateien und kann natürlich nach Belieben angepasst werden. Der html (+css und javascript) code befindet sich in einer separaten Datei, die im sich gleichen Verzeichnis wie die ino Datei befinden muss.

Here the new Arduino sketch. The new software uses Websockets an is reacting substantially faster. Two slider for speed and steering angle allow an intuitive and easy handling. Best browsers are Chrome for Android and Safari for iOS.
The html page (+ css and javascript) is contained in a separate file (in the same folder than the ino file!). Change the files at will.

Thanks to miharix.eu.

rover url

    /*
     *  Space Mining Rover aka snider1
     *  (wemos webserver with AP and L293D)
     *  new websockets version 6/19 weigu.lu
     *  creative-lab.lu
     *
     */

    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>
    #include <WebSocketsServer.h>
    #include "html_css_js.h"

    const char *ssid = "creativews";     // AP settings
    const char *password = "creativews"; // password must have more than 7 char.!!
    IPAddress IP_AP(192, 168, 168, 168);
    IPAddress MASK_AP(255, 255, 255, 0);

    ESP8266WebServer http_server(80);    // create a web server on port 80
    WebSocketsServer ws_server(81);      // create a ws server on port 81

    const byte speed_idle = 30;          // *2/1023 e.g. 30 gives 60 of 1023 = 6%
    const byte angle_idle = 30;

    const byte MotorR1_pin = 16;         // D0 config Wemos pins to motor driver
    const byte MotorR2_pin = 0;          // D3
    const byte MotorL1_pin = 15;         // D8
    const byte MotorL2_pin = 13;         // D7

    short speed, angle;

    /******** SETUP *********************************************************BEGIN*/

    void setup() {
      init_LED();
      LED_on;
      init_motors();                     // init moror pins and
      action(0,0,0,0);                   // stop the motors
      init_wifi_ap();                    // init wifi access point
      init_ws_server();                  // init websocket_server server
      init_http_server();                // init a http server
    }
    /***** SETUP **************************************************************END*/
    /***** MAINLOOP *********************************************************BEGIN*/

    void loop() {
      ws_server.loop();                  // check for websocket_server events
      http_server.handleClient();        // wait for http requests
    }
    /***** MAINLOOP ***********************************************************END*/
    /***** Init functions ***************************************************BEGIN*/

    // build in LED on
    void LED_on() {
      digitalWrite(LED_BUILTIN,LOW);     // LED on (negative logic)
    }

    // build in LED off
    void LED_off() {
      digitalWrite(LED_BUILTIN,HIGH);    // LED off (negative logic)
    }

    // initialise the build in LED and switch it on
    void init_LED() {
      pinMode(LED_BUILTIN,OUTPUT);
      LED_on();
    }

    // initialise the motor pins as output
    void init_motors() {
      pinMode(MotorR1_pin, OUTPUT);      // 4 pins to motor driver as output
      pinMode(MotorR2_pin, OUTPUT);
      pinMode(MotorL1_pin, OUTPUT);
      pinMode(MotorL2_pin, OUTPUT);
    }

    // initialize wifi ap
    void init_wifi_ap() {
      WiFi.softAP(ssid, password);       // start the access point
      WiFi.softAPConfig(IP_AP, IP_AP, MASK_AP); // second is gateway same as ip
      IPAddress myIP = WiFi.softAPIP();
      Serial.print("Access Point ");
      Serial.println(ssid);
      Serial.print("AP IP address: ");
      Serial.println(myIP);
    }

    // init websocket_server server
    void init_ws_server() {
      ws_server.begin();                 // start the ws server
      ws_server.onEvent(ws_server_event);// if ws message, websocket_server_event()
    }

    // init a http server and handle http requests: http://192.168.168.168/
    void init_http_server() {
      http_server.onNotFound(handle_not_found);
      http_server.on("/", handle_root);  // (don't forget the "/")
      http_server.begin();               // start the HTTP server
      http_server.setContentLength(html_css_js.length()); // needed to avoid net:err
    }
    /***** Init functions *****************************************************END*/
    /***** SERVER handlers **************************************************BEGIN*/

    // if the requested page doesn't exist, return a 404 not found error
    void handle_not_found() {
      http_server.send(404, "text/plain", "404: Not Found");
    }

    // handle root (deliver webpage)
    void handle_root() {
      LED_on();
      http_server.send(200,"text/html",html_css_js); // HTTP response code 200
      LED_off();
    }

    // do this when a websocket_server message is received
    void ws_server_event(byte num, WStype_t type, byte * payload, size_t lenght) {
      switch (type) {
        case WStype_DISCONNECTED:        // if the websocket_server is disconnected
          break;
        case WStype_CONNECTED: {         // if new websocket_server con. established
            IPAddress ip = ws_server.remoteIP(num);
          }
          break;
        case WStype_TEXT:                // if new text data is received
          if (payload[0] == '#') {       // we get slider data
            unsigned long pl = (unsigned long) strtol((const char *) &payload[1],
                               NULL, 16);// string data to number
            int speed = pl & 0x3FF;      // retrieve both slider data (0-1023)
            int angle= (pl >> 12) & 0x3FF; // G: bits 12-24
            if ((angle <= (512 + angle_idle)) &&
                (angle >= (512 - angle_idle))) {     // straight
              if (speed > (512 + speed_idle)) {
                action(speed,0,speed,0);             // straight forward
              }
              else if (speed < (512 - speed_idle)) {
                action(speed,1023,speed,1023);       // straight backwards
              }
              else {
                action(0,0,0,0);                     // stop
              }
            }
            else if (angle < (512 - angle_idle)) {   // turn right
              angle = -((512 + angle_idle)-angle);
              if (speed > (512 + speed_idle)) {      // right forward
                action(speed,0,speed+angle,0);
              }
              else if (speed < (512 - speed_idle)) {
                action(speed,1023,speed-angle,1023); // right backwards
              }
              else {
                action(0,0,0,0);
              }
            }
            else {                                   // turn left
              angle = (512 - angle_idle)-angle;
              if (speed > (512 + speed_idle)) {      // left forward
                action(speed+angle,0,speed,0);
              }
              else if (speed < (512 - speed_idle)) { // left backwards
                action(speed-angle,1023,speed,1023);
              }
              else {
                action(0,0,0,0);
              }
            }
          }
          break;
      }
    }
    /***** SERVER handlers ****************************************************END*/

    /***** HELPER functions**************************************************BEGIN*/

    void action(int MotorR1, int MotorR2, int MotorL1, int MotorL2) {
      LED_on();
      analogWrite(MotorR1_pin, MotorR1);
      analogWrite(MotorR2_pin, MotorR2);
      analogWrite(MotorL1_pin, MotorL1);
      analogWrite(MotorL2_pin, MotorL2);
      LED_off();
    }
    /***** Helper functions ***************************************************END*/

Circuit

circuit


Older Software without websockets

rover url

Hier das Arduino Programm , das natürlich nach Belieben angepasst werden soll.

Here the basic Arduino sketch. Change it at will.

    /*
     *  Space Mining Rover aka snider1
     *  (wemos webserver with AP and L293D)
     *  creative-lab.lu
     */


    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>

    const char *ssid = "creative23";     // AP settings
    const char *password = "creative23"; // password must have more than 7 characters!!
    IPAddress IP_AP(192, 168, 168, 168);
    IPAddress MASK_AP(255, 255, 255, 0);

    ESP8266WebServer server(80);         // create object with name "server" port 80

    const int slow = 500;                // speed (500 to get min 2,5V)
    const int medium = 750;
    const int fast = 1023;               // max. 1023)
    const int bowdiff = 150;             // if bigger, lesser radius

    const byte LED = 2;          // D4
    const byte MotorR1_pin = 16; // D0 config Wemos pins to motor driver
    const byte MotorR2_pin = 0;  // D3
    const byte MotorL1_pin = 15; // D8
    const byte MotorL2_pin = 13; // D7

    // here comes the html and css magic
    String myhtml = R"=====(
    <!DOCTYPE html>
    <html>
      <head>
        <title>creative-lab.lu</title>
      </head>
      <style>
        body      {font-family: Arial, Verdana, sans-serif;
                   font-size: 12px;
                   color: red;
                   background-color: green;}
        div       {margin: 0.2em auto;
                   width: 100%;
                   clear: both;}
        p         {margin: 0.2em;
                   padding: 0.1em;
                   border-radius: 1em;
                   background-color: yellow;
                   border: 0.3em red solid;
                   font-size: 4em;
                   font-weight: bolder;
                   text-align: center;}
        p.center  {margin: 0.2em  auto;
                   width: 27%;
                   clear: both;}
        p.lam     {clear: both;}
        p.main    {background-color: orange;
                   width: 27%;
                   float: left;}
        p.side    {width: 27%;
                   float: left;}
        p.stop    {background-color: red;
                   width: 27%;
                   float: left;
                   margin-bottom: 0.4em;}
        a         {display: block;
                   text-decoration: none;}
      </style>
      <body>
        <br><p class="lam">creative-lab.lu
               <br/>Lyc&eacute;e des Arts et M&eacute;tiers</p><br>
        <div>
        <p class="side"><a href=/forwards>Forward<br/>Slow</a></p>
        <p class="main"><a href=/forwardm>Forward<br/>Medium</a></p>
        <p class="side"><a href=/forwardf>Forward<br/>Fast</a></p>
        </div><div>
        <p class="main"><a href=/lefts>Left<br/>Spot</a></p>
        <p class="stop"><a href=/halt>Stop<br/>Now</a></p>
        <p class="main"><a href=/rights>Right<br/>Spot</a></p>
        </div><div>
        <p class="side"><a href=/leftb>Left<br/>Bow</a></p>
        <p class="stop"><a href=/halt>Stop<br/>Now</a></p>
        <p class="side"><a href=/rightb>Right<br/>Bow</a></p>
        </div><div>
        <p class="side"><a href=/backwards>Backward<br/>Slow</a></p>
        <p class="main"><a href=/backwardm>Backward<br/>Medium</a></p>
        <p class="side"><a href=/backwardf>Backward<br/>Fast</a></p>
        </div>
      </body>
    </html>
    )=====";

    void setup() {
      pinMode(MotorR1_pin, OUTPUT); // 4 pins to motor driver as output
      pinMode(MotorR2_pin, OUTPUT);
      pinMode(MotorL1_pin, OUTPUT);
      pinMode(MotorL2_pin, OUTPUT);
      pinMode(D4, OUTPUT);   // blue LED Pin (D4) as output

      digitalWrite(D4, LOW);                  // LED on (negative logic)

      action(0,0,0,0);                         // stop the motors
      /*digitalWrite(Motor_R_PWM_1, LOW);
      digitalWrite(Motor_R_PWM_2, LOW);
      digitalWrite(Motor_L_PWM_1, LOW);
      digitalWrite(Motor_L_PWM_2, LOW);*/

      WiFi.softAP(ssid, password);
      WiFi.softAPConfig(IP_AP, IP_AP, MASK_AP);
      IPAddress myIP = WiFi.softAPIP();

      // handle http requests; root must be called! type: http://192.168.168.168/
      server.on("/", handleRoot);              // (don't forget the "/")
      server.on("/forwards", forwards);
      server.on("/forwardm", forwardm);
      server.on("/forwardf", forwardf);
      server.on("/lefts", lefts);
      server.on("/rights", rights);
      server.on("/halt", halt);
      server.on("/leftb", leftb);
      server.on("/rightb", rightb);
      server.on("/backwards", backwards);
      server.on("/backwardm", backwardm);
      server.on("/backwardf", backwardf);

      server.begin();
      server.setContentLength(myhtml.length()); // if not given we get
    }                                         // net:err_content_length_mismatch

    void loop() {
      server.handleClient();          // wait for http requests
    }

    void handleRoot() {
      digitalWrite(LED, LOW);
      server.send(200,"text/html",myhtml); // HTTP response code 200 (alt. 404)
      digitalWrite(LED, HIGH);
    }

    void forwards()  { action(slow,0,slow,0); }
    void forwardm()  { action(medium,0,medium,0); }
    void forwardf()  { action(fast,0,fast,0); }
    void lefts()     { action(slow,0,1023-slow,1023); }
    void rights()    { action(1023-slow,1023,slow,0); }
    void halt()      { action(0,0,0,0); }
    void rightb()    { action(slow,0,slow+bowdiff,0); }
    void leftb()     { action(slow + bowdiff,0,slow,0); }
    void backwards() { action(1023-slow,1023,1023-slow,1023); }
    void backwardm() { action(1023-medium,1023,1023-medium,1023); }
    void backwardf() { action(1023-fast,1023,1023-fast,1023); }

    void action(int MotorR1, int MotorR2, int MotorL1, int MotorL2) {
      digitalWrite(LED, LOW);
      analogWrite(MotorR1_pin, MotorR1);
      analogWrite(MotorR2_pin, MotorR2);
      analogWrite(MotorL1_pin, MotorL1);
      analogWrite(MotorL2_pin, MotorL2);
      server.send(200, "text/html",myhtml);
      digitalWrite(LED, HIGH);
    }

Downloads

Interesting links: