viernes, 6 de junio de 2014

Mover dos motores paso a paso con Matlab y Arduino por el puerto serie

Como me ha costado bastante comunicarme por el puerto serie desde Matlab a Arduino UNO y viceversa, lo comparto por si a alguien más le sirve.

La idea es configurar mi Arduino para que mueva dos motores paso a paso. Estos motores llevan además una tarjeta EasyDriver para controlar la etapa de potencia. Los motores en mi caso están conectados a dos rotadores, que llevan un limit switch cada uno para chequear el paso por 0º en cada vuelta. Un tornillo fijo pisará ese limit switch cada vez que pase por 0º.

DC 5V Deceleration Stepper Motor Module


EasyDriver V4.4 Stepper Motor Driver Board for Arduino (Works with Official Arduino Boards)


La función de Matlab es arduino(motor, pasos, reset).

motor:    puede ser 1 o 2, en función del motor que queramos mover
pasos:    número de pasos que queremos avanzar.
reset:     puede ser 0 o 1. 

Si reset está a 1, movemos el motor que le hayamos indicado hasta que toque el limit switch.
Si reset está a 0, movemos el motor los pasos que le hemos indicado.

%Funciona con motor_matlab.ino
function arduino(motor, pasos, reset)
ports=instrfind();
if ~isempty(ports)
    fclose(ports);
end
s = serial('COM4');
set(s,'Baudrate',9600); % se configura la velocidad a 9600 Baudios
set(s,'StopBits',1); % se configura bit de parada a uno
set(s,'DataBits',8); % se configura que el dato es de 8 bits, debe estar entre 5 y 8
set(s,'Parity','none'); % se configura sin paridad
set(s,'Terminator','CR/LF');% ìcî caracter con que finaliza el envÌo

flushoutput(s); % Limpiamos el buffer
flushinput(s); % Limpiamos el buffer

fopen(s);

pasos_aux=dec2bin(pasos,16);
pasos_hi=bin2dec(pasos_aux(1:8));
pasos_lo=bin2dec(pasos_aux(9:16));

mat=[motor pasos_hi pasos_lo reset];

c=fscanf(s); % Limpio el buffer

fwrite(s, mat, 'uint8', 'sync');

pasos_2 = fscanf(s,'%s');

LS1='0';
LS2='0';
i=1;

if reset==0
    
    while i<=pasos
        LS1 = fscanf(s,'%s');
        LS2 = fscanf(s,'%s');
        cont= fscanf(s,'%s');
        
        str= [LS1 '   ' LS2 '   ' cont];
        
        disp(str);
        i=i+1;
    end
    
elseif motor==1
    while LS1=='0'
        LS1 = fscanf(s,'%s');
        LS2 = fscanf(s,'%s');
        cont= fscanf(s,'%s');
        
        str= [LS1 '   ' LS2 '   ' cont];
        
        disp(str);
        i=i+1;
    end
    
elseif motor==2
        while LS2=='0'
        LS1 = fscanf(s,'%s');
        LS2 = fscanf(s,'%s');
        cont= fscanf(s,'%s');
        
        str= [LS1 '   ' LS2 '   ' cont];
        
        disp(str);
        i=i+1;
    end
    
end
fclose(s);


 y el sketch en Arduino es este:


//---------------------------------------------------------------------
// motor_matlab.ino
//---------------------------------------------------------------------
//Sketch de arduino 1 para mover el motor 1 o el 2 los pasos que se le 
// indiquen o bien resetear el motor indicado
//---------------------------------------------------------------------
// Inicialización de pines
int dirpin1 = 3;   // Motor 1: dirección y pasos
int steppin1 = 2;  

int dirpin2 = 5;  // Motor 2: dirección y pasos
int steppin2 = 4;  

//limit switch
int PW01 = 11;
int PW02 = 12;

int PW1 = 8;
int PW2 = 9;

int SW1 = 10;
int SW2 = 13;

// Variables:
int motor = 0;
int motor_s = 0;         
int pasos_hi = 0; 
int pasos_lo = 0; 
int pasos;
int reset = 0;
int reset_s = 0;

int buttonState1=0;
int buttonState2=0;

int contador=0;
int i=0;

String myStr_hi;
String myStr_lo;
String myStr;
String motor_str;
String reset_str;

void setup()
{
  Serial.begin(9600);
  
  //PaP
  pinMode(dirpin1, OUTPUT);
  pinMode(steppin1, OUTPUT);
  pinMode(dirpin2, OUTPUT);
  pinMode(steppin2, OUTPUT);

  //limit switch
  pinMode(PW1, OUTPUT);      
  pinMode(PW2, OUTPUT);      
  pinMode(PW01, OUTPUT);
  pinMode(PW02, OUTPUT);
  pinMode(SW1, INPUT);  
  pinMode(SW2, INPUT);
     
  digitalWrite(PW1, HIGH); // Tienen que estar a 5V  
  digitalWrite(PW2, HIGH);
  digitalWrite(PW01, LOW); // Tienen que estar a 0V
  digitalWrite(PW02, LOW); 
  
  digitalWrite(dirpin1, HIGH);     // Dirección del PaP
  delay(100);
  digitalWrite(dirpin2, HIGH);     // Dirección del PaP
  delay(100);
 
}

