OpenMotorControl: il Driver motore open source per la gestione avanzata della trazione in robotica

 

Open source e basato su un microcontrollore ATmega32U4, รจ dotato di driver per due motori CC a spazzole o uno stepper motor. Puรฒ ricevere comandi da USB, seriale o IยฒC bus.

Per chi fa robotica, una delle problematiche da risolvere รจ la gestione dei motori per la trazione, ovvero come alimentare correttamente i motori per far avanzare il proprio robot.

Se lavorate con Arduino, la prima e immediata soluzione รจ lโ€™utilizzo di uno shield; in commercio se ne trovano diversi, dai piรน semplici che permettono il controllo separato di due piccoli motori in corrente continua, ai piรน evoluti che possono anche misurare la corrente assorbita.

Indipendentemente dal produttore, gli shield si basano tutti sullโ€™utilizzo di un driver di potenza (di solito un L298) interfacciato direttamente con le uscite PWM di Arduino e contornato da pochi altri componenti.

Sicuramente lโ€™uso di uno shield รจ una soluzione valida, ma รจ necessario utilizzare almeno quattro uscite di Arduino: di solito due per regolare la velocitร  e due per la direzione.

Se invece utilizzate un microcontrollore generico oppure un Atmel stand-alone o una board diversa da Arduino, le cose si complicano un pochino, perchรฉ in commercio รจ difficile reperire driver con unโ€™interfaccia piรน flessibile ed il costo comincia a lievitare.

Se poi avete la necessitร  di comandare piรน di due motori, la cosa si complica parecchio, anche per chi utilizza una scheda Arduino, perchรฉ sorgono problematiche sia sul piano hardware che su quello della programmazione del dispositivo.

Per venire incontro alle esigenze di chi vuole gestire piccoli motori in corrente continua con logiche programmabili, abbiamo pensato di progettare un driver tutto nostro che permettesse di avere unโ€™elevata flessibilitร  operativa e soprattutto fosse open source, al fine di permettere a chiunque di poterlo adattare alle proprie esigenze.

Il nome che gli abbiamo dato รจ significativo della filosofia progettuale: OpenMotorControl, che abbiamo abbreviato in OMC21, dove 21 indica il numero di canali (due in questo caso) e la corrente gestita per ciascun canale (1A).

Come vedremo, si tratta di un circuito stand-alone pilotabile da varie logiche, dotato di unโ€™interfaccia di comunicazione che prevede diversi protocolli di comunicazione ed รจ adatta alle piรน svariate esigenze.

Schema elettrico di OpenMotorControl

Tipicamente, nel realizzare un controller per motori in corrente continua si ricorre al cosiddetto ponte ad H, ovvero un circuito formato da quattro transistor montati a ponte, in grado di comandare velocitร  e direzione del motore attraverso lโ€™erogazione di impulsi PWM e lโ€™inversione della polaritร  allโ€™uscita.

Per la nostra applicazione, un semplice ed economico circuito integrato contenente un ponte ad H รจ piรน che sufficiente, anche perchรฉ, permette di contenere costi ed ingombri.

Il circuito integrato adottato รจ siglato LV8405 ed รจ un completo ponte ad H a MOSFET ad elevate prestazioni che implementa anche un controllo sulla tensione di alimentazione e dispone di protezioni sia in temperatura che in corrente.

Viene venduto nel package SMD SSOP16 e quindi non รจ direttamente utilizzabile in breadboard, ma รจ necessario sia previsto un apposito PCB.

Pur essendo piccolissimo, presenta caratteristiche di tutto rispetto:
โ€ข 2 canali con controllo forward/reverse;
โ€ข basso consumo;
โ€ข bassa resistenza serie dei MOSFET (0,75 ohm);
โ€ข protezioni integrate da bassa tensione e surriscaldamento;
โ€ข quattro modi di funzionamento (forward/reverse, brake, stop);
โ€ข corrente massima di uscita 1,4A;
โ€ข corrente di uscita (picco) di 2,5A.

La bassissima resistenza dei MOSFET usati per il controllo del motore (soli 0,75 ohm) permette un rendimento molto elevato e presenta una dissipazione di calore molto contenuta.

Per realizzare un controllo motori facile da interfacciare e programmare รจ perรฒ necessario abbinare questo IC ad un microcontrollore debitamente programmato: la scelta รจ caduta sullโ€™ATmega32U4 prodotto dalla Atmel, lo stesso utilizzato sulla scheda Arduino Leonardo.

Nella scheda Leonardo, a differenza di Arduino Uno, che usa il microcontrollore ATmega328, viene usato lโ€™ATmega32U4 perchรฉ implementa al suo interno anche tutto lโ€™hardware per la comunicazione USB, eliminando la necessitร  di utilizzare esternamente un convertitore USB/seriale.

Le caratteristiche sono in generale migliori dellโ€™ATmega328, essendo un componente di ultima generazione; inoltre il micro รจ perfettamente compatibile con lโ€™ambiente di sviluppo (IDE) di Arduino.

