Controllo passo/passo

con 16F876

Progetto PRC2010.

Questo semplice progetto è nato allo scopo di sostituire una vecchia scheda di controllo realizzata un ventennio fa con integrati logici CMOS, con un moderno microcontrollore che ne emula la logica tramite un programma. La programmazione è sviluppata in C per PIC 16 su piattaforma MPLAB.

Questo progetto esegue il controllo di un motore stepper bipolare con dati di targa compatibili all'alimentazione tramite il noto circuito integrato L298. L'impostazione del senso di marcia avviene tramite la chiusura di un interruttore posto sul pannello frontale indicato sullo schema elettrico con S22. L'impostazione della velocità avviene tramite il settaggio di tre digit su tre contraves. Personalmente ritengo questa soluzione piuttosto obsoleta e la sostituire con i due classici pulsanti Aumenta/diminuisci con visualizzazione dei parametri impostati su un display LCD, ma per compatibilità con il vecchio progetto si manterrà l'impostazione Elettromeccanica tramite contraves. IL connettore J1 è il punto di accesso dei tre Nibble abbinati ai contraves. Il collegamento avviene tramite resistenze di pull down. Il connettore J4 porta l'alimentazione del motore ad esempio 12V con 2A per avvolgimento. Il connettore J3 è il punto di collegamento al motore passo, ovvero ai 4 morsetti delle due bobine, cioè A,B,C,D. Tutte le resistenze escluse R61,R62, R18, sono da 10 Kohm, mentre R61,R62 sono da 1 Ohm 1/2 W e servono per prelevare una tensione analogica proporzionale alla corrente di indotto. R18 invece serve semplicemente al led di segnalazione di accensione, un buon valore potrebbe essere 1Kohm.

 

ll layout componenti risulta ben ordinato, come si può vedere dall'immagine sovrastante. Si nota che i diodi di ricircolo risultano molto robusti, fortemente ridimensionati rispetto alla scheda elettronica originale che in molte occasioni ha dimostrato sofferenza proprio in questo punto. I nuovi diodi scelti sono di tipo GI852 in tecnologia schottky.  I connettori non sono dei più comodi ma danno allacciabilità diretta con la versione precedente.

La sezione di potenza deve avere delle piste molto larghe dato che dovranno trasportare tutta la corrente che alimenta le bobine del motore. Un punto critico sarà la connessione del top con il bottom layer tramite fori metallizzati. Queste "Vias Pad" o fori metallizzati passanti, sono stati rinforzati e li possiamo vedere nel layout componenti sopra a R17 e all'interno dell'impronta del diodo D7. Per una ulteriore sicurezza potremmo riempire questo foro di stagno in fase di montaggio o addirittura confermare la connessione sotto sopra saldando un pezzettino di reoforo  su ambo i lati.

Notiamo che le piste uscenti dal connettore J4, ovvero le alimentazioni di potenza sono molto robuste, come anche le 4 linee uscenti dal circuito integrato L298. Posteriormente a questo circuito intergrato non sono stati messi altri componenti per lasciare il necessario spazio all'ampio dissipatore di calore fondamentale per un prolungato e sicuro funzionamento.

Nel bottom layer (piste azzurre) vediamo che si è usato lo stesso spessore del top layer relativamente alla sezione di potenza, anche se le connessioni di questo tipo sono in numero più limitato. Rimangono da descrivere pochissimi altri componenti. Il ponte di diodi è da 1 ampere, ovvero il modello piccolo tondo, visto che dovrà alimentare solo la logica. Il gruppo oscillatore è il classico ponte a pigreco costituito da un quarzo da 20Mhz e due piccoli condensatori ceramici da 18pF. 

scarica il progetto Eagle schemi board e documentazione

 

scarica i file costruttivi gerber del progetto PRC2010

L'anello mancante tra il disegno CAD e la realizzazione professionale sono i file costruttivi gerber. Questi si ottengono dall'editor PCB di eagle agendo sul tasto CAM. Successivamente agire su open job e il resto sarà intuitivo.

Descrizione del funzionamento.

