fbpixel
Étiquettes : ,
5
(1)

Le AC MotorShield ESP32 est une carte d’extension qui permet un NodeMCU ESP32 de piloter deux moteurs CC ou un moteur pas-à-pas. Nous avons vu comment piloter un moteur CC en utilisant un pont en H ce qui peut nécessiter beaucoup de branchement lorsqu’on utilise le circuit intégré simplement. Pour une application embarquée, comme un robot Willy, vous serez amené à piloter plusieurs moteurs en parallèle. Ils existent pour cela des Shields qui simplifieront le montage.

Matériel

  • Ordinateur
  • NodeMCU ESP32
  • Câble USB A Mâle/B Mâle
  • AC Motor Shield ESP32
  • Moteur CC x2 ou Moteur pas-à-pas x1
  • Alimentation externe 9V

Principe de fonctionnement

Le AC MotorShield ESP32 utilise le double pont en H SN751044NE. Il permet de piloter des moteurs en direction et en vitesse avec une tension nominale entre 4.5 et 36V et un courant de 1A avec une source de tension extérieure.
Ce shield permet d’utiliser:

  • jusqu’à deux moteurs à courant continu ou un moteur pas à pas bipolaire
  • Les GPIO disponibles
  • les bus I2C et UART

Schéma

Compatible avec la carte NodeMCU ESP32, le shield se place directement sur le microcontrôleur. L’alimentation des moteurs se branche au bornier VM/GND et celle de la carte au bornier VIN/GND. Les moteurs se branchent sur les borniers A+,A-,B+,B-.

  • 0, 4 (motor A/ Stepper 1,2)
  • 15, 2 (motor B / Stepper 3,4)
  • GPIO disponibles sur les autres broches

Dans le cas d’un shield, les branchements sont prédéfinis. Vérifiez bien dans la documentation technique du composant comment l’utiliser.
Les branchements des moteurs sont détaillés dans les schémas suivants.

Dans les deux exemples suivants, nous ajoutons une interface Web qui permet de tester les moteurs dans les deux sens de rotation.

Code de gestion d’un moteur CC

Pour interagir avec le MotorShield ESP32 et piloter des moteur CC, nous n’utilisons pas de librairie particulière. Il vous est toujours possible de créer votre librairie pour simplifier votre code.

#include <WiFi.h>
#include <WebServer.h>
#include <Arduino.h>
#include <analogWrite.h>

#define IN1 34    //sensor
#define OUT1  0   //A+ - Black
#define OUT2  4   //A- - Green
#define OUT3  15  //B+ - Red
#define OUT4  2   //B- - Blue

//Motor param
int Steps = 0;
int Direction = 0;
int speedMotor = 150;

//Wifi
const char *ssid = "****";
const char *password = "*****";

WebServer server(80);

const int led = 2;
int stateMotorA = 0,stateMotorB = 0;
char stateMotorTextA[3][10] = {"STOP","CCW!","CW!"};
char stateMotorTextB[3][10] = {"STOP","CCW!","CW!"};
String sensorValue;

/*********************************************************************************************
 * HANDLE FUNCTIONS
*********************************************************************************************/
void handleRoot()
{
    String page = "<!DOCTYPE html>";

    page += "<html lang='fr'>";

    page += "<head>";
    page += "    <title>ESP32MotorShieldV1</title>";
    page += "    <meta http-equiv='refresh' content='60' name='viewport' content='width=device-width, initial-scale=1' charset='UTF-8' />";
    page += "    <link rel='stylesheet' href='https://www.w3schools.com/w3css/4/w3.css'>";

   page += "<script>";

   page += "function getData() {";
   page += "  var xhttp = new XMLHttpRequest();";
   page += "  xhttp.onreadystatechange = function() {";
   page += "    if (this.readyState == 4 && this.status == 200) {";
   page += "      document.getElementById('SensorValue').innerHTML =this.responseText;";
   page += "      console.log(this.responseText);";
   page += "    }";
   page += "  };";
   page += "  xhttp.open('GET', 'readSensor', true);";
   page += "  xhttp.send();";
   page += "}";

   page += "setInterval(function() {getData();}, 2000);   // Call a function repetatively with 2s interval";

   page += "</script>";
 
    page += "</head>";

    page += "<body>";
    page += "    <div class='w3-card w3-padding-small w3-jumbo w3-center' style='color:#fff; background-color:#3aaa35;'>";
    page += "        <p>Motor State A: "; page += stateMotorTextA[stateMotorA]; + "</p>";
    page += "    </div>";

    page += "    <div class='w3-bar'>";
    page += "        <a href='/lefta' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>GAUCHE</a>";
    page += "       <a href='/stopa' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>STOP</a>";
    page += "        <a href='/righta' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>DROITE</a>";
    page += "    </div>";

    page += "    <div class='w3-card w3-padding-small w3-jumbo w3-center' style='color:#fff; background-color:#3aaa35;'>";
    page += "        <p>Motor State B: "; page += stateMotorTextB[stateMotorB]; + "</p>";
    page += "    </div>";

    page += "    <div class='w3-bar'>";
    page += "        <a href='/leftb' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>GAUCHE</a>";
    page += "       <a href='/stopb' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>STOP</a>";
    page += "        <a href='/rightb' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>DROITE</a>";
    page += "    </div>";
    
    page += "    <div class='w3-card w3-padding-small w3-jumbo w3-center' style='color:#fff; background-color:#3aaa35;'>";
    page += "        <p>Sensor value: <span id='SensorValue'>0</span></p>";
    page += "    </div>";

    page += "    <div class='w3-center w3-padding-16'>";
    page += "        <p>Server hosted on NodeMCU ESP32 - <i>Made by <a href='https://www.aranacorp.com' style='color:#3aaa35;'>AranaCorp</a></i></p>";
    page += "        ";

    page += "    </div>";

    page += "</body>";

    page += "</html>";

    server.setContentLength(page.length());
    server.send(200, "text/html", page);
}