Pochi altri componenti ed ecco disponibile un controllo motori piccolo, economico e dalle caratteristiche interessanti:
โ€ข configurazione a doppio ponte H per pilotare due motori in cc o uno stepper motor bipolare;
โ€ข tensione della sezione di potenza: 3 รท 15V;
โ€ข tensione di alimentazione della logica: 3 รท 5V;
โ€ข corrente di uscita: 1,4A continua (2,5A picco) per motore;
โ€ข interfacciamento USB, seriale, IยฒC-Bus;
โ€ข ingressi compatibili 3,3V e 5V;
โ€ข alimentazione selezionabile tra interna ed esterna a 3,3V o 5V.

Siccome volevamo un controller molto flessibile, abbiamo curato particolarmente la sezione di alimentazione; volevamo un driver compatibile con logiche a 3,3V e 5V che potesse sia essere alimentato dalla stessa tensione della logica di comando, sia alimentare una logica esterna, cosรฌ da lavorare con gli stessi livelli di alimentazione.

Nello schema elettrico del circuito (lo trovate qui accanto…) potete vedere che sono stati previsti due stabilizzatori di tensione di tipo low-drop-out (a bassa caduta di tensione ingresso-uscita) utilizzati per ricavare le tensioni di alimentazione a 3,3V (se ne occupa U3) e 5V (se ne occupa U2); la selezione della necessaria tensione di alimentazione avviene unendo con una goccia di stagno le piazzole corrispondenti del jumper JP1.

Saldando la piazzola centrale con la 3V3 si imposta la tensione di alimentazione a 5V, mentre collegandola a 3V3 si fissa la tensione a 3,3 volt.

Come da specifiche dellโ€™integrato ATmega32U4, il funzionamento a 3,3 volt รจ garantito solo con un quarzo da 8MHz, al quale va abbinato il corrispondente bootloader. La tensione scelta risulta anche disponibile sul connettore CN1 e puรฒ essere utilizzata per alimentare una logica esterna, come una scheda Arduino (si veda la Tabella 6).

Lโ€™alimentazione principale per tutto il circuito viene prelevata dalla linea di alimentazione dei motori VM.

Unโ€™ulteriore possibilitร  prevede di non saldare alcuna piazzola del connettore CN3 in questo modo lโ€™alimentazione VM verrร  usata per alimentare i soli motori mentre lโ€™alimentazione per lโ€™ATmega32U4 dovrร  essere applicata esternamente dalla logica di comando tramite il connettore CN1; in questo caso sarร  necessario che la logica di comando venga alimentata separatamente.

Per quando riguarda il connettore di alimentazione, esso prevede sei contatti di cui due per lโ€™alimentazione denominati VM e GND, due per il primo motore (1A e 1B) e altrettanti per il secondo motore (2A e 2B).

Lโ€™alimentazione VM dovrร  ovviamente essere compatibile con la tensione di alimentazione dei motori e dovrร  fornire sufficiente corrente per alimentare i motori. Il connettore ICSP รจ il connettore per la programmazione, spiegheremo piรน avanti come utilizzare questo connettore per caricare il bootloader allโ€™interno dellโ€™ATmega32U4.

Il CN1 รจ il connettore per lโ€™alimentazione della logica e per la comunicazione seriale e IยฒC. Quanto al connettore micro USB, รจ utilizzato sia per impartire comandi al controller, sia per la programmazione del microcontrollore tramite lโ€™IDE di Arduino.

Caricare il bootloader su OpenMotorControl

Se avete acquistato OMC21 da Futura Elettronica il bootloader รจ giร  precaricato. Se invece vi siete costruiti il progetto, seguite questa procedura per rendere OMC21 rilevabile come un Arduino Leonardo.

Per caricare il bootloader dovrete necessariamente procedere cosรฌ: non collegate nulla sul connettore CN2 e lasciate dissaldato il connettore per la selezione dellโ€™alimentazione, oppure lasciate impostata una tensione di 5V.

Se disponete di un apposito programmatore per dispositivi Atmel conoscete giร  la procedura; altrimenti munitevi di una scheda Arduino Uno, che userete come programmatore.

Il connettore ICSP del controller OMC21 dovrร  essere cablato pin to pin con il connettore ICSP di Arduino utilizzato come programmatore, ovvero pin 1 con pin 1 e cosรฌ via; fa eccezione il pin 5 (pin di reset) del connettore del controller, che deve essere connesso al pin10 di Arduino.

A questo punto collegate la scheda Arduino alla porta USB; il LED di alimentazione di OMC si accenderร  ad indicare la sua corretta alimentazione.

Caricate su Arduino lo sketch Esempi-ArduinoISP, il quale abiliterร  Arduino alla funzione di programmatore; ora aprite il menu Strumenti-Tipo di Arduino e modificate il target di programmazione in Arduino Leonardo; selezionate il programmatore Arduino as ISP e quindi avviate la programmazione del bootloader cliccando su Scrivi il bootloader. Attendete circa un minuto per il completamento delle operazioni.

