Velocita' minima PWM di un motore DC

Solita macchina 2WD, con soliti motori gialli con ruote...

Sono collegati ad un L298N, alimentati da 4 batterie AA.
Avevo gia' esposto il problema della differenza di velocita' che sono riuscito, bene o male, a compensare con un "delta".

Pero' la macchina va troppo veloce, il sensore di ostacoli (HC-SR04) non fa il tempo a leggere e, in alcuni casi, la macchina va a sbattere.
Allora ho provato a cambiare il valore PWM di entrambi: il problema e' che il valore minimo accettato da uno dei 2, nel mio, caso e' "120" ma:

120 < Vmotore < 255 va come un razzo
Vmotore < 120 FERMO!!!! :o

Con l'altro riesco a scendere a "80" che, nel mio caso, corrisponde ad una velocita' adeguata!
Posso correggere in qualche modo o devo provare un altro motore ? O potrebbe essere il driver?

"Solita macchina 2WD, con soliti motori gialli con ruote." sai quanti tipi ne trovi su ebay e similari e mica sono tutti identici

O metti il link a vecchia discussione oppure (meglio) rimetti qui un pò di info.
Capisci che da quel poco che hai detto, non ti si può suggerire nulla.
Codice che usi, come sono collegate e cosa è collegato ? Che tipo di motori ? etc.

Hai ragione, pensavo di avere indicato pezzi standard!

Inserzione del kit:
https://www.ebay.it/itm/Smart-Car-Tracking-Motor-Smart-Robot-Car-Chassis-Kit-2WD-Ultrasonic-For-Arduino/392308577201

Codice:

//NOTA:
// Il motore di sinistra  ha bisogno di piu' energia

/*
 Semplice test: controlliamo velocita motori
  Usiamo una shield L298N per i motori

 ATTENZIONE:
-  usando la libreria IRremote.h il PWM del pin 3 e' disablitato!!!!
- usando la libreria Servo.h il PWM dei pin 9 e 10 e' disabilitato !!!
*/

/*== CONNESSIONI ===
 * 3 IN1    MOTORE Destro
 * 4 IN2    MOTORE Destro
 * 5 PWM MOTORE Destro
 * 
 * 7 IN1    MOTORE Sinistro
 * 8 IN2    MOTORE Sinistro
 * 9 PWM MOTORE Sinistro
 */


// ============= COMANDO MOTORI=======

int pinMotoreSXPwm         = 8; // PWM controlla la velocita SX
int motoreSX_1     = 9; 
int motoreSX_2     = 7; 

int motoreDX_1     = 3 ; 
int motoreDX_2     = 4; 
int pinMotoreDXPwm        = 5; // PWM controlla la velocita DX


int velocitaCrociera  = 80;           // velocita perfetta per il sensore ultrasuoni
int velocitaAccel       = 180;        // velocita di accel. per dare spunto ad entrambi i motori

int delta =50;                            // delta di PWM per il motore di sinistra



void setup() {
   
      Serial.begin(9600);
 
      //=========== SETUP MOTORI
      
        pinMode(motoreSX_1, OUTPUT);  
        pinMode(motoreSX_2, OUTPUT);  
        pinMode(pinMotoreSXPwm, OUTPUT);  
           
        pinMode(motoreDX_1, OUTPUT);  
        pinMode(motoreDX_2, OUTPUT);  
        pinMode(pinMotoreDXPwm, OUTPUT);  

      avanti();
      
} // END setup()



void loop() {


  avanti();


} // END loop()



void avanti() {
      Serial.println("=========== AVANTI ===========");
     Serial.println ( "SX: DX : deltaTMP"); 
   
    digitalWrite(motoreDX_1,HIGH);   // Direction control motor 1
    digitalWrite(motoreDX_2,LOW);   // Direction control motor 1
 
    digitalWrite(motoreSX_1,HIGH);   // Direction control motor 2
    digitalWrite(motoreSX_2,LOW);   // Direction control motor 2

   // Usiamo una piccola accelezione per poi portarsi alla velocita' di crociera
   int partenza = 1;

   int deltaTMP      = 0;   // il delta lo portiamo da 0 fino al valore finale
   int velocitaSX    = 0;  // il motore SX lo trattiamo in modo diverso

   
    if (partenza == 1) 
    {
         for (int velocita = velocitaAccel ; velocita >= velocitaCrociera ; velocita=velocita-2)
         {
          partenza = 0;

          // f. ricavata da retta passante per due punti A(Vacc, 0) B(Vcroc, delta)
          deltaTMP = ( delta * velocita - delta* velocitaAccel) / ( velocitaCrociera - velocitaAccel);

          velocitaSX = velocita-deltaTMP ;

          // A 127 il motore SX si blocca!!!
          if (velocitaSX <= 127) {velocitaSX = 127; }

          Serial.print( vSX);
          Serial.print(" : " );
          Serial.print(velocita);
          Serial.print(" : " );
          Serial.println(deltaTMP);
      
          delay(200);
          
          analogWrite(pinMotoreSXPwm, velocitaSX);
          analogWrite(pinMotoreDXPwm, velocita);
         }
    } else {
        analogWrite(pinMotoreSXPwm, velocitaSX);
        analogWrite(pinMotoreDXPwm, velocitaCrociera);
       Serial.println("=========== REGIME ===========");
    
    }
   while (1) {}
  
} // END avanti()