void handleLeftA(){
    stateMotorA = 2;
    digitalWrite(led, HIGH);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleRightA(){
    stateMotorA = 1;
    digitalWrite(led, LOW);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleStopA(){
    stateMotorA = 0;
    digitalWrite(led, HIGH);
    server.sendHeader("Location","/");
    server.send(303);
}


void handleLeftB(){
    stateMotorB = 2;
    digitalWrite(led, HIGH);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleRightB(){
    stateMotorB = 1;
    digitalWrite(led, LOW);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleStopB(){
    stateMotorB = 0;
    digitalWrite(led, HIGH);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleInput() {
 sensorValue = String(analogRead(IN1));
 server.send(200, "text/plain", sensorValue); //Send ADC value only to client ajax request
}

void handleNotFound(){
    digitalWrite(led, HIGH);
    stateMotorA = 0;
    stateMotorB = 0;
    server.send(404, "text/plain", "404: Not found");
}


/*********************************************************************************************
 * MAIN
*********************************************************************************************/
void setup()
{
    pinMode(IN1, INPUT); 
    pinMode(OUT1, OUTPUT); 
    pinMode(OUT2, OUTPUT);

    pinMode(OUT3, OUTPUT);
    pinMode(OUT4, OUTPUT);
    
    Serial.begin(115200);
    delay(1000);
    Serial.println("\n");

    pinMode(led, OUTPUT);
    digitalWrite(led, HIGH);

    WiFi.persistent(false);
    WiFi.begin(ssid, password);
    Serial.print("Tentative de connexion...");

    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(100);
    }

    Serial.println("\n");
    Serial.println("Connexion etablie!");
    Serial.print("Adresse IP: ");
    Serial.println(WiFi.localIP());

    server.on("/", handleRoot);
    server.on("/lefta", handleLeftA);
    server.on("/righta", handleRightA);
    server.on("/stopa", handleStopA);
    server.on("/leftb", handleLeftB);
    server.on("/rightb", handleRightB);
    server.on("/stopb", handleStopB);   
    server.on("/readSensor", handleInput);//To get sensor value update

 
    server.onNotFound(handleNotFound);
    server.begin();

    Serial.println("Serveur web actif!");
}


void loop()
{
    server.handleClient();
    //Handle motor A
    switch(stateMotorA) {
      case 0:
        analogWrite(OUT1, 0);
        analogWrite(OUT2, 0);
        break;
      case 1:
        analogWrite(OUT1, speedMotor);
        analogWrite(OUT2, 0);
        break;
      case 2:
        analogWrite(OUT1, 0);
        analogWrite(OUT2, speedMotor);
        break;
    }
    //Handle motor B
    switch(stateMotorB) {
      case 0:
        analogWrite(OUT3, 0);
        analogWrite(OUT4, 0);
        break;
      case 1:
        analogWrite(OUT3, speedMotor);
        analogWrite(OUT4, 0);
        break;
      case 2:
        analogWrite(OUT3, 0);
        analogWrite(OUT4, speedMotor);
        break;
    }
}

Code de gestion d’un moteur pas-à-pas

Pour piloter un moteur pas-à-pas, il faut activer les bobines du moteur en suivant un enchainement précis. Cet enchainement est décrit dans la fonction step de la librairie stepper.h

/*
   Nema   | Board pin | NodeMCU GPIO |  Arduino IDE
   black        A+           0             0
   green        A-           4             4
   red          B+           15            15
   blue         B-           2             2
*/

#include <WiFi.h>
#include <WebServer.h>
#include <Arduino.h>
#include <analogWrite.h>

#include <Stepper.h>

#define IN1 34    //sensor
#define OUT1  0   //A+ - Black
#define OUT2  4   //A- - Green
#define OUT3  15  //B+ - Red
#define OUT4  2   //B- - Blue


//Stepper param
const int stepsPerRevolution = 200;
int speedMotor = 20;
Stepper myStepper(stepsPerRevolution, OUT1, OUT2, OUT3, OUT4);

//Wifi
const char *ssid = "*****";
const char *password = "********";

WebServer server(80);

const int led = 2;
int stateStepper = 0,stateStepperB = 0;
char stateStepperText[3][10] = {"STOP","CCW!","CW!"};
String sensorValue;
  
/*********************************************************************************************
 * HANDLE FUNCTIONS
*********************************************************************************************/
void handleRoot()
{
    String page = "<!DOCTYPE html>";

    page += "<html lang='fr'>";

    page += "<head>";
    page += "    <title>ESP32MotorShieldV1</title>";
    page += "    <meta http-equiv='refresh' content='60' name='viewport' content='width=device-width, initial-scale=1' charset='UTF-8' />";
    page += "    <link rel='stylesheet' href='https://www.w3schools.com/w3css/4/w3.css'>";

   page += "<script>";

   page += "function getData() {";
   page += "  var xhttp = new XMLHttpRequest();";
   page += "  xhttp.onreadystatechange = function() {";
   page += "    if (this.readyState == 4 && this.status == 200) {";
   page += "      document.getElementById('SensorValue').innerHTML =this.responseText;";
   page += "      console.log(this.responseText);";
   page += "    }";
   page += "  };";
   page += "  xhttp.open('GET', 'readSensor', true);";
   page += "  xhttp.send();";
   page += "}";

   page += "setInterval(function() {getData();}, 2000);   // Call a function repetatively with 2s interval";

   page += "</script>";
 
    page += "</head>";

    page += "<body>";
    page += "    <div class='w3-card w3-padding-small w3-jumbo w3-center' style='color:#fff; background-color:#3aaa35;'>";
    page += "        <p>Stepper State: "; page += stateStepperText[stateStepper]; + "</p>";
    page += "    </div>";

    page += "    <div class='w3-bar'>";
    page += "        <a href='/left' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>GAUCHE</a>";
    page += "       <a href='/stop' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>STOP</a>";
    page += "        <a href='/right' class='w3-bar-item w3-button w3-border w3-jumbo' style='width:33%; height:50%;'>DROITE</a>";
    page += "    </div>";
    
    page += "    <div class='w3-card w3-padding-small w3-jumbo w3-center' style='color:#fff; background-color:#3aaa35;'>";
    page += "        <p>Sensor value: <span id='SensorValue'>0</span></p>";
    page += "    </div>";

    page += "    <div class='w3-center w3-padding-16'>";
    page += "        <p>Server hosted on NodeMCU ESP32 - <i>Made by <a href='https://www.aranacorp.com' style='color:#3aaa35;'>AranaCorp</a></i></p>";
    page += "        ";

    page += "    </div>";

    page += "</body>";

    page += "</html>";

    server.setContentLength(page.length());
    server.send(200, "text/html", page);
}

void handleLeft(){
    stateStepper = 2;
    digitalWrite(led, HIGH);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleRight(){
    stateStepper = 1;
    digitalWrite(led, LOW);
    server.sendHeader("Location","/");
    server.send(303);
}

void handleStop(){
    stateStepper = 0;
    digitalWrite(led, HIGH);
    server.sendHeader("Location","/");
    server.send(303);
}


void handleInput() {
 sensorValue = String(analogRead(IN1));
 server.send(200, "text/plain", sensorValue); //Send ADC value only to client ajax request
}

void handleNotFound(){
    digitalWrite(led, HIGH);
    stateStepper = 0;
    server.send(404, "text/plain", "404: Not found");
}


/*********************************************************************************************
 * MAIN
*********************************************************************************************/
void setup()
{
    pinMode(IN1, INPUT); 
    
    Serial.begin(115200);
    delay(1000);
    Serial.println("\n");

    pinMode(led, OUTPUT);
    digitalWrite(led, HIGH);

    myStepper.setSpeed(speedMotor);

    WiFi.persistent(false);
    WiFi.begin(ssid, password);
    Serial.print("Tentative de connexion...");

    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(100);
    }

    Serial.println("\n");
    Serial.println("Connexion etablie!");
    Serial.print("Adresse IP: ");
    Serial.println(WiFi.localIP());

    server.on("/", handleRoot);
    server.on("/left", handleLeft);
    server.on("/right", handleRight);
    server.on("/stop", handleStop);  
    server.on("/readSensor", handleInput);//To get sensor value update

 
    server.onNotFound(handleNotFound);
    server.begin();

    Serial.println("Serveur web actif!");
}


void loop()
{
    server.handleClient();
    //Handle Stepper
    switch(stateStepper) {
      case 0:
        //stop
        break;
      case 1:
        myStepper.step(1);
        break;
      case 2:
        myStepper.step(-1);
        break;
    }
}

Applications

  • Piloter un robot à deux roues comme Willy via une connexion WiFi ou Bluetooth

Sources

Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

How useful was this post?

Click on a star to rate it!

Average rating 5 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?