Motorisation banc de mesure

Il s'agit de motoriser un instrument de mesure fixé à un portique mobile au dessus d'une carotte géologique. C'est donc un mouvement 1,5 degrés de liberté : X (deux moteurs pas-à-pas à contrôler) + Y sur deux positions (haut-bas), plus un déclenchement de la mesure.

Mise en œuvre M5Stack + Driver Module

J'utilise un M5Stack BASIC v2.6. Il faut dans l'IDE Arduino de choisir un M5Stack-Station dans le type de microcontroleur, et limiter les vitesses d'upload.

D'autre part, j'utilise le Stepmotor Driver Module 13.2. Il dispose de 3 drivers X,Y,Z et de 4 switchs de fin de course.

C'est donc en principe suffisant pour ce que je cherche à faire.

Les moteurs sont des MOTECH MT-170HS168A, à 1,8°/pas. Les moteurs disposent de connecteurs 6 pins JST-PH (espacement 2.0mm), mais sont quadrupolaires... Après avoir acheté un coffret de connecteurs à sertir, on commence donc par identifier les bobines à l'aide d'un multimètre.

Le meilleur tutoriel pour avoir le bon geste de sertissage et éviter d'y passer des heures de frustration :

https://www.youtube.com/watch?v=dY3hbyF3ypA

Voici le câblage obtenu :

stepper.pngdriver.png

 

Un M5Stack et module driver brûlés par faute d'un déplacement intempestif, on arrive à faire fonctionner l'exemple produit ici 

/*
*******************************************************************************
* Copyright (c) 2021 by M5Stack
*                  Equipped with M5Core sample source code
*                          配套  M5Core 示例源代码
* Visit for more
information:https://docs.m5stack.com/en/module/stepmotor_driver
* 获取更多资料请访问:https://docs.m5stack.com/zh_CN/module/stepmotor_driver
*
* Describe: Stepmotor With Pluse.
* Date: 2021/11/14
*******************************************************************************
  StepMotor Driver Module TEST Example,Directly drive the motor using pulse
signals. 步进电机模块测试示例,使用脉冲信号直接驱动电机
*/
#include "M5Stack.h"
#include "Module_Stepmotor.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// #define VERSION_1_0

String inputString  = "";
bool stringComplete = false;

static Module_Stepmotor driver;