Il funzionamento di questo dispositivo è piuttosto semplice. Sul pannello frontale ci sono 4 digit impostabili tramite contraves che settano la velocità. Un interruttore imposta il verso di rotazione. Un altro interruttore energizza il tutto. Entrando più sul tecnico dobbiamo ricordare che un motore passo passo entra in rotazione seguendo dei comandi digitali codificati in stringhe di quattro bit. Chiameremo l'insieme delle 4 configurazioni possibili di questa stringa la matrice di passo intero. L'interruttore che seleziona il verso di rotazione decide in realtà da che parte sarà letta ed eseguita la matrice di passo. I bit assumo significato a coppie, ad esempio la prima coppia  posta a 1-0 indica che la corrente scorrente nella prima bobina da A verso B, mentre la coppia 0-1 indica che scorre da B verso A. Analogamente per i secondi due bit  e per a seconda bobina.

Matrice di passo intero

A B C D
1 0 1 0
0 1 1 0
1 0 0 1
0 1 0 1

Oltre alla matrice di passo intero sopra riportata esiste la la matrice di mezzo passo che allo stesso motore permette un avanzamento più risoluto anche se ad una velocità ridotta come minore risulta anche la coppia motrice disponibile all'asse. Sostanzialmente il nostro programma in C dovrà generare agli opportuni pin del processore i bit che corrispondono alla matrice di passo. 

 

Matrice di mezzo passo

A B C D
1 0 1 0
0 0 1 0
0 1 1 0
0 1 0 0
0 1 0 1
0 0 0 1
1 0 0 1
1 0 0 0

Si nota facilmente che nella matrice di mezzo passo le righe raddoppiano, il motore impiega il doppi di cicli di clock per eseguire la matrice. Dipenderà dal numero di poli del motore in quanti step viene eseguita la rotazione completa.

Verso di rotazione.

Il verso di rotazione è imposto dal verso di lettura della matrice di passo e quindi dalla generazione della stessa sui 4 pin corrispondenti del microprocessore.  La prima riga della matrice di passo potrà essere generata dal comando PORTA=0b00001010; Il registro tristato di controllo del PORT A dovrà essere preimpostato in modo che i primo 4 bit siano uscite "0" e il sesto un ingresso di tipo analogico "1". il corrispondente comando sarà  TRISA=0b100000; il pin che corrisponde a RA4 si decide di lasciarlo libero perchè assegnato ad una funzione hardware del processore che qui non è usata (tock). 

Velocità di rotazione.

La velocità di rotazione è definita dalla velocità di lettura ed esecuzione della ,matrice di passo. Nel progetto originale questa era impostata da un'onda quadrata generata da un circuito integrato di tipo NE555, il famoso timer che genera un segnale di clock la cui frequenza è fissata da un gruppo R-C. questo clock sarà emulato nel programma in "C" tramite la funzione DelayMs(10).  Il numero 10 provvisoriamente inpostato tra parentesi corrisponde ad un valore in millisecondi.  

In questa foto vediamo il PCB montato (a meno dei connettori), Al morsetto di alimentazione potremmo collegare indifferente una continua o una alternata purchè stia in un range di tensioni ragionevole, ad esempio 12 o 15 volt AC. Se applichiamo una tensione continua non dovremmo preoccuparci della polarità perchè a raddrizzarla ci pensa il ponte di diodi.

PRC2010_project_overwiev

Lista delle attribuzioni degli ingressi

proxy           RC4

CW/ACW   RC5

D0_b0        RB0
D0_b1        RB1
D0_b2        RB2
D0_b3        RB3

D1_b0        RB4
D1_b1        RB5
D1_b2        RB6
D1_b3        RB7

D2_b0        RC0
D2_b1        RC1
D2_b2        RC2
D2_b3        RC3

Lista delle attribuzioni delle uscite

A                   RA0
B                   RA1
C                   RA2
D                   RA3

scarica la lista delle attribuzioni

Bozza del programma per PIC micro 16F876A

//scarica la librerie delay.h   e  delay.c

/*************************************

*                        PIC 16F876A                         *

          controllo motore passo passo               *

*                     Sisma  PRC2010                        *

*                     prof Gottardo Marco                  *

*************************************/

 

//Nota: settare i pulsanti del PIC_Simulator normal=0 pressed=1.

 

#include <pic.h>

#include <delay.h>

#include <math.h>

 

 #define  ruotaHALFACW  RC7     //interruttore al pin 18  pic 16F876

#define  ruotaHALFCW  RC6     //interruttore al pin 17  pic 16F876

