PID programable a traves de un modulo bluetooth

Dependencies:   BufferedSerial QEI TextLCD mbed

main.cpp

Committer:
andJdmat
Date:
2016-11-30
Revision:
0:acd6b856d63c

File content as of revision 0:acd6b856d63c:

#include "mbed.h"
#include "QEI.h"
#include "TextLCD.h"
#include "iostream"
#include "stdio.h"
#include "string"
#include "stdlib.h"
#include <BufferedSerial.h>

TextLCD lcd(PTB10, PTB11, PTE2, PTE3, PTE4, PTE5, TextLCD::LCD20x4); // rs, e, d4-d7 Teclado
//asignamos el puerto a cada interruptor
QEI encoder (PTA13, PTD5, NC, 624, QEI::X4_ENCODING);
Serial GSM(PTE0,PTE1);
AnalogIn y(PTB3);//entrada analoga
AnalogOut u(PTE30);//salida analoga OJO solo se le pueden drenar 1.5mA en circuitos use un Buffer
//si se ignora esto se arruina la FRDMKL25Z
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
 
DigitalIn button3(PTC16);//cambia ingreso de  los 4 parametros
DigitalIn button4(PTC17);//termina y consolida valores de 4 parametros y sale del loop

Serial pc(USBTX, USBRX); // tx, rx
Serial device(PTE0, PTE1);  // tx, rx
//device.baud(115200); 
 
 
//codigos movimiento del curzor
 
//int C1=0x0E; // solo muestra el curzor
int C2=0x18; // desplaza izquierda
int C3=0x1A; // desplaza derecha
int C4=0x0C; // quito cursor bajo
 
int C1=0x0F;
int cambio=0, diferencia=0;
// se cambio de float a entero

float pid,o,ai,ad,ap,med,err;
float err_v;

// Valores de k y de j
int j=0;
int k=0;

// fin del cambio
int spnum=0,kinum=0,kpnum=0,kdnum=0,pos=1;
char buffer[128];
char buffer2[128];
char salidas[32];
char err_s[3];
char spnum_s[3];
char med_s[3];
char co_s[3];
Timer t;
int l;


// Inicio de modificaciones, en esta parte se agregaron funciones que permiten imprimir datos en la lcd que envia
// el modulo bluetooth, el codigo fue depurado usando la comunicacion serial. 
char* itoa(int value, char* result, int base)     // Funcion para convertir enteros a cadenas de texto, fue importada de un foro                                                                                                     
{                                                                                                                                                        
    // check that the base if valid                                                                                                                      
    if ( base < 2 || base > 36 ) {                                                                                                                       
        *result = '\0';                                                                                                                                  
        return result;                                                                                                                                   
    }                                                                                                                                                    
 
    char* ptr = result, *ptr1 = result, tmp_char;                                                                                                        
    int tmp_value;                                                                                                                                       
 
    do {                                                                                                                                                 
        tmp_value = value;                                                                                                                               
        value /= base;                                                                                                                                   
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];                             
    } while ( value );                                                                                                                                   
 
    // Apply negative sign                                                                                                                               
    if ( tmp_value < 0 )                                                                                                                                 
    *ptr++ = '-';                                                                                                                                    
    *ptr-- = '\0';                                                                                                                                       
 
    while ( ptr1 < ptr ) {                                                                                                                               
    tmp_char = *ptr;                                                                                                                                 
    *ptr-- = *ptr1;                                                                                                                                  
    *ptr1++ = tmp_char;                                                                                                                              
    }                                                                                                                                                    
 
    return result;                                                                                                                                       
}
 