void loop()
{
        if (Serial.available() > 0) 
        {
  // lee los 4 bytes entrantes: [motor pasos_hi pasos_lo reset]
   motor = Serial.read();
                delay(100);
                
                pasos_hi = Serial.read();
                delay(100);

                pasos_lo = Serial.read(); 
                delay(100);
                
                reset = Serial.read(); 
                delay(100);
          
                Serial.flush();
                delay(1);
           
                // Paso los bytes de decimal a binario
                
                myStr_hi = dec2bin8(pasos_hi);
                myStr_lo = dec2bin8(pasos_lo);
                
                // Concateno el byte superior con el inferior
                
                myStr = myStr_hi + myStr_lo;
                
                // paso la cadena de binario a decimal
                
                pasos=bin2dec(myStr,16);
                
                Serial.println(pasos, DEC);
                  if (motor==1)
                   {
                      if (reset==1){
                        
                           do {
                             digitalWrite(steppin1, LOW);  // Inicia el PaP
                             digitalWrite(steppin1, HIGH); 
                             delayMicroseconds(200); 
                             buttonState1 = digitalRead(SW1); // Mira el limit switch 1
                             delay(1);
                             buttonState2 = digitalRead(SW2); // Mira el limit switch 2
                             delay(1);
                             i++;
                             Serial.println(buttonState1);
                             delay(1);
                             Serial.println(buttonState2);
                             delay(1);
                             Serial.println(i);
                           }
                           while (buttonState1 == 0); 
                            
                      }
                      

                      else{
                          do{
                        
                             digitalWrite(steppin1, LOW);  
                             digitalWrite(steppin1, HIGH); 
                             delayMicroseconds(200); 
                             buttonState1 = digitalRead(SW1);
                             delay(1);
                             buttonState2 = digitalRead(SW2);
                             delay(1);
                             i++;
                             Serial.println(buttonState1);
                             delay(1);
                             Serial.println(buttonState2);
                             delay(1);
                             Serial.println(i);
                      
                           }while (i<pasos);
                        
                      
                       }
                   
                   }

                   else
                   {
                      if (reset==1){
                        
                           do {
                             digitalWrite(steppin2, LOW);  
                             digitalWrite(steppin2, HIGH); 
                             delayMicroseconds(200); 
                             buttonState1 = digitalRead(SW1);
                             delay(1);
                             buttonState2 = digitalRead(SW2);
                             delay(1);
                             i++;
                             Serial.println(buttonState1);
                             delay(1);
                             Serial.println(buttonState2);
                             delay(1);
                             Serial.println(i);                           
                           }while (buttonState2 == 0); 
                          
                      
                      }
                      else{
                          do{
                        
                             digitalWrite(steppin2, LOW);  
                             digitalWrite(steppin2, HIGH); 
                             delayMicroseconds(200);
                             buttonState1 = digitalRead(SW1);
                             delay(1);
                             buttonState2 = digitalRead(SW2);
                             delay(1);
                             i++;
                             Serial.println(buttonState1);
                             delay(1);
                             Serial.println(buttonState2);
                             delay(1);
                             Serial.println(i);                     
                          }while (i<pasos);
                      }
                    }
                   
        } 
}
// Para pasar de decimal a binario de 8 bits en arduino uno
String dec2bin8(int myNum)
{

  int zeros = 8 - String(myNum,BIN).length();
  String myStr;
  for (int i=0; i<zeros; i++) {
    myStr = myStr + "0";
  }
  myStr = myStr + String(myNum,BIN);         

  delay(1000);
  
  return myStr;
}
// Para pasar de binario a decimal
int bin2dec(String orig, int tam){
  int result = 0;
  for (int i=0;i<tam;i++){
    result = result*2;
    result += (orig[i]-48);
    //Serial.println(i);
    //Serial.println(result);
    
  }
  return result;
}



Ya sabéis, primero cargáis el sketch de Arduino y lo compiláis. Después, solo tenéis que ejecutar el script de Matlab. 

Y nada más, espero que os sirva para jugar con vuestros arduinos.

¡Hasta otra!

5 comentarios:

Unknown dijo...

Seria de gran ayuda si agregaras el diagrama de coneccion.

Unknown dijo...

LOS LINKS ESTÁN CAIDOS

Unknown dijo...

ME INTERESA TU AYUDA

Unknown dijo...

Me interesa quiero saber como hacer q regrese..

María dijo...

Perdonad, tenía abandonado el blog y no vi vuestros comentarios. Ya he reparado los links.

¡Saludos!