Mostrando entradas con la etiqueta Serial. Mostrar todas las entradas
Mostrando entradas con la etiqueta Serial. Mostrar todas las entradas

miércoles, 29 de diciembre de 2010

Control de Servomotores con SDCC- Original de RedPIC Parte 2

Bueno después de mucho trabajar, por fin creo que ya funca esta versión del programa realizado por Redpic, pero en SDCC, como características tiene las siguientes:

* Comunicación por el puerto RS232 a 57600bps, pero puede aumentarse a 115200bps
* La forma de control de los servos es secuencial, lo que no permite mover dos servos de forma simultánea.
* El formato de instrucción es [servo][valor en grados][velocidad]
-Para servo usamos un byte char [a|b|c|d|e|f]
-Para valor en grados usamos tres bytes ejemplos [090] [001] [175] 90°, 1°, y 175° respectivamente
* Envia códigos de error cuando son suministrados los datos por el puerto serial
Códigos de mensajes de error
0 -- Buffer lleno Se han enviado demasiados caracteres
1 -- turnPLus error no puedo mover servo seleccionado
2 -- turnMinus error no puedo mover servo seleccionado
3 -- commandProcess error o puedo elegir ese servo

Cuando el proceso termina satisfactoriamente se manda la cadena "ok"

Para definir los servos a mover, usamos las siguientes macros definidas al inicio del código

//Definiciones de servos
#define SERVO1 LATBbits.LATB0
#define SERVO2 LATBbits.LATB1
#define SERVO3 LATBbits.LATB2
#define SERVO4 LATBbits.LATB3
#define SERVO5 LATBbits.LATB4
#define SERVO6 LATBbits.LATB5
#define SERVO7 LATBbits.LATB6
#define SERVO8 LATBbits.LATB7

#define CSERVO1 TRISBbits.TRISB0
#define CSERVO2 TRISBbits.TRISB1
#define CSERVO3 TRISBbits.TRISB2
#define CSERVO4 TRISBbits.TRISB3
#define CSERVO5 TRISBbits.TRISB4
#define CSERVO6 TRISBbits.TRISB5
#define CSERVO7 TRISBbits.TRISB6
#define CSERVO8 TRISBbits.TRISB7

Una característica mas, es que no es necesario usar los 8 pines como salida, sino que podemos elegir mediante el "bit"
boolean SERVO1_ON = true;
boolean SERVO2_ON = true;
boolean SERVO3_ON = true;
boolean SERVO4_ON = true;
boolean SERVO5_ON = true;
boolean SERVO6_ON = true;
boolean SERVO7_ON = true;
boolean SERVO8_ON = true;

Si necesitamos usar dos servos, un servo o los 8, como gustes Very Happy, (Esto tambien es original del código de RedPIC)


/* ----------------------------------------------------------------------- */

/* Plantilla generada por Piklab */

/*

La configuracion del micro nos permite trabajar un con XT de 20MHZ

y pero usar el PLL con el propósito de alcanzar los 12MIPS



Códigos de mensajes de error

0 -- Buffer lleno  Se han enviado demasiados caracteres

1 -- turnPLus error  no puedo mover servo seleccionado

2 -- turnMinus error no puedo mover servo seleccionado

3 -- commandProcess error o puedo elegir ese servo



ok -- Proceso terminado correctamente

*/

#include <pic18f2550.h>

#include <delay.h>

#include <uart18f2550.c>

#include <stdlib.h>

#include <string.h>

/* ----------------------------------------------------------------------- */

/* Bits de configuración: adapte los parámetros a su necesidad */

code char at __CONFIG1L CONFIG1L = _PLLDIV_DIVIDE_BY_5__20MHZ_INPUT__1L & _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L & _USBPLL_CLOCK_SRC_FROM_96MHZ_PLL_2_1L;

code char at __CONFIG1H CONFIG1H = _OSC_HS__HS_PLL__USB_HS_1H & _FCMEN_ON_1H & _IESO_ON_1H;

code char at __CONFIG2L CONFIG2L = _PUT_ON_2L & _BODEN_ON_2L & _BODENV_4_2V_2L & _VREGEN_ON_2L;

code char at __CONFIG2H CONFIG2H = _WDT_DISABLED_CONTROLLED_2H & _WDTPS_1_32768_2H;

code char at __CONFIG3H CONFIG3H = _CCP2MUX_RC1_3H & _PBADEN_PORTB_4_0__CONFIGURED_AS_DIGITAL_I_O_ON_RESET_3H & _LPT1OSC_ON_3H & _MCLRE_MCLR_OFF_RE3_ON_3H;

code char at __CONFIG4L CONFIG4L = _STVR_ON_4L & _LVP_OFF_4L & _ENHCPU_OFF_4L & _BACKBUG_OFF_4L;

code char at __CONFIG5L CONFIG5L = _CP_0_OFF_5L & _CP_1_OFF_5L & _CP_2_OFF_5L & _CP_3_OFF_5L;

code char at __CONFIG5H CONFIG5H = _CPB_OFF_5H;

code char at __CONFIG6L CONFIG6L = _WRT_0_OFF_6L & _WRT_1_OFF_6L & _WRT_2_OFF_6L & _WRT_3_OFF_6L;

code char at __CONFIG6H CONFIG6H = _WRTC_OFF_6H & _WRTB_OFF_6H;

code char at __CONFIG7L CONFIG7L = _EBTR_0_OFF_7L & _EBTR_1_OFF_7L & _EBTR_2_OFF_7L & _EBTR_3_OFF_7L;

code char at __CONFIG7H CONFIG7H = _EBTRB_OFF_7H;



//Definiciones de servos

#define SERVO1 LATBbits.LATB0

#define SERVO2 LATBbits.LATB1

#define SERVO3 LATBbits.LATB2

#define SERVO4 LATBbits.LATB3

#define SERVO5 LATBbits.LATB4

#define SERVO6 LATBbits.LATB5

#define SERVO7 LATBbits.LATB6

#define SERVO8 LATBbits.LATB7



#define CSERVO1 TRISBbits.TRISB0

#define CSERVO2 TRISBbits.TRISB1

#define CSERVO3 TRISBbits.TRISB2

#define CSERVO4 TRISBbits.TRISB3

#define CSERVO5 TRISBbits.TRISB4

#define CSERVO6 TRISBbits.TRISB5

#define CSERVO7 TRISBbits.TRISB6

#define CSERVO8 TRISBbits.TRISB7



typedef enum{false = 0, true = 1} boolean;  //para definir variables booleanas



//boolean tuza = true;  este es solo un ejemplo

//Constantes para la definición de ventanas

const unsigned Ticks4WindowH = 0x75;

const unsigned Ticks4WindowL = 0x2F;

const unsigned Ticks4CenterH = 0x46;

const unsigned Ticks4CenterL = 0x4F;

const unsigned Ticks4MinimumH = 0x17;

const unsigned Ticks4MinimumL = 0x6F;

const unsigned Ticks4MaximumH = 0x6B;

const unsigned Ticks4MaximumL = 0xCF;

static unsigned int Ticks4NextInterruptH = 0xCF;

static unsigned int Ticks4NextInterruptL = 0x2C;





const unsigned Ticks4Window = 0x752F;

const unsigned Ticks4Minimum = 0x176F;

const unsigned Ticks4Center = 0x464F;

const unsigned Ticks4Maximum = 0x6BCF;

static unsigned int Ticks4NextInterrupt = 0xCF2C;

static unsigned int Servo_PWM[8];

static unsigned int tempom=0x0000;

static unsigned int tempo=0x0000;

static unsigned int tempol;

static unsigned int tempoh;



static unsigned int Servo_PWMH[8];

static unsigned int Servo_PWML[8];

static unsigned short Servo_Idx = 0;



boolean SERVO1_ON = true;

boolean SERVO2_ON = true;

boolean SERVO3_ON = true;

boolean SERVO4_ON = true;

boolean SERVO5_ON = true;

boolean SERVO6_ON = true;

boolean SERVO7_ON = true;

boolean SERVO8_ON = true;



//definicion de teclas

#define INTRO 0x0D

#define RETROCESO 0x08

#define ESCAPE 0x1B



boolean flag_Phase;

unsigned short j=0xFF;

unsigned int posI;



/*Seccion para la comunicacion en serial*/



#define  lenbuff 10



unsigned char xbuff=0x00;

unsigned char cbuff[lenbuff];

char rcvchar=0x00;

boolean flagcommand = false;



//variables para timers

   unsigned char CounterA;

   unsigned char CounterB;



//Prototipos

void init_board(void);

void EnableTimer1Interrupt(void);

void Tmr1Carga(unsigned char high, unsigned char low);

void initBuff(void);

void add2cbuff(unsigned char c);

void echosel(char c);

void command_process(void);

void delay_ms(int milis);

void delay_us(int milis);

unsigned int SelectServo(unsigned char Servo);

void turnPlus(int vueltas, unsigned char vel, unsigned char Servo);

void turnMinus(int vueltas, unsigned char vel,unsigned char Servo);



//Sección de interrupciones



static void isr_Tmr1() interrupt 1    //Esta es una interrupcion de alta prioridad