Lโ€™integrato ATmega32U4 dispone di una seriale principale facente capo al modulo USB interno; a livello di programmazione, nulla cambia rispetto ad Arduino, se non per il fatto che non serve un convertitore USB/seriale esterno perchรจ giร  implementato allโ€™interno. Grazie al bootloader, non appena OMC21 viene inserito nella USB esso verrร  riconosciuto come periferica e creata una seriale virtuale etichettata come Arduino Leonardo alla quale viene assegnato un nome: nel caso di Fig. 1, COM21.

Fig. 1 Lโ€™OMC21 viene rilevato come periferica seriale Arduino Leonardo.

 

A questo punto il vostro OMC21 puรฒ essere gestito completamente via USB ed รจ possibile caricare, tramite lโ€™IDE di Arduino lo sketch di gestione denominato OMC21.ino; descriviamo ora come funziona questo software di gestione, in particolare il controllo del ponte ad H. Iniziamo col dire che la gestione dei quattro interruttori statici rappresentati dai transistor puรฒ essere fatta in modo differente a seconda della funzione che si vuole ottenere.

Prendiamo a riferimento la Fig. 2 che rappresenta, in modo semplificato, i quattro interruttori del ponte ad H, che nel nostro driver sono implementati con dei MOSFET.

Fig. 2 Schematizzazione del ponte ad H.

 

Leggiamo attentamente il data-sheet del driver LV8405V-D e ricaviamo la tabella di veritร  (Tabella 1) relativa allo stato degli interruttori (S1-S4) e delle uscite (OUT1 e OUT2) per ogni possibile combinazione degli ingressi; la lettera L indica un livello logico basso e la lettera H un livello logico alto.

Analizzando la Tabella 1 possiamo capire piรน in dettaglio le diverse modalitร  di funzionamento a seconda di come pilotiamo i due ingressi IN1 e IN2. Nel primo caso (IN1=H e IN2=H) entrambe le uscite si trovano in alta impedenza; in questa situazione รจ come se il motore fosse scollegato dal driver e libero di ruotare.

Se invece ci poniamo nel quarto caso (IN1=L e IN2=L) รจ come se il motore si trovasse in cortocircuito; cosa cambia allโ€™atto pratico tra i due casi? Se utilizziamo i motori per far avanzare un robot che sta avanzando a velocitร  sostenuta, nel primo caso, privando i motori dellโ€™alimentazione, otterremo un arresto graduale del robot, che si fermerร  in uno spazio dipendente dalla propria inerzia.

Lโ€™arresto deriverร  dai vari attriti negli organi meccanici e da quelli tra il robot e la superficie su cui si muoverร .

Per comprendere cosa succede nella seconda ipotesi, occorre considerare che un motore in corrente continua รจ una macchina reversibile, ovvero se gli forniamo energia elettrica il suo motore ruota, ma se siamo noi a ruotarlo il motore fornirร  energia elettrica, comportandosi, cioรจ, da generatore elettrico; in questo secondo caso, per il fenomeno della reazione dโ€™indotto, lo sforzo richiesto per ruotare lโ€™albero dipenderร  da quanta corrente verrร  prelevata dagli estremi degli avvolgimenti del motore.

Tabella 1 Tabella di veritร  del driver LV8405.

 

Trasferendo questo concetto al nostro caso, diciamo che se quando il robot รจ in movimento togliamo tensione al motore, questo continuerร  a girare per inerzia, ma se il ponte mette in cortocircuito i suoi terminali, la corrente che ne deriva nellโ€™avvolgimento causa a sua volta un campo elettromagnetico tale da opporsi alla causa che lโ€™ha generato; essendo tale causa la rotazione dellโ€™albero, questโ€™ultimo verrร  frenato fino a fermarsi, allorchรฉ mancando la corrente smetterร  anche lโ€™azione frenante.

Se provate entrambi i casi, anche solo facendo girare a mano una ruota, noterete in pratica lโ€™effetto. In molti shield commerciali queste due funzioni non sono selezionabili, mentre nel nostro circuito abbiamo previsto la possibilitร  di selezionare (via software) in quale modalitร  utilizzare le uscite.

I rimanenti due casi descritti nella Tabella 1 sono invece piรน facili da comprendere: se poniamo lโ€™ingresso IN1 a livello basso e comandiamo lโ€™ingresso IN2 con un segnale PWM, abbiamo la possibilitร  di comandare il motore in direzione forward con una potenza direttamente proporzionale al valore del duty-cycle, il che permette di regolare la velocitร  di avanzamento del robot (quando il duty-cycle sarร  zero fermeremo il robot con lโ€™effetto freno precedentemente descritto).

Se invece applichiamo il segnale PWM allโ€™ingresso IN2, ma poniamo lโ€™ingresso IN1 a livello alto, quando il duty-cycle ha valore massimo siamo nel caso delle uscite ad alta impedenza ed il robot si fermerร  senza alcun effetto frenante.