#define  ruotaCW  RC5     //interruttore al pin 16  pic 16F876

#define  proxy  RC4     //sensore di prossimità monostabile al pin 15  pic 16F876

 

#define  D0_b0        RB0     //pulsante al pin 21 pic 16F876

#define  D0_b1        RB1      //pulsante al pin 22 pic 16F876

#define  D0_b2        RB2    //pulsante al pin 23  pic 16F876

#define  D0_b3        RB3     //pulsante al pin 24 pic 16F876

 

#define  D1_b0        RB4     //pulsante al pin 25 pic 16F876

#define  D1_b1        RB5      //pulsante al pin 26 pic 16F876

#define  D1_b2        RB6    //pulsante al pin 27  pic 16F876

#define  D1_b3        RB7     //pulsante al pin 28  pic 16F876

 

#define  D2_b0        RC0     //pulsante al pin 11 pic 16F876

#define  D2_b1        RC1     //pulsante al pin 12 pic 16F876

#define  D2_b2        RC2    //pulsante al pin 13  pic 16F876

#define  D2_b3        RC3     //pulsante al pin 14  pic 16F876

int CONTA=0;

int A=0; //azzero la variabile conta

 

void Full_CW(){

                        while(ruotaCW==1) //doppio uguale per confrontare

                        {  //implementa la matrice di passo intero 10,6,5,9

                        PORTA=10;

                        DelayMs(200);

                        PORTA=6;

                        DelayMs(200);

                        PORTA=5;

                        DelayMs(200);

                        PORTA=9;

                        DelayMs(200);

                        }

}

 

void Full_ACW(){

                        while(ruotaACW==1) //doppio uguale per confrontare

                        { //implementa la matrice di passo intero 9,5,6,10 inversa

                        PORTA=9;

                        DelayMs(200);

                        PORTA=5;

                        DelayMs(200);

                        PORTA=6;

                        DelayMs(200);

                        PORTA=10;

                        DelayMs(200);

                        }

}

 

void    Half_CW(){

                        while(ruotaHALFCW==1) //doppio uguale per confrontare

                        {//implementa la matrice di mezzo passo 10,2,6,4,5,1,9 considerati in binario formano la matrice di passo

                        PORTA=10;

                        DelayMs(200);

                        PORTA=2;

                        DelayMs(200);

                        PORTA=6;

                        DelayMs(200);

                        PORTA=4;

                        DelayMs(200);

                        PORTA=5;

                        DelayMs(200);

                        PORTA=1;

                        DelayMs(200);

                        PORTA=9;

                        DelayMs(200);

                        PORTA=8;

                        DelayMs(200);

                        }

}

 

void    Half_ACW(){

                        while(ruotaHALFACW==1) //doppio uguale per confrontare

                        {//implementa la matrice inversa di mezzo passo 9,1,5,4,6,2,10

                         PORTA=8;

                        DelayMs(200);

                        PORTA=9;

                        DelayMs(200);

                        PORTA=1;

                        DelayMs(200);

                        PORTA=5;

                        DelayMs(200);

                        PORTA=4;

                        DelayMs(200);

                        PORTA=6;

                        DelayMs(200);

                        PORTA=2;

                        DelayMs(200);

                        PORTA=10;

                        DelayMs(200);

                        }

}

 

void main (void){

            TRISA=0b100000;

            TRISB=0f11111111;

            TRISC=0b11111111;

//settaggio port A come output (tranne RA5 che sarà ingresso analogico) e port B e C come input

 

while (1)

            {

            if (ruotaCW==1)

                        {

                        DelayMs(80);

                        Full_CW();

                        PORTB=0x00;           

                        CONTA++;

                        //PORTB=CONTA;

                        }

            if (ruotaCW==0)

                        {

                        DelayMs(80);

                        Full_ACW();

                        PORTB=0x00;           

                        }

            if (ruotaHALFCW==1)

                        {

                        DelayMs(80);

                        Half_CW();

                        PORTB=0x00;

                        }

            if (ruotaHALFACW==1)

                        {

                        DelayMs(80);

                        Half_ACW();

                        PORTB=0x00;

                        }

            }

}

 

Nell'immagine successiva vediamo la prima bozza del lavoro svolto alla lavagna alla Sisma venerdì 30 aprile 2010.

  Pagina precedente