{

   PIE1bits.RCIE=0;  //deshabilitamos la interrupcion del puerto serie

   if(flag_Phase == 1)

   {

      if(Servo_Idx == 0 && SERVO1_ON) {SERVO1 = 1;}

      if(Servo_Idx == 1 && SERVO2_ON) {SERVO2 = 1;}

      if(Servo_Idx == 2 && SERVO3_ON) {SERVO3 = 1;}

      if(Servo_Idx == 3 && SERVO4_ON) {SERVO4 = 1;}

      if(Servo_Idx == 4 && SERVO5_ON) {SERVO5 = 1;}

      if(Servo_Idx == 5 && SERVO6_ON) {SERVO6 = 1;}

      if(Servo_Idx == 6 && SERVO7_ON) {SERVO7 = 1;}

      if(Servo_Idx == 7 && SERVO8_ON) {SERVO8 = 1;}

      Ticks4NextInterruptH = 0xFF - Servo_PWMH[Servo_Idx];

      Ticks4NextInterruptL = 0xFF - Servo_PWML[Servo_Idx];

      Tmr1Carga(Ticks4NextInterruptH,Ticks4NextInterruptL);

   }

  

   if(flag_Phase == 0)

   {

      if(Servo_Idx == 0 && SERVO1_ON) {SERVO1 = 0;}

      if(Servo_Idx == 1 && SERVO2_ON) {SERVO2 = 0;}

      if(Servo_Idx == 2 && SERVO3_ON) {SERVO3 = 0;}

      if(Servo_Idx == 3 && SERVO4_ON) {SERVO4 = 0;}

      if(Servo_Idx == 4 && SERVO5_ON) {SERVO5 = 0;}

      if(Servo_Idx == 5 && SERVO6_ON) {SERVO6 = 0;}

      if(Servo_Idx == 6 && SERVO7_ON) {SERVO7 = 0;}

      if(Servo_Idx == 7 && SERVO8_ON) {SERVO8 = 0;}

      Ticks4NextInterruptH = 0xFF - Ticks4WindowH;

      Ticks4NextInterruptL = 0xFF - Ticks4WindowL;

      

      if(Ticks4NextInterruptL + Servo_PWML[Servo_Idx] > 0xFF)

      {

         Ticks4NextInterruptL = Ticks4NextInterruptL + Servo_PWML[Servo_Idx];

         Ticks4NextInterruptH = Ticks4NextInterruptH + Servo_PWMH[Servo_Idx] + 1;

      }

      else

      {

         Ticks4NextInterruptL = Ticks4NextInterruptL + Servo_PWML[Servo_Idx];

         Ticks4NextInterruptH = Ticks4NextInterruptH + Servo_PWMH[Servo_Idx];

      }

      Tmr1Carga(Ticks4NextInterruptH, Ticks4NextInterruptL);

      if(++Servo_Idx > 7 ) Servo_Idx = 0;

   }

   if(++flag_Phase > 1) flag_Phase = 0;

  

   //Esta instruccion se esta ejecutando cada 13ms con un xtal de 20MHz  

    LATBbits.LATB7^=1; //complementamos el valor del bit RB7

    PIR1bits.TMR1IF=0; //limpiamos la bandera de interrupcion

    PIE1bits.RCIE=1;  //habilitamos la interrupcion del puerto serie

}





static void isr_Serial() interrupt 2  //Esta es una interrupcion de baja prioridad

{

   PIR1bits.RCIF=0;

   rcvchar=RCREG;

   add2cbuff(rcvchar);

   echosel(rcvchar);

}



//Funcion Principal

void main() {

//declaracion de variables

int i=0;

int button_down=1;

int valTimer=0;



RCONbits.IPEN=1; //interrupciones por prioridad habilitadas

init_board();

Print_str("Dispositivo inicializado");

Printf(INTRO);

Print_str("PIC18F2550 en SDCC");

Printf(INTRO);

delay_ms(500); //tiempo de espera

initBuff();



for (i=0;i<9;i++)

{

   Servo_PWMH[i] = Ticks4CenterH;

   Servo_PWML[i] = Ticks4CenterL;

}



EnableTimer1Interrupt();

tempo = Ticks4Center;

tempoh = tempo & 0xFF00;

tempol = tempo & 0x00FF;

Tmr1Carga(tempoh, tempol);

posI = Ticks4Center;



      





while (true)

{

   if(flagcommand)  //si ya presionaste enter

   {

   command_process();

   }

}

}



void init_board(void) {

   flagcommand= false;

ADCON1=0x7; // PORTA used for digital I/O

TRISAbits.TRISA4=true; // configure PORTA4 for input (pushbutton)



/* Configuramos las salidas de los servomotores*/

CSERVO1 = false;

CSERVO2 = false;

CSERVO3 = false;

CSERVO4 = false;

CSERVO5 = false;

CSERVO6 = false;

CSERVO7 = false;

CSERVO8 = false;



//Configuramos la comunicacion serial --rutina de jean Pierre Mandon

setup_UART(B57600);

}



void EnableTimer1Interrupt(void)

{

   T1CON=1;        //Timer1 preescaler 1 interno, carga de 8 bits

   PIE1bits.TMR1IE=1;

   INTCONbits.PEIE=1;

   INTCONbits.GIE=1;

}



void Tmr1Carga(unsigned char high, unsigned char low)

{

   TMR1H=high;

   TMR1L=low;

}

      

//Funcion de vaciado del buffer

void initBuff(void){

   int i;

   for (i=0; i< lenbuff;i++){

      cbuff[i]=0x0;

   }xbuff=0x00;

}



//agrega un caracter mas al buffer, o realiza un acción

void add2cbuff(unsigned char c)

{

   if(xbuff<lenbuff){  //Añade caracteres al buffer mientras no se llene el buffer

      switch(c){

         case INTRO: //Enter  --> Habilita flag para procesar comando

            flagcommand=true;

            break;

         case RETROCESO: //BackSpace --> Borra del buffer el ultimo caracter insertado

            if(xbuff>0) cbuff[--xbuff]=0x00;

            break;

         case ESCAPE: //ESC  --> Borra todo el buffer

            initBuff();

            break;

         default:  //añade caracter al buffer recibido

            cbuff[xbuff++]=c;

      }

   }

   else{

      initBuff();//Si el buffer esta lleno, vacialo

      Print_str("0");  //Envia mensaje de que el buffer esta lleno Error 0

      Printf(INTRO);

   }

}



//Solo imprime los caracteres imprimibles

void echosel(char c)

{

   switch(c){

      case 0x0D: //Si presionamos la tecla intro

             Printf(INTRO);

         break;

      case 0x08: //Si presionamos la tecla BackSpace

         Printf(RETROCESO);

         break;

      case 0x1B: //Si presionamos la tecla ESC

         Printf(ESCAPE);

         break;

      default:

         Printf(c); //Echo de cualquier otro caracter

   }

}



/*

El formato de los comandos es el siguiente:

[a...f] [123] [xx]

servo posicion velocidad

primer byte un caracter alfabético de entre a y e que define al servo

tres bytes para definir la posicion del servo

dos bytes para definir la velocidad de movimiento del servo

a12301 {enter}

mueve el servo 1 a 123 grados de la posicion de origen a la velocidad 01

*/

void command_process()

{

   int i=0;

   char DerIzq= 1; //bandera para saber si va a 180 o a 0 grados

  // DerIzq = 1  Indicará que vamos de 0 a 180 por tanto suma

  // DerIzq = 0  Indicará que vamos de 180 a 0 por tanto resta

   unsigned char cmd[lenbuff]; //comando tecleado

   unsigned char servo[2];

   unsigned char pos[4];  //para almacenar las posiciones

   unsigned char posicion;

   unsigned char velocidad[4];  //para almacenar los incrementos

   unsigned char vel;

  

   unsigned int posF;  //Es posible que estos valores los tengas que dividir

   unsigned int vueltas;

  

  

   flagcommand=false;

   //Recibe el nombre del servo a mover

   strcpy(cmd,cbuff);

   strncpy(servo,cmd,1);

   //guarda la posicion del servo

   strcpy(cmd,cbuff);

   for(i=1;i<4;i++){

      pos[i-1]= cmd[i];

   }

   posicion = atoi(pos);

   //guarda la velocidad a la que se moverá el servo

   strcpy(cmd,cbuff);

   for(i=4;i<7;i++)

   {

      velocidad[i-4]=cmd[i];

   }

   vel = atoi(velocidad);

   tempo = 0;

   tempoh=0;

   tempol=0;

   switch(servo[0]){

      case 'a':

         posI=SelectServo(0);

         break;

      case 'b':

         posI=SelectServo(1);

         break;

      case 'c':

         posI=SelectServo(2);

         break;

      case 'd':

         posI=SelectServo(3);

         break;

      case 'e':

         posI=SelectServo(4);

         break;

      case 'f':

         posI=SelectServo(5);

         break;

      default:

         Print_str("3"); //Error 3 opcion elegida no válida

         Printf(INTRO);

         break;

   }

   posF= 106.66 * posicion + 8399;



  

   if(posF>posI){

      vueltas = posF - posI;

      vueltas = vueltas / vel;

      DerIzq = 1;

   }

   else

   {

      vueltas = posI - posF;

      vueltas = vueltas/ vel;

      DerIzq = 0;

   }

  

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

   /*

   Debe de leerse el valor que tiene del servo desde el array

   Žpara determinar el valor inicial y no unicamente dejarlo

   como valor final. esto causa el eeror de que al mover

   multiples motores con una unica variable se moveran en conse-

   cuencia del anterior

   */

  // posI = posF;  Esto no es correcto



   if(DerIzq)

   {

      switch(servo[0])

      {

         case 'a':  //mueve al servo uno en incrementos de vel hasta llegar a vueltas

            turnPlus(vueltas, vel, 0);

               break;

         case 'b':  //mueve al servo dos en incrementos de vel hasta llegar a vueltas

            turnPlus(vueltas, vel, 1);

               break;

         case 'c':



            

            turnPlus(vueltas, vel, 2);

               break;

         case 'd':



            turnPlus(vueltas, vel, 3);

               break;

         case 'e':



            turnPlus(vueltas, vel, 4);

               break;

         default:

            Print_str("1"); Printf(INTRO); //Error 1 turnPlusError

      }

   }

   else{

      switch(servo[0])

      {

         case 'a':  //mueve al servo uno en incrementos de vel hasta llegar a vueltas

            turnMinus(vueltas,vel,0);



               break;

         case 'b':  //mueve al servo dos en incrementos de vel hasta llegar a vueltas

            turnMinus(vueltas,vel,1);

               break;

         case 'c':

            turnMinus(vueltas,vel,2);

               break;

         case 'd':

            turnMinus(vueltas,vel,3);

               break;

         case 'e':

            turnMinus(vueltas,vel,4);

               break;

         default:

            Print_str("2");Printf(INTRO); // error 2 turnMinus Error

      }

   }

   initBuff();

   Print_str("ok");Printf(INTRO);

}

      