void setup() {
    M5.begin(true, false, true, false);
    M5.Lcd.clear(TFT_BLACK);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(TFT_GREEN);
    M5.Lcd.setTextDatum(MC_DATUM);
    M5.Lcd.drawString("DIRECT_STEPMOTOR", 160, 10, 2);
    M5.Lcd.setTextColor(TFT_YELLOW);
    M5.Lcd.drawString("LIMIT IO STATUS", 160, 90, 2);
    M5.Lcd.drawString("DIR", 70, 220, 2);
#ifndef VERSION_1_0
    M5.Lcd.drawString("FAULT IO STATUS", 160, 160, 2);
    M5.Lcd.drawString("RST ALL", 160, 220, 2);
    M5.Lcd.drawString("1/1", 260, 220, 2);
#else
    M5.Lcd.drawString("STEP", 260, 220, 2);
#endif

    Wire.begin(21, 22, 400000UL);
    driver.init(Wire);

#ifndef VERSION_1_0
    driver.resetMotor(0, 0);
    driver.resetMotor(1, 0);
    driver.resetMotor(2, 0);
#else
    driver.setMicrostepResolution(DIRECT_STEPMOTOR::kMicrosteps16);
#endif

    driver.enableMotor(1);
    Serial1.begin(115200, SERIAL_8N1, 35, 5);
    Serial2.begin(115200, SERIAL_8N1, 34, 26);
    Serial2.setTimeout(100);

    ledcSetup(0, 10000, 8);
    ledcAttachPin(16, 0);
    ledcAttachPin(12, 0);
    ledcAttachPin(15, 0);
    ledcWrite(0, 127);

    pinMode(17, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(0, OUTPUT);

    digitalWrite(17, 1);
    digitalWrite(13, 1);
    digitalWrite(0, 1);
}

void loop() {
    static uint8_t step_dir                                  = 1;
    static uint8_t reset_mtr                                 = 0;
    static Module_Stepmotor::MicrostepResolution_t micro_res = Module_Stepmotor::kMicrosteps16;
    Serial1.print("Y");
    delay(25);
    M5.update();
    if (Serial2.available()) {
        char inChar = (char)Serial2.read();
        if (inChar == 'Y') {
            M5.Lcd.fillRect(105, 180, 120, 20, TFT_GREEN);
        }
    } else {
        M5.Lcd.fillRect(105, 180, 120, 20, TFT_RED);
    }
    if (M5.BtnA.wasPressed()) {
        step_dir = 1 - step_dir;
        digitalWrite(17, step_dir);
        digitalWrite(13, step_dir);
        digitalWrite(0, step_dir);
    }

    if (M5.BtnB.wasPressed()) {
#ifndef VERSION_1_0
        driver.resetMotor(0, 0);
        driver.resetMotor(1, 0);
        driver.resetMotor(2, 0);
        reset_mtr = 0;
#endif
    }

    if (M5.BtnC.wasPressed()) {
#ifndef VERSION_1_0
        if (reset_mtr == 0) {
            driver.resetMotor(0, 1);
            driver.resetMotor(1, 1);
            driver.resetMotor(2, 1);
        }
        driver.resetMotor(int(reset_mtr / 2), (reset_mtr & 0x01));
        reset_mtr += 1;
        if (reset_mtr == 6) reset_mtr = 0;
#else
        if (micro_res == DIRECT_STEPMOTOR::kMicrosteps16) {
            micro_res = DIRECT_STEPMOTOR::kMicrosteps8;
        } else {
            micro_res = DIRECT_STEPMOTOR::kMicrosteps16;
        }
        driver.setMicrostepResolution(micro_res);
#endif
    }

    driver.getExtIOStatus();
    if (driver.ext_io_status[3]) {
        M5.Lcd.fillRect(70, 45, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(70, 45, 20, 20, TFT_GREEN);
    }

    if (driver.ext_io_status[2]) {
        M5.Lcd.fillRect(120, 45, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(120, 45, 20, 20, TFT_GREEN);
    }

    if (driver.ext_io_status[1]) {
        M5.Lcd.fillRect(170, 45, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(170, 45, 20, 20, TFT_GREEN);
    }

    if (driver.ext_io_status[0]) {
        M5.Lcd.fillRect(220, 45, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(220, 45, 20, 20, TFT_GREEN);
    }
#ifndef VERSION_1_0
    driver.getFaultStatus();
    if (driver.fault_io_status[2]) {
        M5.Lcd.fillRect(95, 115, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(95, 115, 20, 20, TFT_GREEN);
    }

    if (driver.fault_io_status[1]) {
        M5.Lcd.fillRect(145, 115, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(145, 115, 20, 20, TFT_GREEN);
    }

    if (driver.fault_io_status[0]) {
        M5.Lcd.fillRect(195, 115, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(195, 115, 20, 20, TFT_GREEN);
    }
#endif
}

 

 

Test des fins de course

Tout est dans le titre.

Les fins de courses comprennent trois pôles: 

Le connecteur étant branché C -> GND et NC->L0, on observe bien l'effet de cette partie du code :

     driver.getExtIOStatus();
    if (driver.ext_io_status[3]) {
        M5.Lcd.fillRect(70, 45, 20, 20, TFT_RED);
    } else {
        M5.Lcd.fillRect(70, 45, 20, 20, TFT_GREEN);
    }

Le rectangle concerné devient rouge quand le bouton est enfoncé.

Tentative de première programmation

Il m'apparaît que le module StepMotor Driver 13.2 dont je dispose est la version 1.0. 

Le microcontrolleur pilotant les drivers est en effet un TCA9554 (et non un STM32 comme dans les versions ultérieures).

Il faut donc décommenter la directive 

#define VERSION_1_0

Et là, patatras, plus rien ne compile. 

Il semblerait que j'ai mis le bazar dans mon installation en mettant à jour les bibliothèques : le problème est probablement lié à la bibliothèque FastLED dont dépend la bibliothèque M5Display dont dépend la bibliothèque M5stack...

La "nouvelle" version de l'API ignore par exemple ledcAttachPin (deprecated) et utilise ledcAttach, avec des arguments différents. Sans parler de ledcSetup qui a changé. Bref, c'est la m... s'il faut ré-écrire l'exemple.