Site icon AranaCorp

Utilisation du AC MotorShield ESP32

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

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:

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-.

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

Sources

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

Quitter la version mobile