void delay_ms(int milis){

delay1ktcy(10*milis);



}



void delay_us(int milis){

delay10tcy(1*milis);

}



unsigned int SelectServo(unsigned char Servo)

{

         tempoh = Servo_PWMH[Servo];

         tempo = tempoh << 8;

         return (tempo | Servo_PWML[Servo]);

}



void turnPlus(int vueltas, unsigned char vel, unsigned char Servo)

{

int i=0;



for(i=0;i<vueltas;i++)

            {

               tempoh = Servo_PWMH[Servo];

               tempoh = tempoh << 8;

               tempo  = tempoh | Servo_PWML[Servo];

               tempo += vel;

               Servo_PWML[Servo] = tempo & 0x00FF;

               tempoh = tempo & 0xFF00;

               tempoh = tempoh >> 8;

               Servo_PWMH[Servo] = tempoh;

               delay_us(100);

            }

}



void turnMinus(int vueltas, unsigned char vel, unsigned char Servo)

{

int i=0;



for(i=0;i<vueltas;i++)

            {

               tempoh = Servo_PWMH[Servo];

               tempoh = tempoh << 8;

               tempo  = tempoh | Servo_PWML[Servo];

               tempo -= vel;

               Servo_PWML[Servo] = tempo & 0x00FF;

               tempoh = tempo & 0xFF00;

               tempoh = tempoh >> 8;

               Servo_PWMH[Servo] = tempoh;

               delay_us(100);

            }

}


Control de Servomotores con SDCC- Original de RedPIC Parte 1

Control de 8 servos de RC por puerto serie -- Original de RedPIC traducido a SDCC

Mensaje maigke el Vie 17 Sep 2010 - 9:32
Buenas noches a todos (Aquí en Mx es de madrugada)

Bien en esta ocasion les presento un codigo que es original de RedPIc, y que gracias a la lógica que el presenta en su sitio, he aprendido bastante. Pues bien, aqui esta el código que el nos presenta para controlar 8 servomotores con una sola interrupcion del timer1 a 16 bits, pero con las siguientes modificaciones:

-- El pic es un 18F2550
-- El lenguaje claro que es SDCC y pues así lo hace libre esto.
-- El oscilador es a 20MHz, pero basado en el proyecto Pinguino se establece que el micro trabaje a 12MIPS.
-- Tome algunos ejemplos de como trabaja el proyecto Pinguino de Jean - Pierre Mandon.
-- Aun el micro no entiende lo que le mandes por el puerto paralelo serial (andaba medio dormido). cyclops pero ya mero

sin mas preambulos, les muestro el código, que digamoslo así, es casí una copia fiel, pero con sus bueno retoques, algo importante, no se la causa del por que el SDCC no trabaja bien con las operaciones de 16bits, así que tuve que hacer algunos ajustes, así que tuve que gastar aun mas recursos de los que ya de por si SDCC requiere. posterior les presento algunas pantallas.

Espero sus notas y comentarios:, por cierto este post, se puede ligar al de GAMBAS + pic16f628 + puerto serial. Wink


/* ----------------------------------------------------------------------- */

/* Plantilla generada por Piklab */

/*

La configuracion del micro nos permite trabajar un con XT de 20MHZ

y pero usar el PLL con el propósito de alcanzar los 12MIPS

*/

#include <pic18f2550.h>

#include <delay.h>

#include <uart18f2550.c>

/* ----------------------------------------------------------------------- */

/* Bits de configuración: adapte los parámetros a su necesidad */

code char at __CONFIG1L CONFIG1L = _PLLDIV_DIVIDE_BY_5__20MHZ_INPUT__1L & _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L & _USBPLL_CLOCK_SRC_FROM_96MHZ_PLL_2_1L;

code char at __CONFIG1H CONFIG1H = _OSC_HS__HS_PLL__USB_HS_1H & _FCMEN_ON_1H & _IESO_ON_1H;

code char at __CONFIG2L CONFIG2L = _PUT_ON_2L & _BODEN_ON_2L & _BODENV_4_2V_2L & _VREGEN_ON_2L;

code char at __CONFIG2H CONFIG2H = _WDT_DISABLED_CONTROLLED_2H & _WDTPS_1_32768_2H;

code char at __CONFIG3H CONFIG3H = _CCP2MUX_RC1_3H & _PBADEN_PORTB_4_0__CONFIGURED_AS_DIGITAL_I_O_ON_RESET_3H & _LPT1OSC_ON_3H & _MCLRE_MCLR_OFF_RE3_ON_3H;

code char at __CONFIG4L CONFIG4L = _STVR_ON_4L & _LVP_OFF_4L & _ENHCPU_OFF_4L & _BACKBUG_OFF_4L;

code char at __CONFIG5L CONFIG5L = _CP_0_OFF_5L & _CP_1_OFF_5L & _CP_2_OFF_5L & _CP_3_OFF_5L;

code char at __CONFIG5H CONFIG5H = _CPB_OFF_5H;

code char at __CONFIG6L CONFIG6L = _WRT_0_OFF_6L & _WRT_1_OFF_6L & _WRT_2_OFF_6L & _WRT_3_OFF_6L;

code char at __CONFIG6H CONFIG6H = _WRTC_OFF_6H & _WRTB_OFF_6H;

code char at __CONFIG7L CONFIG7L = _EBTR_0_OFF_7L & _EBTR_1_OFF_7L & _EBTR_2_OFF_7L & _EBTR_3_OFF_7L;

code char at __CONFIG7H CONFIG7H = _EBTRB_OFF_7H;



//Definiciones de servos

#define SERVO1 LATBbits.LATB0

#define SERVO2 LATBbits.LATB1

#define SERVO3 LATBbits.LATB2

#define SERVO4 LATBbits.LATB3

#define SERVO5 LATBbits.LATB4

#define SERVO6 LATBbits.LATB5

#define SERVO7 LATBbits.LATB6

#define SERVO8 LATBbits.LATB7



#define CSERVO1 TRISBbits.TRISB0

#define CSERVO2 TRISBbits.TRISB1

#define CSERVO3 TRISBbits.TRISB2

#define CSERVO4 TRISBbits.TRISB3

#define CSERVO5 TRISBbits.TRISB4

#define CSERVO6 TRISBbits.TRISB5

#define CSERVO7 TRISBbits.TRISB6

#define CSERVO8 TRISBbits.TRISB7



typedef enum{false = 0, true = 1} boolean;



//Constantes para la definición de ventanas

const unsigned Ticks4WindowH = 0x75;

const unsigned Ticks4WindowL = 0x2F;

const unsigned Ticks4CenterH = 0x46;

const unsigned Ticks4CenterL = 0x4F;

const unsigned Ticks4MinimumH = 0x17;

const unsigned Ticks4MinimumL = 0x6F;

const unsigned Ticks4MaximumH = 0x6B;

const unsigned Ticks4MaximumL = 0xCF;

static unsigned int Ticks4NextInterruptH = 0xCF;

static unsigned int Ticks4NextInterruptL = 0x2C;



static unsigned short Servo_PWMH[8];

static unsigned short Servo_PWML[8];

static unsigned short Servo_Idx = 0;



#define SERVO1_ON true

#define SERVO2_ON false

#define SERVO3_ON false

#define SERVO4_ON false

#define SERVO5_ON false

#define SERVO6_ON false

#define SERVO7_ON false

#define SERVO8_ON false



//definicion de teclas

#define INTRO 0x0D

#define RETROCESO 0x08

#define ESCAPE 0x1B



unsigned short flag_Phase;

unsigned short j=0xFF;



/*Seccion para la comunicacion en serial*/



#define  lenbuff 10



unsigned char xbuff=0x00;

unsigned char cbuff[lenbuff];

char rcvchar=0x00;

unsigned char flagcommand = 0;





//Prototipos

void init_board(void);

void EnableTimer1Interrupt();

void Tmr1Carga(unsigned char high, unsigned char low);

void delay_ms(int milis);

void delay_us(int milis);





//Sección de interrupciones



static void isr_Tmr1() interrupt 1    //Esta es una interrupcion de alta prioridad

