L293D_Handler

drivers
drivers/L293D_Handler.h
driver stable stable

Driver: L293D Pilote bas niveau du circuit intégré L293D (double pont en H). Un seul L293D permet de commander jusqu'à 2 moteurs DC (ou 1 moteur pas à pas bipolaire) en contrôlant indépendamment le sens et la vitesse de chaque canal via une broche Enable PWM.

Méthodes publiques

Méthode Description Paramètres Retour
L293D_Handler()
L293D_Handler();
Constructeur / Destructeur Le destructeur coupe les deux canaux (roue libre) par sécurité. /
L293D_Handler()
L293D_Handler();
Constructeur / Destructeur Le destructeur coupe les deux canaux (roue libre) par sécurité. /
begin()
begin(uint8_t in1A, uint8_t in2A, uint8_t enA, uint8_t in1B, uint8_t in2B, uint8_t enB);
begin()
begin(PCA9685_Handler& pca, uint8_t chIn1A, uint8_t chIn2A, uint8_t enA, uint8_t chIn1B, uint8_t chIn2B, uint8_t enB);
setSpeed()
setSpeed(L293D_Channel channel, int8_t speed);
Commande de vitesse Définit la vitesse et le sens de rotation d'un canal donné. automatiquement bornée. 0 équivaut à stop(channel). / channel: Canal à commander (CHANNEL_A ou CHANNEL_B)
speed: Vitesse de -100 (arrière max) à 100 (avant max), automatiquement bornée. 0 équivaut à stop(channel). /
stop()
stop(L293D_Channel channel);
Arrêt roue libre Coupe un canal (IN1=IN2=LOW, PWM=0) : le moteur connecté peut continuer à tourner librement par inertie. /
stopAll()
stopAll();
Coupe les deux canaux (équivalent à stop() sur A puis B). /
brake()
brake(L293D_Channel channel);
Freinage actif Court-circuite les sorties d'un canal (IN1=IN2=HIGH, PWM=max) pour un ralentissement plus rapide qu'un simple stop(). /
getSpeed()
getSpeed(L293D_Channel channel) const;
Vitesse actuellement appliquée sur le canal donné. /
isInitialized()
isInitialized() const {
Indique si begin() a déjà été appelé avec succès. /
getStatus()
getStatus() const {

Méthodes privées


            channelRef(L293D_Channel channel);;
channelRef(L293D_Channel channel) const;;
writeDir(uint8_t pinOrChannel, bool high);;
begin(115200);;
begin(L293D_IN1A, L293D_IN2A, L293D_ENA,
              L293D_IN1B, L293D_IN2B, L293D_ENB);;
setSpeed(crepp::drivers::L293D_Channel::CHANNEL_A, 70);;
setSpeed(crepp::drivers::L293D_Channel::CHANNEL_B, 40);;
delay(2000);;
stopAll();;
delay(1000);;
begin(115200);;
println("Erreur d'initialisation du PCA9685 !");;
while (1);;
begin(pca,
              PCA9685_CH_1A, PCA9685_CH_2A, L293D_ENA,
              PCA9685_CH_3A, PCA9685_CH_4A, L293D_ENB);;
setSpeed(crepp::drivers::L293D_Channel::CHANNEL_A, 70);;
setSpeed(crepp::drivers::L293D_Channel::CHANNEL_B, -40);;
delay(2000);;
stopAll();;
delay(1000);;

                    

Variables membres


            return _initialized;
return _status;

                    

Code source


        #pragma once
#include <Arduino.h>
#include "../StatusDevice.h"
#include "PCA9685_Handler.h"

namespace crepp::drivers {

/**
 * @brief Identifie l'un des deux demi-ponts (canaux) du L293D.
 *
 * Le L293D intègre 2 ponts en H indépendants :
 * - Canal A : broches IN1/IN2, sortie 1Y/2Y, activation 1,2EN
 * - Canal B : broches IN3/IN4, sortie 3Y/4Y, activation 3,4EN
 */
enum class L293D_Channel : uint8_t {
    CHANNEL_A = 0, ///< Premier pont en H du circuit
    CHANNEL_B = 1  ///< Second pont en H du circuit
};

/*
 * =========================
 * Driver: L293D
 * -------------------------
 * Pilote bas niveau du circuit intégré L293D (double pont en H).
 * Un seul L293D permet de commander jusqu'à 2 moteurs DC (ou 1 moteur
 * pas à pas bipolaire) en contrôlant indépendamment le sens et la
 * vitesse de chaque canal via une broche Enable PWM.
 *
 * @badge driver
 * @badge stable
 *
 * Fonctionnalités :
 * - Configuration des broches des deux canaux (A et B) en une seule
 *   commande begin()
 * - Commande vitesse + sens par canal via PWM (-100 à 100)
 * - Arrêt "roue libre" (haute impédance) par canal ou global
 * - Freinage actif par canal (court-circuit des bobines)
 * - Lecture de la vitesse appliquée et de l'état du driver
 *
 * @note Cette classe ne modélise QUE le circuit L293D lui-même
 *       (bas niveau, sans notion de rampe ou de moteur). Pour une
 *       API orientée "moteur" avec rampe d'accélération, voir
 *       crepp::tools::Motor_Driver qui s'appuie sur cette classe.
 * =========================
 */
class L293D_Handler {
public:
    /*
     * =========================
     * Constructeur / Destructeur
     * -------------------------
     * Le destructeur coupe les deux canaux (roue libre) par sécurité.
     */
    L293D_Handler();
    ~L293D_Handler();

    /*
     * =========================
     * Initialisation
     * -------------------------
     * Configure les 6 broches utilisées par le L293D (3 par canal)
     * et place les deux canaux à l'arrêt.
     *
     * @param in1A Broche IN1 du canal A
     * @param in2A Broche IN2 du canal A
     * @param enA  Broche Enable / PWM du canal A
     * @param in1B Broche IN3 du canal B (nommée in1B pour cohérence d'API)
     * @param in2B Broche IN4 du canal B
     * @param enB  Broche Enable / PWM du canal B
     */
    void begin(uint8_t in1A, uint8_t in2A, uint8_t enA,
               uint8_t in1B, uint8_t in2B, uint8_t enB);

    /*
     * =========================
     * Initialisation (variante PCA9685)
     * -------------------------
     * Variante d'initialisation où les 4 broches de direction (IN1/IN2
     * des deux canaux, soit 1A/2A/3A/4A côté L293D) sont pilotées via
     * un crepp::drivers::PCA9685_Handler (I2C), tandis que les 2 broches
     * Enable (vitesse PWM) restent en GPIO natif du Pico.
     *
     * @param pca   Référence vers un PCA9685_Handler déjà initialisé
     *              (begin() du PCA9685 doit avoir été appelé au préalable)
     * @param chIn1A Canal PCA9685 (0-15) relié à IN1 du canal A (broche 1A)
     * @param chIn2A Canal PCA9685 (0-15) relié à IN2 du canal A (broche 2A)
     * @param enA    Broche GPIO native du Pico, PWM (broche 1,2EN)
     * @param chIn1B Canal PCA9685 (0-15) relié à IN3 du canal B (broche 3A)
     * @param chIn2B Canal PCA9685 (0-15) relié à IN4 du canal B (broche 4A)
     * @param enB    Broche GPIO native du Pico, PWM (broche 3,4EN)
     */
    void begin(PCA9685_Handler& pca,
               uint8_t chIn1A, uint8_t chIn2A, uint8_t enA,
               uint8_t chIn1B, uint8_t chIn2B, uint8_t enB);

    /*
     * =========================
     * Commande de vitesse
     * -------------------------
     * Définit la vitesse et le sens de rotation d'un canal donné.
     * @param channel Canal à commander (CHANNEL_A ou CHANNEL_B)
     * @param speed   Vitesse de -100 (arrière max) à 100 (avant max),
     *                automatiquement bornée. 0 équivaut à stop(channel).
     */
    void setSpeed(L293D_Channel channel, int8_t speed);

    /*
     * =========================
     * Arrêt roue libre
     * -------------------------
     * Coupe un canal (IN1=IN2=LOW, PWM=0) : le moteur connecté peut
     * continuer à tourner librement par inertie.
     */
    void stop(L293D_Channel channel);

    /**
     * @brief Coupe les deux canaux (équivalent à stop() sur A puis B).
     */
    void stopAll();

    /*
     * =========================
     * Freinage actif
     * -------------------------
     * Court-circuite les sorties d'un canal (IN1=IN2=HIGH, PWM=max)
     * pour un ralentissement plus rapide qu'un simple stop().
     */
    void brake(L293D_Channel channel);

    /**
     * @brief Vitesse actuellement appliquée sur le canal donné.
     */
    int8_t getSpeed(L293D_Channel channel) const;

    /**
     * @brief Indique si begin() a déjà été appelé avec succès.
     */
    bool isInitialized() const { return _initialized; }

    StatusDevice getStatus() const { return _status; }

private:
    /**
     * @brief Regroupe les broches et l'état d'un canal du L293D.
     */
    struct ChannelPins {
        uint8_t pinIn1 = 0;
        uint8_t pinIn2 = 0;
        uint8_t pinEn = 0;
        int8_t currentSpeed = 0;
    };

    ChannelPins _channels[2]; ///< [0] = CHANNEL_A, [1] = CHANNEL_B
    bool _initialized = false;
    StatusDevice _status = StatusDevice::DEVICE_ERROR_INIT;

    /// Non-nullptr si les broches IN1/IN2 sont pilotées via un PCA9685
    /// (mode hybride) plutôt qu'en GPIO natif.
    PCA9685_Handler* _pca = nullptr;

    ChannelPins& channelRef(L293D_Channel channel);
    const ChannelPins& channelRef(L293D_Channel channel) const;

    /// Ecrit un état logique HIGH/LOW sur une broche de direction,
    /// que ce soit un GPIO natif (digitalWrite) ou un canal PCA9685
    /// (write I2C), selon le mode d'initialisation utilisé.
    void writeDir(uint8_t pinOrChannel, bool high);
};

/*
@example

@include
#include <crepp/drivers/L293D_Handler.h>
@end_include

@macro
// Canal A -> moteur gauche, Canal B -> moteur droit
#define L293D_IN1A 2
#define L293D_IN2A 3
#define L293D_ENA  4
#define L293D_IN1B 5
#define L293D_IN2B 6
#define L293D_ENB  7
@end_macro

@instance
crepp::drivers::L293D_Handler l293d;
@end_instance

@setup
  Serial.begin(115200);
  l293d.begin(L293D_IN1A, L293D_IN2A, L293D_ENA,
              L293D_IN1B, L293D_IN2B, L293D_ENB);
@end_setup

@loop
  // Les deux moteurs avancent à des vitesses différentes
  l293d.setSpeed(crepp::drivers::L293D_Channel::CHANNEL_A, 70);
  l293d.setSpeed(crepp::drivers::L293D_Channel::CHANNEL_B, 40);
  delay(2000);

  l293d.stopAll();
  delay(1000);
@end_loop

@end_example

@example

@include
#include <crepp/drivers/PCA9685_Handler.h>
#include <crepp/drivers/L293D_Handler.h>
@end_include

@macro
// Directions (1A/2A/3A/4A) via PCA9685, EN en PWM direct du Pico
#define PCA9685_CH_1A 0
#define PCA9685_CH_2A 1
#define PCA9685_CH_3A 2
#define PCA9685_CH_4A 3
#define L293D_ENA 14
#define L293D_ENB 15
@end_macro

@instance
crepp::drivers::PCA9685_Handler pca;
crepp::drivers::L293D_Handler l293d;
@end_instance

@setup
  Serial.begin(115200);

  if (!pca.begin(1000.0f)) { // fréquence indifférente pour du tout-ou-rien
      Serial.println("Erreur d'initialisation du PCA9685 !");
      while (1);
  }

  l293d.begin(pca,
              PCA9685_CH_1A, PCA9685_CH_2A, L293D_ENA,
              PCA9685_CH_3A, PCA9685_CH_4A, L293D_ENB);
@end_setup

@loop
  l293d.setSpeed(crepp::drivers::L293D_Channel::CHANNEL_A, 70);
  l293d.setSpeed(crepp::drivers::L293D_Channel::CHANNEL_B, -40);
  delay(2000);

  l293d.stopAll();
  delay(1000);
@end_loop

@end_example
*/

} // namespace crepp::drivers