Invertendo IN1 con IN2 avremmo le stesse funzioni, ma con il motore che ruoterร  in senso inverso. Vedete quindi come, giocando sugli ingressi, abbiamo la possibilitร  di scegliere direzione e velocitร  del motore e di attivare o meno lโ€™effetto frenante.

Gli ingressi del driver IN1 e IN2 per il primo motore e IN3 e IN4 per il secondo motore, sono connessi a quattro uscite PWM dellโ€™integrato ATmega32U4, facilmente gestibili con lโ€™istruzione analogWrite disponibile nellโ€™IDE di Arduino.

Per il collegamento dei motori e dellโ€™alimentazione di potenza รจ stato previsto il connettore CN2, sul quale possono essere saldati sia uno strip maschio o femmina, sia un connettore con morsetti a vite.

Abbiamo previsto anche la possibilitร  di leggere la tensione di alimentazione VM utilizzando un semplice partitore di tensione; per rendere compatibile il livello della tensione di alimentazione dei motori con quella di lettura degli ingressi analogici di Arduino, la tensione viene ridotta di un fattore undici e quindi resa disponibile allโ€™ingresso A0 di Arduino.

Conoscere la tensione permette, nel caso di alimentazione a batteria, di evitare la scarica completa, ovvero, in carica, di impedire la sovra-scarica (sempre dannosa).

Al connettore CN2 fanno capo ulteriori pin di Arduino, ovvero i rimanenti pin digitali non usati dal driver e tre pin analogici. In pratica รจ come se disponessimo di una scheda Arduino Leonardo con a bordo un driver per motori.

Piano di montaggio di OMC21

Elenco componenti

R1, R6: 10 kohm (0603)
R2, R3: 22 ohm (0603)
R4: 470 ohm (0603)
R5: 100 kohm (0603)
C1: 100 nF multistrato (0603)
C2: 15 pF ceramico (0603)
C3: 15 pF ceramico (0603)
C4: 1 ยตF ceramico (0603)
C5รทC7: 100 nF multistrato (0603)
C8: 10 ยตF 10 VL elettrolitico (ร˜ 4mm)
C9, C11: 100 nF multistrato (0603)
C10: 10 ยตF 35 VL elettrolitico (ร˜ 4mm)
C12: 10 nF multistrato (0603)
C13, C14: 100 nF multistrato (0603)
C15: 4,7 ยตF 10 VL elettrolitico (ร˜ 4mm)
D1: GF1M
F1: Fusibile 500mA auto ripristinante
LD1: LED verde (0805)
U1: ATMEGA32U4-AU (MF1173)
U2: LD1117S50CTR
U3: LD1117AS33TR
U4: LV8405V-TLM-E
P1: Pulsante SMD basso profilo
Q1: Quarzo 16MHz

Varie:
- Connettore micro-USB
- Strip maschio 3 vie (2 pz.)
- Strip maschio 6 vie (1 pz.)
- Strip maschio 8 vie (1 pz.)
- morsetto 6 poli passo 2,54mm
- Circuito stampato

Il firmware

Occupiamoci ora di descrivere il programma che sarร  caricato sullโ€™ATmega32U4.

Lo sketch dovrร  occuparsi di gestire la comunicazione USB, quella seriale e quella IยฒC, interpretando i comandi letti e mettendoli in pratica comandando adeguatamente gli ingressi del driver.

Lo sketch prevede quindi una routine di ascolto sulle tre porte di comunicazione, in attesa di dati in arrivo; fortunatamente il piccolo ATmega32U4 dispone di due moduli UART ed una porta IยฒC hardware, perfette per il nostro progetto.

La seriale principale (Serial) fa capo al modulo USB e dal lato software si comporta esattamente come la seriale di Arduino Uno, perciรฒ la ricezione di dati su questa porta puรฒ essere ottenuta con lโ€™istruzione Serial.available() che riporta il numero di caratteri presenti sul buffer di lettura.

In questa modalitร  lโ€™OMC21 รจ controllabile tramite un PC o una qualsiasi periferica che disponga di una USB host.

La dichiarazione di utilizzo di questa seriale avviene con la riga di codice Serial.begin(9600) dove 9600 รจ la velocitร  di comunicazione (modificabile a piacimento secondo le vostre necessitร ).

Abbiamo usato 9600 come impostazione predefinita perchรฉ รจ la velocitร  piรน usata; volendo ridurre i tempi di lettura dei comandi, potete incrementare questo valore sino al massimo di 115.200 bps.

Se sono presenti caratteri nel buffer del modulo UART, vengono letti tramite lโ€™istruzione Serial.readBytes(inByte, maxinByte) che permette di leggere un numero prefissato di byte in un lasso di tempo prestabilito.

Il protocollo di comunicazione che abbiamo pensato di utilizzare prevede lโ€™utilizzo di quattro byte, di cui il primo รจ solo il carattere โ€˜$โ€™ , necessario per riconoscere lโ€™inizio della sequenza; questo, assieme al numero di caratteri inviati, rappresenta il controllo di correttezza nella lettura del comando.