{

   PIE1bits.RCIE=0;  //deshabilitamos la interrupcion del puerto serie

   if(flag_Phase == 1)

   {

      if(Servo_Idx == 0 && SERVO1_ON) {SERVO1 = 1;}

      if(Servo_Idx == 1 && SERVO2_ON) {SERVO2 = 1;}

      if(Servo_Idx == 2 && SERVO3_ON) {SERVO3 = 1;}

      if(Servo_Idx == 3 && SERVO4_ON) {SERVO4 = 1;}

      if(Servo_Idx == 4 && SERVO5_ON) {SERVO5 = 1;}

      if(Servo_Idx == 5 && SERVO6_ON) {SERVO6 = 1;}

      if(Servo_Idx == 6 && SERVO7_ON) {SERVO7 = 1;}

      if(Servo_Idx == 7 && SERVO8_ON) {SERVO8 = 1;}

      Ticks4NextInterruptH = 0xFF - Servo_PWMH[Servo_Idx];

      Ticks4NextInterruptL = 0xFF - Servo_PWML[Servo_Idx];

      Tmr1Carga(Ticks4NextInterruptH,Ticks4NextInterruptL);

   }

  

   if(flag_Phase == 0)

   {

      if(Servo_Idx == 0 && SERVO1_ON) {SERVO1 = 0;}

      if(Servo_Idx == 1 && SERVO2_ON) {SERVO2 = 0;}

      if(Servo_Idx == 2 && SERVO3_ON) {SERVO3 = 0;}

      if(Servo_Idx == 3 && SERVO4_ON) {SERVO4 = 0;}

      if(Servo_Idx == 4 && SERVO5_ON) {SERVO5 = 0;}

      if(Servo_Idx == 5 && SERVO6_ON) {SERVO6 = 0;}

      if(Servo_Idx == 6 && SERVO7_ON) {SERVO7 = 0;}

      if(Servo_Idx == 7 && SERVO8_ON) {SERVO8 = 0;}

      Ticks4NextInterruptH = 0xFF - Ticks4WindowH;

      Ticks4NextInterruptL = 0xFF - Ticks4WindowL;

      

      if(Ticks4NextInterruptL + Servo_PWML[Servo_Idx] > 0xFF)

      {

         Ticks4NextInterruptL = Ticks4NextInterruptL + Servo_PWML[Servo_Idx];

         Ticks4NextInterruptH = Ticks4NextInterruptH + Servo_PWMH[Servo_Idx] + 1;

      }

      else

      {

         Ticks4NextInterruptL = Ticks4NextInterruptL + Servo_PWML[Servo_Idx];

         Ticks4NextInterruptH = Ticks4NextInterruptH + Servo_PWMH[Servo_Idx];

      }

      Tmr1Carga(Ticks4NextInterruptH,Ticks4NextInterruptL);

      if(++Servo_Idx > 7 ) Servo_Idx = 0;

   }

   if(++flag_Phase > 1) flag_Phase = 0;

   //Esta instruccion se esta ejecutando cada 13ms con un xtal de 20MHz  

    LATBbits.LATB7^=1; //complementamos el valor del bit RB7

//   RB7^=1;  <- dice que no se puede así

    PIR1bits.TMR1IF=0; //limpiamos la bandera de interrupcion

    PIE1bits.RCIE=1;  //habilitamos la interrupcion del puerto serie

    //Carga el timer para 1ms

    //Tmr1Carga(0xD1,0x1F);    //TMR1 = FFFF - FF00

}





static void isr_Serial() interrupt 2  //Esta es una interrupcion de baja prioridad

{

   PIR1bits.RCIF=0;

   rcvchar=RCREG;

   Printf(rcvchar);

}



//Funcion Principal

void main() {

//declaracion de variables

int i=0;

int button_down=1;

int valTimer=0;



RCONbits.IPEN=1; //interrupciones por prioridad habilitadas



init_board();

Print_str("Dispositivo inicializado");

Printf(INTRO);

Print_str("PIC18F2550 en SDCC");

Printf(INTRO);





for (i=0;i<9;i++)

{

   Servo_PWMH[i] = Ticks4MaximumH;

   Servo_PWML[i] = Ticks4MaximumL;

}

EnableTimer1Interrupt();

while (true)

{

}

}



void init_board(void) {

ADCON1=0x7; // PORTA used for digital I/O

TRISAbits.TRISA4=true; // configure PORTA4 for input (pushbutton)



/* Configuramos las salidas de los servomotores*/

CSERVO1 = false;

CSERVO2 = false;

CSERVO3 = false;

CSERVO4 = false;

CSERVO5 = false;

CSERVO6 = false;

CSERVO7 = false;

CSERVO8 = false;



//Configuramos la comunicacion serial --rutina de jean Pierre Mandon

setup_UART(B57600);

}



void EnableTimer1Interrupt()

{

   TMR1H=0xFF;

   TMR1L=0x00;    //TMR1 = FFFF - FF00

   T1CON=1;        //Timer1 preescaler 1 interno, carga de 8 bits

   PIE1bits.TMR1IE=1;

   INTCONbits.PEIE=1;

   INTCONbits.GIE=1;

}



void Tmr1Carga(unsigned char high, unsigned char low)

{

   TMR1H=high;

   TMR1L=low;

}

      

void delay_ms(int milis){

delay1ktcy(5*milis);

}



void delay_us(int milis){

delay10tcy(1*milis);

}


Y esta es la rutina de comunicacion serial de Jean Pierre que use

// UART Library for PIC 18F2550
// SDCC version / small device c compiler
// written by Jean-Pierre MANDON 2008 jp.mandon@free.fr
// www.pictec.org
/*
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
*/
// this program is intended for an oscillator frequency of 20 Mhz


// SPBRG value for FOSC 20 Mhz

#define B300 1,0,0x27,0x0F
#define B1200 1,0,0x09,0xC3
#define B2400 1,0,0x04,0xE1
#define B4800 1,0,0x02,0x70
#define B9600 0,0,0x00,0x4D
#define B19200 0,0,0x00,0x26
#define B57600 1,1,0x00,0xCF
#define B115200 1,1,0x00,0x67

// local definition UART.C

#define BUFFER 128 // rx buffer length
char rx[BUFFER]; // this is the buffer
unsigned char wpointer,rpointer; // write and read pointer

#define charreceived (wpointer!=rpointer)
#define SERIAL

typedef struct
{
unsigned int
hhigh4:4,
hlow4:4,
lhigh4:4,
llow4:4;
} bitfield;

// setup PIC UART

void setup_UART(unsigned char brg16,unsigned char brgh,unsigned char highbyte,unsigned char lowbyte)
{
TXSTAbits.BRGH=brgh&1; // set BRGH bit
BAUDCONbits.BRG16=brg16&1; // set 16 bits SPBRG
SPBRGH=highbyte; // set UART speed SPBRGH
SPBRG=lowbyte; // set UART speed SPBRGL
RCSTA=0x90; // set RCEN and SPEN
BAUDCONbits.RCIDL=1; // set receive active
PIE1bits.RCIE=1; // enable interrupt on RX
INTCONbits.PEIE=1; // enable peripheral interrupts
IPR1bits.RCIP=0; // define low priority for RX interrupt
wpointer=1; // initialize write pointer
rpointer=1; // initialize read pointer
TXSTAbits.TXEN=1; // enable TX
INTCONbits.GIE=1;
}

// UART write char

void Printf(unsigned char caractere)
{
while (!TXSTAbits.TRMT);
TXREG=caractere; // yes, send char
}

// rxint is called by interruption service routine

void rxint(void)
{
char caractere;
unsigned char newwp;

PIR1bits.RCIF=0; // clear RX interrupt flag
caractere=RCREG; // take received char
if (wpointer!=BUFFER-1) // if not last place in buffer
newwp=wpointer+1; // place=place+1
else
newwp=1; // else place=1

if (rpointer!=newwp) // if read pointer!=write pointer
rx[wpointer++]=caractere; // store received char

if (wpointer==BUFFER) // if write pointer=length buffer
wpointer=1; // write pointer = 1
}


// get char

unsigned char getch()
{
unsigned char caractere=0;

if (charreceived)
{
caractere=rx[rpointer++];
if (rpointer==BUFFER)
rpointer=1;
}
return(caractere);
}

// clear rx buffer

void clear_buffer(void) {
wpointer=1;
rpointer=1;
}

// write a string on the UART

void Print_str(const char* text)
{
unsigned char i=0;
while ( text[i] != 0 )
Printf( text[i++] );
}

// convert 16 bits binary value to DEC and send it on the UART

void Print_dec(unsigned int valeur)
{
unsigned char result;
unsigned char zero=1;


result=valeur/10000;
if (result!=0) {
Printf(result+0x30);
zero=0;
}
valeur=valeur%10000;
result=valeur/1000;
if (result!=0) {
Printf(result+0x30);
zero=0;
}
else if (zero==0) Printf('0');
valeur=valeur%1000;
result=valeur/100;
if (result!=0) {
Printf(result+0x30);
zero=0;
}
else if (zero==0) Printf('0');
valeur=valeur%100;
result=valeur/10;
if (result!=0) {
Printf(result+0x30);
zero=0;
}
else if (zero==0) Printf('0');
result=valeur%10;
Printf(result+0x30);
}

// convert 16 bits binary value to HEX and send it on the UART