Output:

a 127 il motore di SX e' bloccato , il destro continua ad andare tranquillamente
Come dicevo a 129, invece, gira ancora troppo veloce

=========== AVANTI ===========
SX : DX : deltaTMP
168 : 172 : 4
165 : 170 : 5
162 : 168 : 6
159 : 166 : 7
156 : 164 : 8
153 : 162 : 9
150 : 160 : 10
147 : 158 : 11
144 : 156 : 12
141 : 154 : 13
138 : 152 : 14
135 : 150 : 15
132 : 148 : 16
129 : 146 : 17
127 : 144 : 18
127 : 142 : 19
127 : 140 : 20
127 : 138 : 21
127 : 136 : 22
127 : 134 : 23
127 : 132 : 24
127 : 130 : 25
127 : 128 : 26
127 : 126 : 27
127 : 124 : 28
127 : 122 : 29
127 : 120 : 30
127 : 118 : 31
127 : 116 : 32
127 : 114 : 33
127 : 112 : 34
127 : 110 : 35
127 : 108 : 36
127 : 106 : 37
127 : 104 : 38
127 : 102 : 39
127 : 100 : 40
127 : 98 : 41
127 : 96 : 42
127 : 94 : 43
127 : 92 : 44
127 : 90 : 45
127 : 88 : 46
127 : 86 : 47
127 : 84 : 48
127 : 82 : 49
127 : 80 : 50

Devi prendere motori con un ingranaggio che ha un rapporto di demoltiplicazione maggiore (gira piú lento).
Ciao Uwe

ciao
tra le connessioni:

/*== CONNESSIONI ===
 * 3 IN1    MOTORE Destro
 * 4 IN2    MOTORE Destro
 * 5 PWM MOTORE Destro
 *
 * 7 IN1    MOTORE Sinistro
 * 8 IN2    MOTORE Sinistro
 * 9 PWM MOTORE Sinistro
 */

e il comando motori:

int pinMotoreSXPwm     = 8; // PWM controlla la velocita SX
int motoreSX_1     = 9;
int motoreSX_2     = 7;

int motoreDX_1     = 3 ;
int motoreDX_2     = 4;
int pinMotoreDXPwm     = 5; // PWM controlla la velocita DX

c'è una incongruenza.
Adesso trova tu la differenza.
ciao
pippo72

Si ok: c'è un' incongruenza tra i commenti e una dichiarazione ma poi nel codice viene usato il nome della variabile.
Non mi sembra rilevante.

Se per te il fatto di usare un pin che NON è pwm come se lo fosse non è rilevante ... per me va bene.

Ciao
Pippo72

pippo72:
Se per te il fatto di usare un pin che NON è pwm come se lo fosse non è rilevante ... per me va bene.

Giustissimo: hai ragione!
Cmq, il risultato non cambia: ho rifatto il circuito e il comportamento e' lo stesso.
Pero' vedo che se gli do' uno spunto manuale, inizia a girare.
Non riesco a farlo decrementare correttamente.

L298N piu alimentazione a 6V ... il datasheet indica come possibile caduta da un minimo di 1.8V fino ad un massimo di 3.2V con un carico da 1A ... caduta che puo arrivare ad un massimo di 4.9V per 2A di carico ... ed un motore fermo assorbe in media parecchio piu di uno in rotazione, anche lenta ...

Non sara' il problema principale, ma ti consiglierei di usare dei ponti mosfet, invece che BJT ... :wink:

Al volo mi vengono in mente DRV8876 o DRV8874 della TI, ma ce ne sono anche altri ... e mi sembra che qualche compagnia produca anche "breakout" per semplificare l'uso con Arduino, dato che ormai quasi tutto e' SMD ...

Cmq, il risultato non cambia: ho rifatto il circuito e il comportamento e' lo stesso.