int readBuffer(char *buffer,int count)   //esta funcion lee un bufer de datos
{
    int i=0; 
    t.start();    //CUENTA EL TIEMPO DE CONEXION E INICIA
    while(1) {
      while (device.readable()) {
            char c = device.getc();
            //if (c == '\r' || c == '\n') c = '$';//si se envia fin de linea o de caracxter inserta $
            buffer[i++ - 1] = c;//mete al bufer el caracter leido
            if(i > count)break;//sale del loop si ya detecto terminacion
        }
        if(i > count)break;
        if(t.read() > 1) {  //MAS DE UN SEGUNDO DE ESPERA SE SALE Y REINICA EL RELOJ Y SE SALE
            t.stop();
            t.reset();
            break;
        }
    }   
     return 0;
}
 
void cleanBuffer(char *buffer, int count)  //esta funcion limpia el bufer
{
    for(int i=0; i < count; i++) {
        buffer[i] = '\0';
    }
}

int tamano(char *buffer)
{
int tam = 0;
    while (buffer[tam] != '\0')
    {
        tam++;    
    }
    return tam;
}

void verificacion(char *buffer) // Esta funcion fue creada para esta aplicacion especifica, permite verificar si los datos que entraron a la freescale
// son los esperados y adicionalmente crea un nuevo buffer con los datos para imprimir.
{
    int l = tamano(buffer);
    buffer2[0] = '-';
    if (l < 16)
    {
        if(buffer[0]=='\0')
        {
            for (int i = 0; i < 16; i++)
                {
                    buffer2[i] = '0';
                }
        }
        else 
        {         
            int k = 0;
            int j = 0;
            for(int i=0; i < 15; i++) 
            {
                if(j == 1)
                {
                    if(buffer[i+1]=='-')
                    {
                        j = 0;
                    }
                    else if (buffer[i+2]=='-')
                    {
                        j = 0;
                        i = i+1;
                    }
                    else if (buffer[i+3]=='-')
                    {
                        j = 0;
                        i = i+2;
                    }
                    else if(buffer[i+4]=='-')
                    {
                        j = 0;
                        i = i+3;                 
                    }
                }

                else
                {       
                    if(buffer[i+1]=='-')
                    {
                        buffer2[k + 1] = '0';
                        buffer2[k + 2] = '0';
                        buffer2[k + 3] = '0';
                        buffer2[k + 4] = '-';
                        k = k + 4;
                        j = 1;
                    }
                else if (buffer[i+2]=='-')
                    {
                        buffer2[k + 1] = '0';
                        buffer2[k + 2] = '0';
                        buffer2[k + 3] = buffer[i+1];
                        buffer2[k + 4] = '-';
                        k = k + 4;
                        j = 1;
                    }
                else if (buffer[i+3]=='-')
                    {
                        buffer2[k + 1] = '0';
                        buffer2[k + 2] = buffer[i+1];
                        buffer2[k + 3] = buffer[i+2];
                        buffer2[k + 4] = '-'; 
                        k = k+4;
                        j = 1;
                    }
                else if(buffer[i+4]=='-')
                    {
                        buffer2[k + 1] = buffer[i+1];
                        buffer2[k + 2] = buffer[i+2];
                        buffer2[k + 3] = buffer[i+3];
                        buffer2[k + 4] = '-';
                        k = k+4;
                        j =1;                 
                    }
                }
            }
        }  
    }
    else
    {
        for (int i = 0; i < 16; i++)
        {
            buffer2[i] = buffer[i];
        }
    }
}
// Fin de la modificacion para la impresion por bluetooth
int main()
{
    lcd.locate(0,1);
    lcd.printf("**Control PID**");
    wait(2);
    lcd.cls(); // Borrar Pantalla
    lcd.writeCommand(C1);//escribimos un comando segun el manual del modulo LCD
 
    lcd.locate(8,0);
    lcd.printf("Kp=%d",kpnum);
    lcd.locate(0,1);
    lcd.printf("Ki=%d",kinum);
    lcd.locate(8,1);
    lcd.printf("Kd=%d",kdnum);
    lcd.locate(0,0);
    lcd.printf("Sp=%d",spnum);
 
    while(1)
    {
        //lcd.locate(8,0);
        //lcd.printf("Kp=%d",encoder.getPulses());
        //wait(.5);
        
        if(device.readable()) // Se comprueba si ha datos para leer y se imprimen.
            {   
        
        cleanBuffer(buffer2,128);
        cleanBuffer(buffer,128);
        readBuffer(buffer,128);
        if (buffer[0] == 'p'){break;}
        pc.printf("buffer= %s\n\r ",buffer);  //imprime el bufer
        verificacion(buffer);
        pc.printf("buffer2= %s\n\r ",buffer2);  //imprime el buffer reconstruido
        pc.printf("tamano buffer= %d \n\r",l);  //imprime el tamaño
        pc.printf("Sp= %c %c %c\n\r ",buffer2[1],buffer2[2],buffer2[3]);
        pc.printf("Kp= %c %c %c\n\r ",buffer2[5],buffer2[6],buffer2[7]);
        pc.printf("Ki= %c %c %c\n\r ",buffer2[9],buffer2[10],buffer2[11]);
        pc.printf("Kd= %c %c %c\n\r ",buffer2[13],buffer2[14],buffer2[15]);
        spnum = 1*(buffer2[3]-48)+ 10*(buffer2[2]-48)+ 100*(buffer2[1]-48);
        
        lcd.locate(3,0);
        lcd.printf("     ");
        lcd.locate(3,0);
        lcd.printf("%d", spnum);
        kpnum = 1*(buffer2[7]-48)+ 10*(buffer2[6]-48)+ 100*(buffer2[5]-48);
        lcd.locate(11,0);
        lcd.printf("     ");
        lcd.locate(11,0);
        lcd.printf("%d", kpnum);
        kinum = 1*(buffer2[11]-48)+ 10*(buffer2[10]-48)+ 100*(buffer2[9]-48);
        lcd.locate(3,1);
        lcd.printf("     ");
        lcd.locate(3,1);
        lcd.printf("%d", kinum);
        kdnum = 1*(buffer2[15]-48)+ 10*(buffer2[14]-48)+ 100*(buffer2[13]-48);
        lcd.locate(11,1);
        lcd.printf("     ");
        lcd.locate(11,1);
        lcd.printf("%d", kdnum);
        cleanBuffer(buffer2,128);
        cleanBuffer(buffer,128);          
            }
        else{
        
        diferencia=encoder.getPulses()-cambio;
        cambio=encoder.getPulses();
 
        if (diferencia==0)
        {
            //nada
        }
        else if(diferencia>0)
        {
            if(pos==1)
            {
                if(spnum+diferencia>=999)
                {
                    spnum=999;
                    lcd.locate(3,0);
                    lcd.printf("    ");
                    lcd.locate(3,0);
                    lcd.printf("%d", spnum);
                }
                else
                {
                    spnum+=diferencia;
                    lcd.locate(3,0);
                    lcd.printf("%d", spnum);
                }
            }
            else if(pos==2)
            {
                if(kpnum+diferencia>=999)
                {
                    kpnum=999;
                    lcd.locate(11,0);
                    lcd.printf("    ");
                    lcd.locate(11,0);
                    lcd.printf("%d", kpnum);
                }
                else
                {
                    kpnum+=diferencia;
                    lcd.locate(11,0);
                    lcd.printf("%d", kpnum);
                }
            }
            else if(pos==3)
            {
                if(kinum+diferencia>=999)
                {
                    kinum=999;
                    lcd.locate(3,1);
                    lcd.printf("    ");
                    lcd.locate(3,1);
                    lcd.printf("%d", kinum);
                }
                else
                {
                    kinum+=diferencia;
                    lcd.locate(3,1);
                    lcd.printf("%d", kinum);
                }
            }
            else if(pos==4)
            {
                if(kdnum+diferencia>=999)
                {
                    kdnum=999;
                    lcd.locate(11,1);
                    lcd.printf("    ");
                    lcd.locate(11,1);
                    lcd.printf("%d", kdnum);
                }
                else
                {
                    kdnum+=diferencia;
                    lcd.locate(11,1);
                    lcd.printf("%d", kdnum);
                }
            }
        }
        
        else if(diferencia<0)
        {
            if(pos==1)
            {
                if(spnum+diferencia<0)
                {
                    //No ocurre nada
                }
                else
                {
                    spnum+=diferencia;
                    lcd.locate(3,0);
                    lcd.printf("    ");
                    lcd.locate(3,0);
                    lcd.printf("%d", spnum);
                }
            }
            else if(pos==2)
            {
                if(kpnum+diferencia<0)
                {
                    //No ocurre nada
                }
                else
                {
                    kpnum+=diferencia;
                    lcd.locate(11,0);
                    lcd.printf("    ");
                    lcd.locate(11,0);
                    lcd.printf("%d", kpnum);
                }
            }
            else if(pos==3)
            {
                if(kinum+diferencia<0)
                {
                    //No ocurre nada
                }
                else
                {
                    kinum+=diferencia;
                    lcd.locate(3,1);
                    lcd.printf("    ");
                    lcd.locate(3,1);
                    lcd.printf("%d", kinum);
                }
            }
            else if(pos==4)
            {
                if(kdnum+diferencia<0)
                {
                    //No ocurre nada
                }
                else
                {
                    kdnum+=diferencia;
                    lcd.locate(11,1);
                    lcd.printf("    ");
                    lcd.locate(11,1);
                    lcd.printf("%d", kdnum);
                }
            }
         }   
    } 
        if (!button3)  //cambia la posicion de ingreso de parametros
        {
            led3 =!led3;
            if(pos==4)
            {
                pos=1;
                lcd.locate(3,0);
                lcd.printf("%d", spnum);
            }
            else if (pos==1)
            {
                pos++;
                lcd.locate(11,0);
                lcd.printf("%d", kpnum);
            }
            else if(pos==2)
            {
                pos++;
                lcd.locate(3,1);
                lcd.printf("%d", kinum);
            }
            else if(pos==3)
            {
                pos++;
                lcd.locate(11,1);
                lcd.printf("%d", kdnum);
            }
            wait(0.25);
 
        }
 
        if (!button4)
        {
            break;     //sale del bucle si pisan suiche4
        }
        wait(0.1);        
    }
 
 
//Transicion
    lcd.writeCommand(C4);//escribimos un comando segun el manual del modulo LCD para quitar cursor bajo
    lcd.cls(); //borra la pantalla
    lcd.printf("   GUARDADOS!");
    wait(1);
    lcd.cls();
    lcd.printf(" INICIA EL PID");
    wait(1);
// se imprimen los parches del control  *****************************************
    lcd.cls();
    lcd.printf("Er=%3.0f",err);
    lcd.locate(8,0);
    lcd.printf("Me=%3.0f",med);
    lcd.locate(0,1);
    lcd.printf("Sp=%3.0f",spnum);
    lcd.locate(8,1);
    lcd.printf("Co=%3.0f",pid);
    wait(1);
 
// CICLO PRINCIPAL CONTROLADOR PID
 lop1:  med = y.read()*999;
        err = (spnum-med);  //se calcula el error
        ap = kpnum*err*0.01f;     //se calcula la accion proporcinal
        ai =(kinum*err*0.01f)+ai;    //calculo de la integral del error
        ad = kdnum*(err-err_v)*0.01f; //calculo de la accion derivativa
        pid = (ap+ai+ad);
        // se verifica que pid sea positivo **************************************
        if(pid<=0)
        {
            pid=0;
        }
 
        // se verifica que pid sea menor o igual la valor maximo *****************
        if (pid > 999)
        {
            pid=999;
        }
 
       
        //se muestran las variables******************************************
            lcd.locate(3,0);
            lcd.printf("    ");
            lcd.locate(3,0);
            lcd.printf("%3.0f",err);
            lcd.locate(11,0);
            lcd.printf("   ");
            lcd.locate(11,0);
            lcd.printf("%3.0f",med);
            lcd.locate(3,1);
            lcd.printf("   ");
            lcd.locate(3,1);
            lcd.printf("%d",spnum);
            lcd.locate(11,1);
            lcd.printf("   ");
            lcd.locate(11,1);
            lcd.printf("%3.0f",pid);

        // Modificacion para enviar los datos por bluetooth
        
        
        cleanBuffer(err_s,3);
        cleanBuffer(spnum_s,3); 
        cleanBuffer(co_s,3);   
        cleanBuffer(med_s,3); 
        cleanBuffer(salidas,17);
        //pc.printf("error= %f\n\r ",err);
                
        char *r = ".";
        
        
        itoa(int(err),err_s,10);
        //pc.printf("error= %s\n\r ",err_s);
        strcpy(salidas, err_s);
        strcat(salidas, r); 
        
        itoa(int(spnum),spnum_s,10);
        //pc.printf("sp= %s\n\r ",spnum_s);
        strcat(salidas, spnum_s);
        strcat(salidas, r); 
        
        itoa(int(pid),co_s,10);
        //pc.printf("CO= %s\n\r ",co_s);
        strcat(salidas, co_s);
        strcat(salidas, r); 
        
        itoa(int(med),med_s,10);
        //pc.printf("med= %s\n\r ",med_s);
        strcat(salidas, med_s);
        strcat(salidas, r);   
        salidas[17]='.';   
        pc.printf("Salidas= %s\n\r ",salidas);
        
        
        device.puts(salidas);
        
        cleanBuffer(err_s,3);
        cleanBuffer(spnum_s,3); 
        cleanBuffer(co_s,3);   
        cleanBuffer(med_s,3); 
        cleanBuffer(salidas,17);
        /*
       if(err<256)
       {           //debo generar dos casos a APP inventor solo me recibe hex asi: 0xhhhh (4 cifras)    
           device.putc(0);     //si el numero es hasta 255 se le ponen dos ceros adelante a la secuencia de bits
           device.putc(err);     //luego la cifra menos significativa
       }
       if(err>255)
       {          //pero si es mayor a 255 las cifras deben ser convertidas a un hex de dos bytes de la siguiente forma   
           j=err/256;       //calculo la cifra mas significativa
           k=err-j*256;     //calculo la cifra menos significativa
           device.putc(j);   //las envio a la usart para que se las ponga al modulo bluetooth y la lleve al android
           device.putc(k);   //mas significativa primero, menos despues si no no funciona!!! y con la orden PUTC solo asi le envia binarios
       }   
        
       if(med<256)
       
       {           //debo generar dos casos a APP inventor solo me recibe hex asi: 0xhhhh (4 cifras)    
           device.putc(0);     //si el numero es hasta 255 se le ponen dos ceros adelante a la secuencia de bits
           device.putc(spnum);     //luego la cifra menos significativa
       }
       
       if(med>255)
        {          //pero si es mayor a 255 las cifras deben ser convertidas a un hex de dos bytes de la siguiente forma   
           j = 0;
           k = 0;
           j=med/256;       //calculo la cifra mas significativa
           k=med-j*256;     //calculo la cifra menos significativa
           device.putc(j);   //las envio a la usart para que se las ponga al modulo bluetooth y la lleve al android
           device.putc(k);   //mas significativa primero, menos despues si no no funciona!!! y con la orden PUTC solo asi le envia binarios
        }  
        */ // Fin de la modificacion
            
        //Normalizacion de la salida
        // se actualizan las variables *******************************************
        err_v = err;
        o = pid/999;
        u.write(o);
        //  se envia el valor pid a puerto analogico de salida (D/A) **************
        
        //  se repite el ciclo
        wait_ms(300);
        goto lop1;
}