Terminata la lettura dei quattro byte, si verifica se ve ne siano altri; in ogni caso il buffer viene svuotato.

Puรฒ capitare che inviando i comandi si aggiungano inavvertitamente dei caratteri non necessari, come ad esempio un fine riga o un ritorno a capo; nella nostra applicazione questi vengono ignorati e cancellati dal buffer.

I rimanenti tre byte dopo il carattere โ€˜$โ€™ rappresentano i comandi per il controller: il secondo byte contiene informazioni sulla modalitร  di funzionamento (brake o standby) e sulla direzione di marcia dei motori, mentre i byte tre e quattro contengono lโ€™informazione della velocitร , rispettivamente, per il motore 1 e 2. In questo modo, inviando una sequenza di quattro byte si comandano contemporaneamente entrambi i motori (Tabella 2).

Tabella 2 Sequenza di byte per il comando del controller.

 

Il byte2 contiene informazioni sia sulla modalitร  di funzionamento che sulla direzione dei motori (Tabellaย 3).

Il quinto bit del byte2, se posto a uno consente di richiedere la lettura della tensione di alimentazione; รจ lโ€™unico caso in cui รจ necessaria la comunicazione seriale bidirezionale, altrimenti la sola linea di invio dati al controller รจ sufficiente.

Tabella 3 Funzioni relative al byte2 della sequenza di comando.

 

Nel Listato 1 trovate le righe di codice dello sketch che svolgono le funzioni descritte.

Se volete comandare il controller tramite la seriale di un microcontrollore, dovete utilizzare la seconda porta seriale (Serial1) del microcontrollore ATmega32U4 i cui pin TX e RX sono disponibili nel connettore CN1.

La connessione prevede che la linea TX del microcontrollore sia connessa alla linea RX di OMC21 e se richiesta la lettura della tensione di alimentazione, anche la linea RX del microcontrollore connessa alla linea TX di OMC21.

La riga di codice che abilita questa seriale รจ Serial1.begin(9600); anche in questo caso la velocitร  di trasmissione puรฒ essere modificata sino un massimo di 115.200 bps.

Per quanto riguarda la gestione del software, รจ simile a quella della comunicazione seriale principale. Inoltre, la porta di comunicazione IยฒC viene attivata tramite l’istruzione Wire.onReceive(I2CreceiveEvent), dove I2CreceiveEvent รจ la procedura richiamata dall’interrupt alla ricezione del primo byte. Per maggiori dettagli su come vengono elaborati i dati ricevuti, si prega di consultare il Listato 2. riferitevi al Listato 2.

Ad ogni arrivo di dati su questa porta viene richiamata la procedura che si preoccupa di verificare se la sequenza รจ compatibile con lo standard OMC21 e quindi ne estrapola i valori. Lo sketch per OMC21 รจ quindi predisposto per monitorare continuamente lโ€™invio dei byte di comando su tutte e tre le porte di comunicazione: USB, seriale e IยฒC.

Non ha importanza su quale porta arriveranno i dati, al limite potrebbero arrivare anche in contemporanea, anche se sarebbe abbastanza inutile farlo, il vantaggio รจ comunque quello di caricare un unico sketch, evitando di impazzire con la programmazione.

Il nostro controller OMC21 una volta programmato รจ pronto ad azionare i motori in base ai comandi ricevuti, vediamo con degli esempi come poterlo fare sfruttando le diverse porte di comunicazione.

Listato 1

if (Serial.available() & gt; 0) {
  char inByte[maxinByte];
  int numByte = Serial.readBytes(inByte, maxinByte);
  // reads until maxinByte are reads or if TimeOut is occurred
  byte extraByte;  // clear the buffer if extra bytes is arrived
  while (Serial.available()) extraByte = Serial.read();
  // if data starting with โ€˜$โ€™ and lenght is correct...
  if (inByte[0] ==โ€™$โ€™ & amp; & numByte == maxinByte) {
    dirM1 = inByte[1];
    dirM1 = dirM1 & amp;
    0x01;
    dirM2 = inByte[1];
    dirM2 = (dirM2 & amp; 0x02) & gt;
    >
    1;
    modeM1 = inByte[1];
    modeM1 = (modeM1 & amp; 0x04) & gt;
    >
    2;
    modeM2 = inByte[1];
    modeM2 = (modeM2 & amp; 0x08) & gt;
    >
    3;
    speedM1 = inByte[2];
    speedM2 = inByte[3];
    setMotor();
    byte readVM = inByte[1];
    readVM = (readVM & amp; 0x10) & gt;
    >
    4;
    if (readVM == 1) {
      int VM = analogRead(VM_pin) * 36;
      VM = VM & gt;
      >
      6;
      Serial.println(VM);  // VM*10 [volt] (0-255)
    }
  }
}

Listato 2