void Print_hex(unsigned int valeur)
{
const char hexa[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

Printf(hexa[(valeur>>12)&0x000F]);
Printf(hexa[(valeur>>8)&0x000F]);
Printf(hexa[(valeur>>4)&0x000F]);
Printf(hexa[valeur&0x000F]);
}

// convert 16 bits binary value to byte and send it on the UART

void Print_byte(unsigned int valeur)
{
unsigned int result;
result=valeur;
Printf(result);
}

Referencias


http://picmania.garcia-cuervo.net/picc.php#COMBUF232
http://picmania.garcia-cuervo.net/picc_servos_x_8.php
http://sdcc.sourceforge.net/doc/sdccman.pdf
http://pinguino.walii.es/archives/161
http://karoshi.auic.es/index.php?topic=1689.0
http://jpmandon.blogspot.com/

jueves, 12 de noviembre de 2009

Java + CCS + Proteus + servos + rs232 + compim

El siguiente post trata de como podemos programar una aplicación desarrollada en JAVA, usando la libreria RXTX para comunicarse con un microcontrolador PIC16F877 simulado en proteus a través de componente COMPIM, para controlar posiciones simples de 3 servomotores. El desarrollo es interesante, ya que además no necesitas nada de hardware con estas herramientas para hacer las pruebas. El código de la comunicación se basa en la de que se muestra en picmania de RedPic.
Cabe mencionar que el desarrollo de este pequeño proyecto fué desarrollado por mis alumnos Ismael Pérez Amaro, Alejandra Karina Rojas Guzmán y Magdalena López Tiburcio de la carrera de Ing. en Sistemas Computacionales que cursan el 7to. Semestre en el ITST. a continuación coloco el texto e imagenes que me hicieron favor de redactar, así como los links de descarga.
************************************************************************************


http://www.scribd.com/doc/22497242/InterfazSerialJAVAPROTEUS

InterfazSerialJAVAPROTEUS

domingo, 20 de septiembre de 2009

Tlacotli primeras pruebas

:D Hoy estoy muy contento ya que ayer probamos 3 servos del proyecto Tlacotli (si ves la barra lateral ahi esta una foto junto con otros proyectos) pero ahora ya con un nuevo mecanismo de soporte y ademas el manejo del mismo, aqui les dejo el video

sábado, 12 de septiembre de 2009

Servomotor funcionando Bajo Linux

Saludos, aqui coloco el post que tengo en el foro de linux para pics y electrónica, espero les guste, cualquier comentario se los agradeceré

Bueno ya es de día!! y por fin ha subido el video donde se muestra como podemos controlar el servomotor con Gambas usando el Puerto Serial, bueno por el momento solo es un servo, pero mas adelante colocaremos mas servos para mover un mecanismo. y bueno creo que con esto doy terminado el hilo, y en la parte de proyectos continuaré con las siguientes partes y por menores.



Aqui coloco los fuentes para instalar, solo recuerda que debes tener el runtime de Gambas 2 en tu caja Linux y la version que trabajo es 2.8 de Gambas



Download testSerial_Paquetes.tar.bz2 from FileFactory.com
El hosting tiene ads y cosillas de esas, pero como usamos linux, pues no nos preocupemos
saludos!!!

Pruebas casi finales, aun falta ensamblar!!

Ya casi esta listo!, bueno, ya dandole toques finales para que sea funcional mi prueba con Gambas, después de unos meses de estar trabajando con esto, pues la verdad ha sido bien satisfactorio, el ver que ya esta mas vivo el programa.

El código, se ha quedado como se muestra, solo que hemos hecho un pequeño trucaje al servo que mostre en fotos anteriores, puesto que se transporto el potenciometro del servo que lleva interno, a una parte externa, de estar forma se hizo, debido a que el mecanismo de gusano sinfin + corona, exigia dos cosas:

  • El servo pudiera dar vueltas completas y varías, debido a la relacion que hay entre los engranajes
  • El posicionamiento del eje deberia ser exacto, con respecto a la horizontal que forma con la base.
Esto se puede ver claramente en la siguiente imagen

Lamentablemente, la corona que va con el gusano sin fin, al estar hecha de aluminio, y soportar una gran fuerza, pues, los dientes sufrieron los estragos, desgastandose, me comenta, Ruben, que sería mejor que dichos engranes fueran hechos de bronce, espero que consigamos una pieza pronto

El codigo fuente, hasta el momento, es el que presente en post anteriores, y el programa lo deje trabajando un buen de horas solo conectado con la tarjeta de control de servomotores y funciona de forma muy adecuada, detalles aun hay muchos, sin embargo, prodria decir, ¡Ya casí esta listo!


Falta el video donde se ve como se mueve el servo con el slider del GUI desarrollado, en este momento esta de subida.

Codigo Fuente para control de servos por RS232 Gambas



  • Responder citando
  • Editar/Borrar este mensaje



Re: GAMBAS Almenos es basic- Puerto Serie - PIC16F628A

Mensaje maigke el Lun 7 Sep 2009 - 19:39

Esta es la Parte de la comunicacion

Código:

' Gambas class file

'Variables Globales

PUBLIC flag1 AS Boolean = FALSE
PUBLIC flag2 AS Boolean = FALSE
PUBLIC fTermine AS Boolean = FALSE ' bandera para indicar que ya acabo de mover un servo

'Variables para posicionamiento
PUBLIC S1Pos1 AS Integer PUBLIC S2Pos1 AS Integer PUBLIC S3Pos1 AS Integer PUBLIC S4Pos1 AS Integer
PUBLIC S5Pos1 AS Integer
PUBLIC S1Pos2 AS Integer PUBLIC S2Pos2 AS Integer PUBLIC S3Pos2 AS Integer PUBLIC S4Pos2 AS Integer
PUBLIC S5Pos2 AS Integer

'Variables para HOME
PUBLIC s1 AS Integer PUBLIC s2 AS Integer PUBLIC s3 AS Integer PUBLIC s4 AS Integer PUBLIC s5 AS Integer
PUBLIC vini1 AS Integer PUBLIC vfin1 AS Integer PUBLIC vini2 AS Integer PUBLIC vfin2 AS Integer PUBLIC vini3 AS Integer
PUBLIC vfin3 AS Integer PUBLIC vini4 AS Integer PUBLIC vfin4 AS Integer PUBLIC vini5 AS Integer PUBLIC vfin5 AS Integer
PUBLIC tempo AS Integer

PUBLIC SUB Form_Close()
IF ttyUSB.Status = Net.Active THEN CLOSE ttyUSB
END


'***************************Seccion para la comunicacion del puerto serial
'Esta parte es bastante modificable

PUBLIC SUB Check_Status()
ChkDSR.Value = ttyUSB.DSR
ChkDTR.Value = ttyUSB.DTR
ChkCTS.Value = ttyUSB.CTS
ChkRTS.Value = ttyUSB.RTS
ChkDCD.Value = ttyUSB.DCD
ChkRNG.Value = ttyUSB.RNG
END

PUBLIC SUB Form_Open()
cmdVelocidad.Index = cmdVelocidad.Find("115200") 'Lo que sigue no es valido separa las lineas indicadas por ';'
vini1 = 0; vfin1 = 0; vini2 = 0; vfin2 = 0; vini3 = 0; vfin3 = 0; vini4 = 0; vfin4 = 0; vini5 = 0; vfin5 = 0; sldS1.Value = 250
sldS2.Value = 250; sldS3.Value = 250; sldS4.Value = 250; sldS5.Value = 250
END

PUBLIC SUB Button1_Click()
ME.Close
END

PUBLIC SUB cmdAbreCierra_Click()
IF ttyUSB.Status = Net.Active THEN
CLOSE ttyUSB
cmdAbreCierra.Text = "Abre"
ELSE
'Linea de parametros
ttyUSB.PortName = txtPortText.Text
ttyUSB.Speed = cmdVelocidad.Text
ttyUSB.Parity = cmbParidad.Index
ttyUSB.DataBits = cmbDataBits.Text
ttyUSB.FlowControl = cmbControlFlujo.Index
ttyUSB.StopBits = cmbBitParo.Text
ttyUSB.Open()
Check_Status()
TextArea1.Text = "Puerto Abierto : " & ttyUSB.PortName & " Ajustes : " &
ttyUSB.Speed & " , " & ttyUSB.Parity & " , " & ttyUSB.DataBits & " , " &
ttyUSB.StopBits & " , " & Chr(13) & Chr(10)
cmdAbreCierra.Text = "Cierra"
ENDIF
END

'Funcion para leer puerto serial RS232
PUBLIC SUB ttyUSB_Read()
DIM s AS String
IF TabStrip1.Text = "Configuracion" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea1.Text = TextArea1.Text & s
ELSE IF TabStrip1.Text = "Servo 1" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea2.Text = TextArea2.Text & s
ELSE IF TabStrip1.text = "Servo 2" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea3.Text = TextArea3.Text & s
ELSE IF TabStrip1.Text = "Servo 3" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea4.Text = TextArea4.text & s
ELSE IF TabStrip1.Text = "Servo 4" THEN
READ #ttyusb, s, Lof(ttyUSB)
TextArea5.Text = TextArea5.text & s
ELSE IF TabStrip1.Text = "Servo 5" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea6.Text = TextArea6.Text & s
ENDIF
END

PUBLIC SUB ttyUSB_RNGChange(ival AS Boolean)
ChkRNG.Value = ival
END

PUBLIC SUB ttyUSB_DTRChange(ival AS Boolean)
ChkDTR.Value = ival
END

PUBLIC SUB ttyUSB_DSRChange(ival AS Boolean)
ChkDSR.Value = ival
END

PUBLIC SUB ttyUSB_CTSChange(ival AS Boolean)
ChkCTS.Value = ival
END

PUBLIC SUB ttyUSB_DCDChange(ival AS Boolean)
ChkDCD.Value = ival
END

PUBLIC SUB ttyUSB_RTSChange(ival AS Boolean)
ChkRTS.Value = ival
END

PUBLIC SUB ChkDTR_Click()
ttyUSB.DTR = ChkDTR.Value
Check_Status
END

PUBLIC SUB ChkRTS_Click()
ttyUSB.RTS = ChkRTS.Value
Check_Status
END

PUBLIC SUB cmbControlFlujo_Click()
ttyUSB.FlowControl = cmbControlFlujo.Index
END
Esta parte es la que envia los datos a los seis servos upps, ¿de cuál fumé? si son solo 5 Laughing

Código:

'************************************************************************************************
PUBLIC SUB cmdAtras_Click()
IF ttyUSB.Status = Net.Inactive THEN
Message("Primero abre el Puerto")
ELSE
PRINT #ttyUSB, "a"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "A"
WAIT 0.3 'Este retardo es para el parpadeo, entre colores, pero no tiene mucho caso
ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
ENDIF
END

PUBLIC SUB cmdAdelante_Click()
IF ttyUSB.Status = Net.Inactive THEN
Message("Primero abre el puerto")
ELSE
PRINT #ttyUSB, "11"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "1"
WAIT 0.3
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
ENDIF
END
'**************************************************************************
'Control del primer servo
'Para el envio de datos, fue probada la tarjeta con varios valores
'en el tiempo medido por osciloscopio, cuando la tarjeta es reiniciada
'con escala de 0.5ms por division, el tiempo en alto esta establecido a 1500ms
'tomado este valor como referencia, el slider y el spinbox, tienen el valor de
'250 de forma inicial, ya fueron medidos los tiempos de forma repetida, para
'verificar la presición del numero de datos enviados a la tarjeta.
PUBLIC SUB spnboxS1_Change()
DIM maximo AS Integer
DIM i AS Integer
sldS1.Value = spnboxS1.Value
vfin1 = spnboxS1.Value
tempo = 0
tempo = Abs(vfin1 - vini1)
'TextArea2.Text = "Vini1=" & vini1 & " Vfin1= " & vfin1 & " ciclo= " & tempo
'wait 1
IF (vfin1 - vini1) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "AAA"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "A"
WAIT 0.1 'Este retardo es importante, ya que la tarjeta no responde muy rápido
ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
NEXT
maximo = 0
ELSE
ENDIF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "111"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "1"
WAIT 0.1
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
NEXT
maximo = 0
ELSE
ENDIF
ENDIF
vini1 = vfin1
tempo = 0
fTermine = TRUE
END
'**********************************************************************************
PUBLIC SUB sldS1_Change()
DIM maximo AS Integer
DIM i AS Integer
spnboxS1.Value = sldS1.Value
vfin1 = spnboxS1.Value
tempo = 0
tempo = Abs(vfin1 - vini1)
'TextArea2.Text = "Vini1=" & vini1 & " Vfin1= " & vfin1 & " ciclo= " & tempo
'WAIT 1
IF (vfin1 - vini1) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "A"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "A"
WAIT 0.1
ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
NEXT
maximo = 0
ELSE
ENDIF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "1"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "1"
WAIT 0.1
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
NEXT
maximo = 0
ELSE
ENDIF
ENDIF
vini1 = vfin1
tempo = 0
fTermine = TRUE
END
'***********************************************************************************
'Control del segundo servo
PUBLIC SUB spnboxS2_Change()
DIM maximo AS Integer
DIM i AS Integer
sldS2.Value = spnboxS2.Value
vfin2 = spnboxS2.Value
tempo = 0
tempo = Abs(vfin2 - vini2)
'Usese solo en caso de que olvide el cable de comicacion como a mi me paso :(
'TextArea3.Text = "Vini2=" & vini2 & " Vfin2= " & vfin2 & " ciclo= " & tempo
' WAIT 1
IF (vfin2 - vini2) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "B"
ToolButton3.Background = &FF0000&
ToolButton3.Text = "B"
WAIT 0.1 'Este retardo es importante, ya que la tarjeta no responde muy rápido
ToolButton4.BackColor = &00FF00&
ToolButton4.Text = ""
NEXT
maximo = 0
ELSE
ENDIF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "2"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "2"
WAIT 0.1
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
NEXT
maximo = 0
ELSE
ENDIF
ENDIF
vini2 = vfin2
tempo = 0
END
'**********************************************************************************
PUBLIC SUB sldS2_Change()
DIM maximo AS Integer
DIM i AS Integer
spnboxS2.Value = sldS2.Value
vfin2 = spnboxS2.Value
tempo = 0
tempo = Abs(vfin2 - vini2)
IF (vfin2 - vini2) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "B"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "B"
WAIT 0.1
ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
NEXT
maximo = 0
ELSE
ENDIF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "1"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "1"
WAIT 0.1
ToolButton2.Background = &00FF00&
ToolButton2.text = ""
NEXT
maximo = 0
ELSE
ENDIF
ENDIF
vini2 = vfin2
tempo = 0
fTermine = TRUE
END
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'Control del tercer servo
PUBLIC SUB spnboxS3_Change()
DIM maximo AS Integer
DIM i AS Integer
sldS3.value = spnboxS3.Value
vfin3 = spnboxS3.Value
tempo = 0
tempo = Abs(vfin3 - vini3)
IF (vfin3 - vini3) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "C"
ToolButton5.BackColor = &FF0000&
ToolButton5.Text = "C"
WAIT 0.1
ToolButton5.BackColor = &00FF00&
ToolButton5.Text = ""
NEXT
maximo = 0
ELSE
END IF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "3"
ToolButton6.BackColor = &FF0000&
ToolButton6.Text = "3"
WAIT 0.1
ToolButton6.BackColor = &00FF00&
ToolButton6.Text = ""
NEXT
maximo = 0
ENDIF
END IF
vini3 = vfin3
tempo = 0
fTermine = TRUE
END

PUBLIC SUB sldS3_Change()
DIM maximo AS Integer
DIM i AS Integer
spnboxS3.value = sldS3.Value
vfin3 = sldS3.Value
tempo = 0
tempo = Abs(vfin3 - vini3)
IF (vfin3 - vini3) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "C"
ToolButton5.BackColor = &FF0000&
ToolButton5.Text = "C"
WAIT 0.1
ToolButton5.BackColor = &00FF00&
ToolButton5.Text = ""
NEXT
maximo = 0
ELSE
END IF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "3"
ToolButton6.BackColor = &FF0000&
ToolButton6.Text = "3"
WAIT 0.1
ToolButton6.BackColor = &00FF00&
ToolButton6.Text = ""
NEXT
maximo = 0
ENDIF
END IF
vini3 = vfin3
tempo = 0
fTermine = TRUE
END
'***********************************************************************************************************
'Control del 4to servo
PUBLIC SUB spnboxS4_Change()
DIM maximo AS Integer
DIM i AS Integer
sldS4.value = spnboxS4.Value
vfin4 = spnboxS4.Value
tempo = 0
tempo = Abs(vfin4 - vini4)
IF (vfin4 - vini4) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "D"
ToolButton7.BackColor = &FF0000&
ToolButton7.Text = "D"
WAIT 0.1
ToolButton7.BackColor = &00FF00&
ToolButton7.Text = ""
NEXT
maximo = 0
ELSE
END IF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "4"
ToolButton8.BackColor = &FF0000&
ToolButton8.Text = "4"
WAIT 0.1
ToolButton8.BackColor = &00FF00&
ToolButton8.Text = ""
NEXT
maximo = 0
ENDIF
END IF
vini4 = vfin4
tempo = 0
fTermine = TRUE
END

PUBLIC SUB sldS4_Change()
DIM maximo AS Integer
DIM i AS Integer
spnboxS4.value = sldS4.Value
vfin4 = sldS4.Value
tempo = 0
tempo = Abs(vfin4 - vini4)
IF (vfin4 - vini4) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "D"
ToolButton7.BackColor = &FF0000&
ToolButton7.Text = "D"
WAIT 0.1
ToolButton7.BackColor = &00FF00&
ToolButton7.Text = ""
NEXT
maximo = 0
ELSE
END IF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "4"
ToolButton8.BackColor = &FF0000&
ToolButton8.Text = "4"
WAIT 0.1
ToolButton8.BackColor = &00FF00&
ToolButton8.Text = ""
NEXT
maximo = 0
ENDIF
END IF
vini4 = vfin4
tempo = 0
fTermine = TRUE
END
'***********************************************************************************************************
'control Servo 5
PUBLIC SUB spnboxS5_Change()
DIM maximo AS Integer
DIM i AS Integer
sldS5.value = spnboxS5.Value
vfin5 = spnboxS5.Value
tempo = 0
tempo = Abs(vfin5 - vini5)
IF (vfin5 - vini5) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "E"
ToolButton9.BackColor = &FF0000&
ToolButton9.Text = "E"
WAIT 0.1
ToolButton9.BackColor = &00FF00&
ToolButton9.Text = ""
NEXT
maximo = 0
ELSE
END IF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "5"
ToolButton10.BackColor = &FF0000&
ToolButton10.Text = "5"
WAIT 0.1
ToolButton10.BackColor = &00FF00&
ToolButton10.Text = ""
NEXT
maximo = 0
ENDIF
END IF
vini5 = vfin5
tempo = 0
fTermine = TRUE
END

PUBLIC SUB sldS5_Change()
DIM maximo AS Integer
DIM i AS Integer
spnboxS5.value = sldS5.Value
vfin5 = sldS5.Value
tempo = 0
tempo = Abs(vfin5 - vini5)
IF (vfin5 - vini5) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "E"
ToolButton9.BackColor = &FF0000&
ToolButton9.Text = "E"
WAIT 0.1
ToolButton9.BackColor = &00FF00&
ToolButton9.Text = ""
NEXT
maximo = 0
ELSE
END IF
ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "5"
ToolButton10.BackColor = &FF0000&
ToolButton10.Text = "5"
WAIT 0.1
ToolButton10.BackColor = &00FF00&
ToolButton10.Text = ""
NEXT
maximo = 0
ENDIF
END IF
vini5 = vfin5
tempo = 0
fTermine = TRUE
END
'***********************************************************************************************************
La última parte del código borra los textareas y manda a posicionar al servo, aqui hay una parte importante con un ciclo while - wend, y tiene mucho que ver la bandera que puse en cada seccion de movimiento de servos, ya que sin esta bandera no se saldría de dicho ciclo. Very Happy

Código:

'Area de borrados de textAreas, cada text area solo contendra la info necesaria para su propio servo
PUBLIC SUB cmdBorrar_Click()
TextArea2.Text = ""
END

PUBLIC SUB Button2_Click()
TextArea3.Text = ""
END

PUBLIC SUB Button3_Click()
TextArea4.Text = ""
END

PUBLIC SUB Button4_Click()
TextArea5.Text = ""
END

PUBLIC SUB Button5_Click()
TextArea6.Text = ""
END

'Rutina de grabar las posiciones de los servos

PUBLIC SUB cmdGrabar_Click()
IF flag1 = FALSE AND flag2 = FALSE THEN
cmdGrabar.Text = "Grabar"
S1Pos1 = spnboxS1.Value
S2Pos1 = spnboxS2.Value
S3Pos1 = spnboxS3.Value
S4Pos1 = spnboxS4.Value
S5Pos1 = spnboxS5.Value
flag1 = TRUE
ELSE IF flag1 = TRUE AND flag2 = FALSE THEN
S1Pos2 = spnboxS1.Value
S2Pos2 = spnboxS2.Value
S3Pos2 = spnboxS3.Value
S4Pos2 = spnboxS4.Value
S5Pos2 = spnboxS5.Value
flag2 = TRUE
ELSE
Message.Error("Solo dos posiciones")
cmdGrabar.Text = "Borra"
S1Pos1 = 0
S1Pos2 = 0
S2Pos1 = 0
S2Pos2 = 0
S3Pos1 = 0
S3Pos2 = 0
S4Pos1 = 0
S4Pos2 = 0
S5Pos1 = 0
S5Pos2 = 0
flag1 = FALSE
flag2 = FALSE
END IF
END

PUBLIC SUB cmdHome_Click()
s1 = spnboxS1.Value
s2 = spnboxS2.Value
s3 = spnboxS3.Value
s4 = spnboxS4.Value
s5 = spnboxS5.Value
TextArea1.text = "Home ha sido selecionado con las siguientes
posiciones " & s1 & " " & s2 & " " & s3 & " "
& s4 & " " & s5
'TabStrip1.Action =
END

PUBLIC SUB ToolButton11_Click()
'Ir a home
'Colocamos una bandera que se llama fTermine que nos indica si un ciclo de envio de datos ya termino
' ahora preguntamos si los valores del spinbox y del valor dado como home son iguales
' esto pasa si un eje no lo mueves desde un inicio, en caso de ser cierto, pues entonces
' no hace nada, ya que si no se pone el if por alguna razon entra en un bucle infinito
' si los valores actuales del spinbox y de la pos de home no son iguales,
' mandamos a modificar ahora el valor del spinbox, enviando los correspondientes
' a través del puerto serial
fTermine = FALSE
IF (spnboxS1.Value <> s1) THEN
spnboxS1.Value = s1
WHILE fTermine = FALSE
WEND
END IF
fTermine = FALSE
IF (spnboxS2.Value <> s2) THEN
spnboxS2.Value = s2
WHILE fTermine = FALSE
WEND
END IF
fTermine = FALSE
IF (spnboxS3.Value <> s3) THEN
spnboxS3.Value = s3
WHILE fTermine = FALSE
WEND
END IF
fTermine = FALSE
IF (spnboxS4.Value <> s4) THEN
spnboxS4.Value = s4
WHILE fTermine = FALSE
WEND
END IF
fTermine = FALSE
IF (spnboxS5.Value <> s5) THEN
spnboxS5.Value = s5
WHILE fTermine = FALSE
WEND
END IF
'Ir a la posicion 1
'Ir a la posicion 2
'Regresar a home
END

martes, 1 de septiembre de 2009

Nueva prueba de comunicacion serial con GAMBAS

Hola a todos de nuevo!

Bien, pues el dia de hoy y despues de varios infructuosos intentos de hacer la comunicacion con la aplicacion que estoy desarrollando, me puse a pensar un poquito Laughing

Me volví a fijar en el archivo que viene de ejemplo en GAMBAS 2, y pues ya que me cayo el 20, decidi, de nuevo emplear todas las opciones de la conexion por el puerto serial, y bueno ahora usando la interfaz usb-serie, que por cierto para linux no requiere de algún tipo en partícular de driver.

basado en esto y analizando mas a conciencia el código de ejemplo vi los siguientes aspectos

1. Existe una funcion para abrir el puerto (Demasiado obvio, pero por esto mismo me equivoque en el anterior), no unicamente se pasan los paramtros, sino que tambien, se hace necesario un chequeo de estado pasando a unos indicadores chkbox los valores de algunos valores importantes de la comunicacion serial como son Ring, DCD, CTS, etc. en este caso, si todo va bien, al hacer el chequeo, unicamente se marcarán DTR, RTS (Data Terminal Ready - Request to Send) Que nos indican que la terminal de datos esta lista para funcionar y que ademas esta en petición para enviar datos
Fuente: http://www.beyondlogic.org/serial/serial.htm

2. Una parte de asignación de cambio de valores booleanos a los chkbox de los pines del RS232

3. La implementación de la función de lectura, usando el comando READ a través de un flujo (stream) que viene del objeto instanciado hacia el Puerto Serial. y almacenandolo en una cadena llamada s.

4. El envio de datos, es la parte que personalizamos, para poder enviar datos, primero debemos verificar que se encuentre activo el puerto serie, esto se hace usando el siguiente comando

IF ttyUSB.Status = Net.Inactive THEN

posterior a esto puede colocar una ventana de mensaje o algún otro tipo de dato; en el ELSE usted podrá colocar el envio de los datos, para nosotros fué más facil el pensar en trabajarlo con un PRINT a través de flujo (stream) #ttyUSB, quedando de esta forma

PRINT #ttyUSB, "a" 'Esto envia el caracter ascii de la letra 'a' por el puerto serial, siempre y cuando este abierto dicho puerto.

para el envio de los datos use, dos commmandButton, que envian únicamente una letra por cada clic, y un slider con un spinbox, como lo hice en el programa anterior, pero ademas, coloque, dos toolbutton, que ya se que no son para eso pero los use como indicadores cyclops cambiando de color cuando un dato ha sido enviado.

Tuve problema primero, pues al enviar cantidades pequeñas de datos, es decir, unas 3 letrs, todo trabajaba a la perfección, el problema se sucitó, cuanod enviaba mas de 10 elementos, y pues esto se moría, y bueno como se arreglo mas o menos el asunto, espero en verdad encontrar una mejor solución.

Colocando un wait 0.1 que genera un retardo de 100ms, tiempo suficiente para que enie el dato y le de chance a nuestro programa que responda de forma adecuada, de hecho así lo hizo!!!

les dejo el código fuente que hemos realizado

Código:

' Gambas class file
'Midiendo con el Osciloscopio, el ancho de pulso de la tarjeta mide 1500us
'si con en programa, suponemos que por cada caracter que envie al micro, un servo tendrá un
'movimiento de un grado, parece que este dato es totalmente erroneo, a pesar de que los
'calculos esten bien realizados.

'Para iniciar el programa solo manda caracteres, pero creo que estos incluyen muchos
'CR & LF en los cuales el micro al recibirlos se ataranta.
'como recibi muchos datos y tambien los envia, es impresindible que solo
'envie una señal cuando yano reciba datos, pero como asegurarnos que ha recibido
'el correcto numero de pulsos, que no sea a traves del uso del printf
' y/o de alguna incorrecta inicializacion de otro dispositivo
' el uso de wait, realmente ha hecho que el programa sea muy lento

'Variables Globales

PUBLIC vini1 AS Integer
PUBLIC vfin1 AS Integer

PUBLIC tempo AS Integer




PUBLIC SUB Form_Close()
IF ttyUSB.Status = Net.Active THEN CLOSE ttyUSB
END


'***************************Seccion para la comunicacion del puerto serial
'Esta parte es bastante modificable

PUBLIC SUB Check_Status()

ChkDSR.Value = ttyUSB.DSR
ChkDTR.Value = ttyUSB.DTR
ChkCTS.Value = ttyUSB.CTS
ChkRTS.Value = ttyUSB.RTS
ChkDCD.Value = ttyUSB.DCD
ChkRNG.Value = ttyUSB.RNG


END

PUBLIC SUB Form_Open()
cmdVelocidad.Index = cmdVelocidad.Find("115200")
vini1 = 0
vfin1 = 0
sldS1.Value = 90
END



PUBLIC SUB Button1_Click()

ME.Close

END



PUBLIC SUB cmdAbreCierra_Click()

IF ttyUSB.Status = Net.Active THEN
CLOSE ttyUSB
cmdAbreCierra.Text = "Abre"
ELSE
'Linea de parametros
ttyUSB.PortName = txtPortText.Text
ttyUSB.Speed = cmdVelocidad.Text
ttyUSB.Parity = cmbParidad.Index
ttyUSB.DataBits = cmbDataBits.Text
ttyUSB.FlowControl = cmbControlFlujo.Index
ttyUSB.StopBits = cmbBitParo.Text

ttyUSB.Open()
Check_Status()
TextArea1.Text = "Puerto Abierto : " & ttyUSB.PortName & " Ajustes : " &
ttyUSB.Speed & " , " & ttyUSB.Parity & " , " & ttyUSB.DataBits & " , " &
ttyUSB.StopBits & " , " & Chr(13) & Chr(10)
cmdAbreCierra.Text = "Cierra"
ENDIF
END

PUBLIC SUB ttyUSB_Read()
DIM s AS String


IF TabStrip1.Text = "Configuracion" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea1.Text = TextArea1.Text & s
ELSE IF TabStrip1.Text = "Servo 1" THEN
READ #ttyUSB, s, Lof(ttyUSB)
TextArea2.Text = TextArea2.Text & s
ENDIF
END


PUBLIC SUB ttyUSB_RNGChange(ival AS Boolean)

ChkRNG.Value = ival

END

PUBLIC SUB ttyUSB_DTRChange(ival AS Boolean)

ChkDTR.Value = ival

END

PUBLIC SUB ttyUSB_DSRChange(ival AS Boolean)

ChkDSR.Value = ival

END

PUBLIC SUB ttyUSB_CTSChange(ival AS Boolean)

ChkCTS.Value = ival

END

PUBLIC SUB ttyUSB_DCDChange(ival AS Boolean)

ChkDCD.Value = ival

END

PUBLIC SUB ttyUSB_RTSChange(ival AS Boolean)

ChkRTS.Value = ival

END

PUBLIC SUB ChkDTR_Click()

ttyUSB.DTR = ChkDTR.Value
Check_Status

END

PUBLIC SUB ChkRTS_Click()

ttyUSB.RTS = ChkRTS.Value
Check_Status

END

PUBLIC SUB cmbControlFlujo_Click()

ttyUSB.FlowControl = cmbControlFlujo.Index

END



'************************************************************************************************
'Esta parte corresponde a los controles que se encuentran en el tab SERVO 1
'Los primeros son dos botones con dos toolbuttons que sirven como leds indicadores
'La segunda parte corresponde a un spinbox y aun slider

PUBLIC SUB cmdAtras_Click()

IF ttyUSB.Status = Net.Inactive THEN
Message("Primero abre el Puerto, NO JODAS")
ELSE
PRINT #ttyUSB, "a"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "A"
WAIT 0.3 'Este retardo es para el parpadeo, entre colores, pero no tiene mucho caso
ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
ENDIF
END

PUBLIC SUB cmdAdelante_Click()

IF ttyUSB.Status = Net.Inactive THEN
Message("Primero abre el puerto NO JODAS")
ELSE
PRINT #ttyUSB, "11"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "1"
WAIT 0.3
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
ENDIF
END
'**************************************************************************
PUBLIC SUB spnboxS1_Change()
DIM maximo AS Integer
DIM i AS Integer

sldS1.Value = spnboxS1.Value
vfin1 = spnboxS1.Value
tempo = 0

tempo = Abs(vfin1 - vini1)

IF (vfin1 - vini1) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "AAA"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "A"
WAIT 0.1 'Este retardo es importante, ya que la tarjeta no responde muy rápido

ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
NEXT
maximo = 0
ELSE
Message.Info("NO JODAS A")
ENDIF

ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "111"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "1"
WAIT 0.1
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
NEXT
maximo = 0
ELSE
Message.info("NO JODAS 1")
ENDIF
ENDIF
vini1 = vfin1

END
'**********************************************************************************
PUBLIC SUB sldS1_Change()
DIM maximo AS Integer
DIM i AS Integer

spnboxS1.Value = sldS1.Value
vfin1 = spnboxS1.Value
tempo = 0

tempo = Abs(vfin1 - vini1)

IF (vfin1 - vini1) < 0 THEN
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "AAA"
ToolButton2.Background = &FF0000&
ToolButton2.Text = "A"
WAIT 0.3
ToolButton2.BackColor = &00FF00&
ToolButton2.Text = ""
NEXT
maximo = 0
ELSE
Message.Info("NO JODAS A")
ENDIF

ELSE
IF ttyUSB.Status = Net.Active THEN
maximo = tempo
FOR i = 1 TO maximo
PRINT #ttyUSB, "111"
ToolButton1.Background = &FF0000&
ToolButton1.Text = "1"
WAIT 0.3
ToolButton1.Background = &00FF00&
ToolButton1.text = ""
NEXT
maximo = 0
ELSE
Message.info("NO JODAS 1")
ENDIF
ENDIF
vini1 = vfin1


END

PUBLIC SUB cmdBorrar_Click()

TextArea2.Text = ""

END

PUBLIC SUB cmdColor_Click()

cmdColor.text = "Rojo"
FMain.BackColor = &H00FF0000&

END








Lo mas padre de todo esto es que si funciona aunque lento pero funciona.

Prueba de Interfaz USB-RS232 Linux + minicom

Hola a todos!!, despues de como 20 días sin avance, y bueno por fin podre mas o menos seguir adelante con esto !!!

Espero que no hayan pensado que deje abandonado pero bueno, poe el momento y asi como que de rápido, por fin consegui una interfaz serial usb, y eso es lo que estaba deteniendo mucho.

acabo de probar mi tarjeta controladora de servos con la interfaz usb-rs232 y minicom, que es una aplicacion muy padre de comunicacion serial para linux en linea de comandos., para que podamos usar la interfaz haremos lo siguiente.

conectar nuestro cable
abrir una terminal
teclear el siguiente comando $dmesg y esperar que nos diga algo como esto
[ 2106.356084] usb 3-1: new full speed USB device using uhci_hcd and address 3
[ 2106.521639] usb 3-1: configuration #1 chosen from 1 choice
[ 2106.525273] pl2303 3-1:1.0: pl2303 converter detected
[ 2106.545611] usb 3-1: pl2303 converter now attached to ttyUSB0

En este caso la interfaz es reconocida por ubuntu de forma automática como ttyUSB0, ahora solo toca configura el minicom.

para esto tecleamos

minicom -s
+-----------------------------------------------------------------------+
| A - Dispositivo Serial : /dev/ttyUSB0 |
| B - Localización del Archivo de Bloqueo : /var/lock |
| C - Programa de Acceso : |
| D - Programa de Salida : |
| E - Bps/Paridad/Bits : 115200 8N1

Al terminar si estamos en una lap, conviene guardar la configuracion,
así que al salir, pues a guardar como

| Salvar configuración como dfl |<--- Esta!!
| Salvar configuración como.. |
| Salir |

y pues a comunicarse!!.
+--------------------------------------
boxpic> 1
> S_1 +
1
> S_1 +
2
> S_2 +
2
> S_2 +
3
> S_3 +
3
> S_3 +
4
> S_4 +
4
> S_4 +
5
> S_5 +
+-----------------------------------------

La verdad el programa del microcontrolador no tiene muchos printf
ya que estos se acaban la memoria, entonces, mejos solo uso los necesarios

El unico detalle que hasta el momento le veo es el siguiente.
cuando cierro el minicom, automáticamente se desconecta la interfaz USB-RS

y entonces tengo sacar el cable y conectarlo de nuevo. espero, que en el
siguiente post, pues ya tenga mas avances!

Por cierto hoy no coloco imagenes por que ando de prisas, hoy, voy a la casa
de mi novia, y pues voy por ella!! cheers cheers cheers

sábado, 8 de agosto de 2009

RS232 GAMBAS PIC prueba

Probando el ejemplo que trae GAMBAS

Bien, como sabran, gambas trae un ejemplo base Smile (de hecho a mi se me hizo muy completo!!), del manejo del puerto serial, para esto, probe la tarjeta que mostre en el anterior post, pero ya con la maquina.

Antes que nada el ejemplo si lo instalas en ubuntu, lo vas a encontrar en la siguiente ruta

/usr/share/gambas2/examples/Networking/SerialPort

copia esta carpeta a lugar donde desees de tu home, esto hace que al colocarla en otro lugar, ahora esta carpeta, junto con su contenido te pertenezcan alien

bueno, ahora aqui tuve un gran problema. probe mi tarjeta con la aplicacion minicom, y pues funciona perfecto, con cada caracter que recibe el micro, este modifica el ancho de pulso del servo que esta controlando, por lo tanto su posicion.

Sin embargo al trabajar con el ejemplo que trae gambas, pues nada que me reconocia el caracter, y es que en el programa del micro que tengo, pasa lo siguiente

*lee el caracter desde el buffer del puerto serial
* lo convierte a mayuscula
* usa switch y case para definir como va a tratar al dato recien llegado
* genera las interrupciones adecuadas para modificar el ancho del pulso
Código:

do{

if(comando!='\0')

{ //solo entra aqui si comando es diferente a nulo

//comando = toupper(comando);

ComandoValido=0;

printf("%c\r\n",comando);

//delay_ms(1000);

switch(comando){
case '1':{

printf("> S_1 +\r\n");

Servo_PWM[0]+=20;

ComandoValido=1;

}break;

case 'A':{

printf("> S_1 -\r\n");

Servo_PWM[0]-=20;

ComandoValido=1;

}break;

case '2':{

printf("> S_2 +\r\n");

Servo_PWM[1]+=20;

ComandoValido=1;

}break;

case 'B':{

printf("> S_2 -\r\n");

Servo_PWM[1]-=20;

ComandoValido=1;

}break;
default:{

printf("<%c>no se encontro \n",comando);

ComandoValido=0;

disable_interrupts(int_rda);

delay_ms(10);

enable_interrupts(int_rda);

//delay_ms(10);

}break;

}

if(ComandoValido==0) {

if(comando== '\0'){printf("EOL\n");}

else

printf("*%c \n",comando); }

comando='\0';

//delay_ms(1);

}

//delay_ms(50);

}while(1);

imprimiendo entre cada etapa, ahora, pasa algo extraño Question , el caracter recibido, si me lo imprimia, pero no me lo reconocía, es como si lo borrara. bueno anduve de arriba para abajo con esto.

Sin embargo no me di cuenta de algo!!, despues de unas horas Embarassed , que el problema no era tanto el codigo del micro, si no mas bien el codigo de gambas, ya que en una parte hace lo siguiente
Código:

PUBLIC SUB Button2_Click()

IF Sport.Status = Net.Inactive THEN
Message("Open port first!")
ELSE
'Cuando damos clic al boton 2, lee el texto que hay en txtSend y lo manda por el flujo Sport
' Pero ademas de eso envia dos caracteres mas, un Retorno de Carro y Alimentacion de Línea
'Esto me daba en la torre (T_T)
PRINT #Sport, txtSend.Text; Chr$(13); Chr$(10);
END IF

END


En efecto, ahora como pude evitar eso, pues la forma mas sencilla y más rapida que se me ocurrio fue la siguiente.

Si el primer caracter me lo detecta, pero tambien el segundo y hace lo que quiere la tarjeta
Pues entonces, mandale 2 caracteres iguales!!!, pero ambos deben ser mayusculas!!, ya que el programa únicamente
recibe el primer dato, y lo transforma, pero aun no averiguo que diablos le hace al segundo, ya que este ultimo mencionado
es el que acepta. affraid
Bueno aqui les coloco unas imagenes y un video, espero sea de su agrado, algo que se me hizo interesante, deje funcionando la aplicacion un buen de horas y con todo conectado y nunca se trabo, o tuve que cerrar el puerto o abrirlo




Pikitin, la funcion de lectura es la siguiente:

Código:

PUBLIC SUB SPort_Read()
DIM s AS String 'Variable donde se almacena lo recibido por el buffer
READ #Sport, s, Lof(Sport) 'Leer el stream del puerto, almacenarlo en s y medir su tamaño
TextArea1.Text = TextArea1.Text & s 'manda el texto recibido por el puerto paralelo a un textArea
END