Strano, se il valore di analogWrite (che sarebbe il valore PWM 0÷255) è uguale per entrambe i motori questi dovrebbero girare più o meno alla stessa velocità. Ci sta che un valore di PWM inferiore ad una certa soglia non riesca a fare girare il motore. Trova questa soglia che è valida solo per l'avvio, a questa soglia ci aggiungi un valore di spunto ad esempio soglia + 10 che userai solo per avviare i motori quindi per un tempo massimo di un secondo.

Normalmente per ovviare a questo problema si usa un algoritmo PID che richiede un sensore di velocità su ogni ruota. L'algoritmo ricava un valore di errore che cerca di mantenere uguale a 0, sostanzialmente è un differenziale tra velocita desidera - velocita effettiva, ad esempio se entrambe valgono 100, 100 - 100 = 0.

L'algoritmo accetta in ingresso due valori, velocità desiderata (detto setpoint) e velocità effettiva ricavata dal sensore di velocità. In base all'errore che inzialmente sarà grande l'algoritmo aumenta il pwm e l'errore tende a diminuire. L'algoritmo non riesce a mantenere l'errore fisso a zero, ma questo errore oscillerà attorno allo zero +o-. Ad esempio la auto affronta una discesa la velocità aumenterà e con esso l'errore il quale sarà compensato dall'algoritmo che ridurrà il pwm.

Per il PID c'è la libreria. Nel kit vedo due rotelle forate che somigliano alle ruote di un encoder ottico, però nella foto non vedo i sensori ottici. Puoi darmi info?

PS: può essere anche che l'algoritmo pid lo hai implementato tu nel codice, chiarisci questo punto, grazie.

@Etemenanki
Ciao Ete, ma volendo rimanere con il 298 che può fare se non aggiungere qualche batteria in più, potrebbe andare meglio con 6x1.2V = 7.2V??

Ciao.

Grazie a tutti!

Inizio col dire che, per ora, ho ovviato usando 2 servo continui in modo da far andare alla velocita' che voglio.
Non e' il massimo ma per iniziare e imparare e' gia' molto (per me!)

Sono anche io propenso a pensare che sia un problema di alimentazione perche' ogni singolo motore, preso da solo, si comporta in maniera corretta (regge senza problemi un PWM molto minore come "minimo di giri").
In piu', aumentando l'alimentazione, (ho usato un alimentatore da banco) il comportamento cambia totalmente.

Nel kit ci sono due dischi aggiuntivi da encoder ma figuriamoci che i cinesi mi mandavano l' encoder! :slight_smile:

Come si puo' vedere dal codice, ho provato ad usare l'approccio "parti a manetta e rallenta fino a raggiungere la velocita' di crociera" ma il motore SX arrivato al valore 127 si ferma di botto.

Grazie per la dritta sul PID: lo guardero' di sicuro perche' sembra interessantissimo (anche se vedo che, essendo basato sul calcolo differenziale, dovro' rispolverare gli anni di universita'!)

Grazie

Maurotec:
...ma volendo rimanere con il 298 che può fare se non aggiungere qualche batteria in più, potrebbe andare meglio con 6x1.2V = 7.2V??

Ciao.

Si, con 6 oppure 8 stilo dovrebbe migliorare ,sempre controllando prima i valori di tensione massima e corrente di stallo dei motori che ha, per evitare di friggerli ... stando sul prudente, direi di togliere almeno 2V come caduta "media" (quindi ad esempio, se i motori sono da 6V nominali, darne 8 al driver e' ok, anche 9 andrebbero bene, un volt o due in piu non dovrebbero creare troppi problemi, mentre probabilmente 12 sarebbero un po troppi, ed anche se alimentato in PWM potrebbeo surriscaldarli)

Come si puo' vedere dal codice, ho provato ad usare l'approccio "parti a manetta e rallenta fino a raggiungere la velocita' di crociera" ma il motore SX arrivato al valore 127 si ferma di botto.

Quindi e il motore che proprio non va? Per togliermi il dubbio invertire i motori.

Nel kit ci sono due dischi aggiuntivi da encoder ma figuriamoci che i cinesi mi mandavano l' encoder!

:smiley:
Comunque se uno dei motori (o driver) ha problemi con il pid ti complichi la vita senza risultati, quindi prima c'è da capire se c'è qualche problema hardware e l'unico modo pratico è quello di escludere un problema software e ciò con il minimo indispensabile del software tipo analogWrite(value) dove value è una variabile che incrementi lentamente.

Occhio con i pin PWM hardware, che se no prendi fischi per fiaschi. :smiling_imp:

Ciao.