void I2CreceiveEvent(int byteIn) {
  while (Wire.available() & gt; 0)  // loop until available byte on wire
  {
    char acknowledge = Wire.read();
    if (acknowledge ==โ€™$โ€™) {
      char mode = Wire.read();  // read mode byte
      speedM1 = Wire.read();    // read speed byte
      speedM2 = Wire.read();    // read speed byte
      dirM1 = mode;
      dirM1 = dirM1 & amp;
      0x01;
      dirM2 = mode;
      dirM2 = (dirM2 & amp; 0x02) & gt;
      >
      1;
      modeM1 = mode;
      modeM1 = (modeM1 & amp; 0x04) & gt;
      >
      2;
      modeM2 = mode;
      modeM2 = (modeM2 & amp; 0x08) & gt;
      >
      3;
      setMotor();
    }
  }
}

Gestione tramite USB

Appena programmato, lโ€™OMC21 รจ ancora connesso alla USB e viene subito voglia di testarlo senza ulteriori cablaggi, utilizzando il PC per lโ€™invio dei comandi.

A titolo di esempio vediamo come costruire i tre byte dati per il controllo dei motori nel caso volessimo il motore 1 con direzione forward con potenza del 50% e funzione frenatura attivata ed il motore 2 con direzione reverse con potenza del 25% senza frenatura (standby).

Essendo la velocitร  espressa come valore numerico compreso da 0 (0% della potenza) a 255 (100% della potenza), ai due valori 50% e 25% corrispondono rispettivamente i valori decimali 128 e 64.

Il byte2 dovrร  essere costruito bit per bit come nella Tabella 4.

Tabella 4 Costruzione del byte2 per lโ€™esempio indicato.

 

I tre byte di comando saranno quindi quelli riportati in Tabella 5.

Tabella 5 Sequenza di byte per lโ€™esempio indicato.

 

Se il nostro controller รจ connesso alla seriale difficilmente potremmo controllarlo utilizzando la funzione SerialMonitor di Arduino, per il semplice motivo che i primi 31 caratteri del codice ASCII non sono stampabili, in quanto usati come comandi relativamente alla comunicazione con le stampanti.

Se vogliamo inviare i quattro byte cosรฌ costruiti รจ necessario utilizzare un monitor seriale che permetta di gestire anche i caratteri non stampabili; nel nostro caso abbiamo usato un software gratuito, distribuito in versione portable di nome SSCOM (Fig. 3), ma tanti altri sono disponibili in rete.

Nellโ€™esempio sono stati inviati (cerchio rosso) i byte 0x24 0x10 0x8F 0x00 corrispondenti a motore 1 fermo e motore 2 forward al 56% e richiesta tensione di alimentazione VM.

Evidenziati con un cerchio blu, i dati di risposta relativi ad una tensione di alimentazione di circa 6,8 volt.

Se invece volete crearvi un software di gestione tutto vostro, vi consigliamo di utilizzare Processing, che permette con semplicitร  di utilizzare una comunicazione seriale via USB, un esempio di sketch รจ riportato nel Listato 3.

Listato 3

// OpenMotorControl21
// Example to use Processing for control OMC21 USB

import processing.serial.*;

Serial myPort; // Create object from Serial class

void setup() {
  size(200, 200);
  background(0);
  String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. 
  println(โ€œportName: โ€œ, portName);
  myPort = new Serial(this, portName, 9600);
}

void draw() {}

void mouseClicked() // if click on background
{
  int dirM1 = 0; // set direction for Motor1 0=forward 1=reverse
  int dirM2 = 0; // set direction for Motor2 0=forward 1=reverse
  int modeM1 = 0; // set mode for Motor1 0=brake 1=standby
  int modeM2 = 0; // set mode for Motor2 0=brake 1=standby 
  int mode = (modeM2 & lt; & lt; 3) + (modeM1 & lt; & lt; 2) + (dirM2 & lt; & lt; 1) + dirM1;
  char modedir = char(mode); // convert integer to char
  char speedM1 = 128; // set speed for Motor1 at 50%
  char speedM2 = 128; // set speed for Motor2 at 50%
  myPort.write(โ€˜$โ€™); // write start char
  myPort.write(modedir); // write mode-dir byte
  myPort.write(speedM1);
  myPort.write(speedM2);
}

In questo esempio, semplicemente viene creato un oggetto della classe serial, quindi allโ€™avvio dello sketch viene aperta la porta e non appena viene cliccato su un qualsiasi punto vengono costruiti ed inviati i quattro byte necessari al comando dellโ€™OMC21.

Non avendo previsto un menu a tendina per la scelta della COM, la porta viene specificata con la riga di codice portName = Serial.list()[0] in cui รจ necessario indicare lโ€™indice relativo allโ€™elenco del COM installate nel PC.

Se, come spesso accade, non disponete di COM hardware ed al PC รจ connesso solo Arduino, nella lista trovate una sola COM il cui indice รจ zero.

 

Fig. 3 Monitor Seriale SSCOM per inviare i comandi ad OMC21.

 

Gestione via Seriale

Se vogliamo comandare lโ€™OMC21 tramite una scheda Arduino, conviene utilizzare una seriale software, utilizzando una sola linea digitale da connettere alla linea RX del connettore CN1; in questo modo la seriale hardware rimarrร  libera di comunicare con il PC.

Lo sketch di esempio รจ riportato nel Listato 4, dove viene mostrato come sia possibile costruire il byte di controllo (byte2) partendo dalle impostazioni dei singoli bit di direzione e frenatura. Sarร  la riga di codice int mode = (modeM2<<3) + (modeM1<<2) + (dirM2<<1) + dirM1 a ricostruire il byte completo traslando e sommando i singoli bit. Utilizzeremo successivamente quattro comandi Serial.write per inviare i singoli byte contenenti il carattere di inizio e i tre byte di dati.

Listato 4

// OpenMotorControl21
// Example to use Arduino for control OMC21 Softserial Serial

#include <SoftwareSerial.h>

SoftwareSerial OMCSerial(2, 3); // RX, TX

void setup() {
  Serial.begin(9600); //use Hardware Serial to communicate with PC 
  OMCSerial.begin(9600); //use software serial to communicate with OMC21 
}

void loop() {
  byte dirM1 = 0; // set direction for Motor1 0=forward 1=reverse
  byte dirM2 = 0; // set direction for Motor2 0=forward 1=reverse
  byte modeM1 = 0; // set mode for Motor1 0=brake 1=standby
  byte modeM2 = 0; // set mode for Motor2 0=brake 1=standby 
  byte mode = (modeM2 & lt; & lt; 3) + (modeM1 & lt; & lt; 2) + (dirM2 & lt; & lt; 1) + dirM1;
  mode = mode + 16; //if request Motor voltage
  char speedM1 = 128; // set speed for Motor1 at 50%
  char speedM2 = 128; // set speed for Motor2 at 50%
  OMCSerial.write(โ€˜$โ€™);
  OMCSerial.write(mode);
  OMCSerial.write(speedM1);
  OMCSerial.write(speedM2);
  delay(1000);
}

Gestione tramite IยฒC

Se volete controllare lโ€™OMC21 tramite la porta TWI di Arduino, non dovete far altro che connettere le due linee SDA e SCL di entrambe le porte tra loro e collegare i GND di entrambe le schede.

Non sono necessarie le resistenze di pull-UP per il semplice motivo che sono giร  presenti internamente al microcontrollore sia in Arduino Uno che sullโ€™ATmega32U4 ed abilitate in automatico non appena si richiama la funzione Wire.begin().

Lo sketch da caricare in Arduino Uno per comandare lโ€™OMC21 รจ contenuto nel Listato 5, che si presenta molto simile ai giร  descritti precedenti listati. Cโ€™รจ perรฒ unโ€™importante differenza con il modo di comunicare tramite seriale che riguarda il sistema di indirizzamento delle periferiche.

Mentre in una comunicazione seriale lo scambio di dati avviene punto a punto, ovvero solo due periferiche dialogano tra loro, nel Bus IยฒC possono coesistere sino a 127 periferiche di tipo Slave, tutte in comunicazione con lโ€™unico master.

Il master in questo caso รจ Arduino Uno (o la logica di comando) mentre gli slave sono le schede OMC21; il vantaggio evidente รจ quello di poter utilizzare piรน controller e quindi piรน motori, tutti gestiti da unโ€™unica scheda Arduino utilizzando una sola porta TWI.

Ricordiamo che in Arduino la porta TWI utilizza a tutti gli effetti il protocollo IยฒC, che perรฒ รจ proprietario della Philips (che lo ha inventato).

Nel Listato 5 รจ infatti presente la riga di codice const int OMC21address=4 che ha lo scopo di specificare verso quale slave avviene la comunicazione; ovviamente sul BUS TWI potranno coesistere anche altri slave non necessariamente controller motori OMC21. Nello sketch OMC21.ino รจ stato specificato come indirizzo predefinito di periferica il valore 4, ma questo puรฒ essere modificato a piacimento se intendete usare sul bus una periferica che ha giร  questo indirizzo.

Se usate piรน controller OMC21 รจ necessario che ciascuno abbia un indirizzo univoco; dovrete quindi caricare su ciascun controller uno sketch in cui avrete specificato un indirizzo differente. Nella stesura del programma di controllo dovrete poi tenere conto dei vari indirizzi assegnati, per assicurare il corretto transito dei dati.

Listato 5

// OpenMotorControl21
// Example to use Arduino for control OMC21 I2C

#include <Wire.h>

const int OMC21address = 4; //address of OMC21

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}

void loop() {
  byte dirM1 = 0; // set direction for Motor1 0=forward 1=reverse
  byte dirM2 = 0; // set direction for Motor2 0=forward 1=reverse
  byte modeM1 = 0; // set mode for Motor1 0=brake 1=standby
  byte modeM2 = 0; // set mode for Motor2 0=brake 1=standby 
  byte mode = (modeM2 & lt; & lt; 3) + (modeM1 & lt; & lt; 2) + (dirM2 & lt; & lt; 1) + dirM1;
  char speedM1 = 128; // set speed for Motor1 at 50%
  char speedM2 = 128; // set speed for Motor2 at 50%
  Wire.beginTransmission(OMC21address); // transmit to OMC21
  Wire.write(โ€˜$โ€™);
  Wire.write(mode);
  Wire.write(speedM1);
  Wire.write(speedM2);
  Wire.endTransmission(); // stop transmitting

  delay(1000);
}

Utilizzo del controller

Quanto ai collegamenti e allโ€™utilizzo pratico, sono possibili numerose combinazioni per lโ€™alimentazione della logica di controllo e della sezione di potenza dellโ€™integrato driver LV8405V-D; la Fig. 4 mostra il collegamento generale dei due motori in cc (per lo stepper-motor bipolare ogni avvolgimento va al posto di un motore) e dellโ€™alimentazione della scheda.

Fig. 4 Collegamento di motori e alimentazione al controller OMC21.

 

Invece, nella Fig. 5 viene illustrato come impostare il ponticello 3V3/5V (in questo caso va lasciato completamente aperto) di selezione dellโ€™alimentazione del microcontrollore e della logica del driver LV8405V-D affinchรฉ venga prelevata direttamente dalla connessione USB; nella stessa figura i motori vengono alimentati da VM.

Fig. 5 Motori alimentati da VM e ATmega32U4 alimentato esternamente dalla logica di controllo.

 

La Fig. 6 mostra come impostare il ponticello se si desidera alimentare il circuito di potenza con VM e il microcontrollore e la logica del driver con i 3,3 volt ricavati dalla stessa VM tramite il regolatore U3 (il ponticello va realizzato chiudendolo con una goccia di stagno).

Fig. 6 Motori alimentati da VM e ATmega32U4 alimentato a 3,3V da VM.

 

Nella Fig. 7 รจ invece proposta lโ€™impostazione del ponticello ammettendo di alimentare il microcontrollore e la logica del driver con i 5 volt che il regolatore U2 ricava da VM (tensione dโ€™ingresso del circuito e di potenza).
E veniamo alle connessioni con Arduino Uno per il controllo seriale: le Fig. 8 e Fig. 9 riguardano rispettivamente la connessione via seriale TTL e quella tramite IยฒC-Bus.

Aggiungiamo ora alcune raccomandazioni per il corretto utilizzo di questo controller, tenendo conto di tutte le problematiche che si possano incontrare allโ€™atto pratico nellโ€™utilizzo dei motori a spazzole.

Fig. 7 Motori alimentati da VM e ATmega32U4 alimentato a 5V da VM.

 

Fig. 8 OMC21 e logica di comando alimentati entrambi da VM e connessi in seriale ad Arduino Uno.

 

รˆ buona norma prima di collegare un motore verificare se la massima corrente assorbita (di solito chiamata corrente di stallo) non eccede il valore massimo consentito.

Unโ€™altra buona norma รจ di saldare direttamente sui contatti del motore tre condensatori ceramici del valore compreso tra 10 nF e 100 nF, con lo scopo di sopprimere i disturbi derivati dallo strisciamento delle spazzole sul collettore. I condensatori vanno saldati tra i due terminali e la carcassa ed eventualmente anche uno tra i due terminali di alimentazione (vedere Fig. 10).

Fig. 9 OMC21 e logica di comando alimentati entrambi da VM e connessi tramite I2C ad Arduino Uno.

 

Fig. 10 Utilizzo dei condensatori come soppressori dei disturbi su un motore a spazzole.

 

Per concludere lโ€™articolo, riportiamo anche un esempio pratico di utilizzo del nostro controller utilizzandolo in sostituzione della circuiteria elettronica guasta in una piccola automobilina RC. In questo esempio utilizziamo lโ€™OMC21 per leggere i segnali provenienti da un ricevitore RC, di quelli usati in ambito modellistico, e comandare il motore dellโ€™automobilina.

La ricevente รจ alimentata dallo stesso OMC grazie allo stabilizzatore di tensione interno impostato sui 5V. Il servo per lo sterzo รจ controllato direttamente dalla ricevente RC. Lโ€™alimentazione giunge da una piccola batteria LiPo connessa direttamente ad OMC21.

Il programma da inserire sul controller si chiama esc_rc_car2.ino e prevede anche una funzione di diagnostica grazie alla quale su serial monitor รจ possibile visualizzare i dati ricevuti dalla ricevente RC (Fig. 11).

Fig. 11 Dati ricevuti dalla ricevente RC.

 

Il programma รจ molto semplice e si basa sulla lettura della durata dellโ€™impulso ricevuto dalla ricevente RC grazie alla funzione pulseIn di Arduino; da questa lettura รจ poi sufficiente ricavare il giusto valore del duty-cycle per il comando dei motori. Per il resto sono state usate le funzioni giร  precedentemente descritte, con in aggiunta la lettura della tensione della batteria, impostando lo spegnimento motore (cut-off), non appena questa scenda al di sotto dei 6V, al fine di salvaguardare la batteria di alimentazione.

Lascia un commento

Il tuo indirizzo email non sarร  pubblicato.

Menu