Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Estoy liado con el código en CSS para lanzar una trama por RS232 hacia el PC(en este caso la lectura de varias LDR por las analógicas).El problema reside que cuando lanzo la trama con Printf al parecer entra la interrupcion de TMR0 (varias veces supongo)y me corta la trama, recibiendo caracteres sin sentido en el PC, otras veces cortadas, etc. Si desabilito el TMR0 no tengo ningún problema de recibir estas tramas. ¿alguna idea al respecto?. La interrupción de TMR la tengo rápida para no equivocarme mucho porque ataco a los servos trucados utilizando la parte de electrónica (asi me ahorro los puentes en H) . Y todo esto es para hacer un Mod de Tarribot. (gracias Furri por dar luz donde hay oscuridad y muy bueno tu trabajo).
Saludos
He reformateado el programa a mi gusto, manías mias, asi lo sigo con más facilidad. Lástima que al enviarlo desaparezcan los tabuladores.
Creo que el problema es que haces demasiados printf seguidos. El PIC va muy rápido y si envías un printf por cada vuelta de programa (cada llamada a Secuenciador) a 9600 baudios el puerto serie se "atraganta" con tantos datos, no le da tiempo a enviar un mensaje y ya llega otro. Prueba a enviar una printf cada 400 vueltas de programa o algo parecido (he marcado en negrita la modificación). Tienes que esperar a que haya enviado un mensaje antes de mandar otro. A 9600 baudios es (start + 8 bits + stop * 9600 bits/segundo = 960 caracteres por segundo) tu printf tiene 53 caracteres, si no he contado mal, tarda 55,2 ms en enviarse.
Ahora no tengo a mano ningún PIC y no he pocido probarlo, ya me contaras...
/* Pruebas de motor en secuencia. Dos servos conectados a B0 y B1.
Los define de motor estan alterados para ir en lenta . Substituir si necesitamos mas velocidad.
*/
#include <16F877A>
#fuses HS,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=20000000)
#define ADELANTE 2
#define IZQUIERDAS 3
#define DERECHAS 4
#define MOTOR_DERECHO_ADELANTE_RAPIDO 0x7f //0x01
#define MOTOR_DERECHO_ADELANTE_LENTO1 0x7f
#define MOTOR_DERECHO_ADELANTE_LENTO2 0x7E
#define MOTOR_DERECHO_PARADO 0
#define MOTOR_DERECHO_ATRAS_RAPIDO 0x81 //0xFF
#define MOTOR_DERECHO_ATRAS_LENTO1 0x81
#define MOTOR_DERECHO_ATRAS_LENTO2 0x82
#define MOTOR_IZQUIERDO_ADELANTE_RAPIDO 0x81 //0xFF
#define MOTOR_IZQUIERDO_ADELANTE_LENTO1 0x81
#define MOTOR_IZQUIERDO_ADELANTE_LENTO2 0x82
#define MOTOR_IZQUIERDO_PARADO 0
#define MOTOR_IZQUIERDO_ATRAS_RAPIDO 0x7f // 0xff
#define MOTOR_IZQUIERDO_ATRAS_LENTO1 0x7f
#define MOTOR_IZQUIERDO_ATRAS_LENTO2 0x7E
#define MOTOR_CENTRADO 0x80
#define MOTOR_PARADO 0x00
#define MOTOR_DERECHO 0x01
#define MOTOR_IZQUIERDO 0x00
//#use standard_io(b)
#use fast_io(B)
int8 x,val,duty,timer0,dato,retardo,refe,ldr_izquierda_valor,ldr_derecha_valor,ldr_centro_valor,movimiento;
int1 led=FALSE,tick=FALSE,startPWM;
int8 duty_pwm[8],permiso_pwm[8];
void motorizacion(int8);
void secuenciador(void);
unsigned int contador;
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#ORG 0x1f00, 0x1FFF{}
/* INTERRUPCION SERIE =======================================================*/
#int_rda
void serial_isr()
{
if (kbhit()) refe=getc();
}
/* INTERRUPCION TIMER0 ======================================================*/
#int_TIMER0
void RTCC_isr()
{
/*
x++;
if (x==3) set_RTCC(100); // porque he tenido que redondear dar más tiempo (retardo) para que no vibre?
if (x>=4)
{
tick=TRUE;
x=0;
}
*/
}
/* Monitorizacion ===========================================================*/
void motorizacion(int8 valor)
{
switch(valor)
{
// motores parados
case 1:
duty_pwm[MOTOR_DERECHO]=MOTOR_PARADO;
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_PARADO;
// printf ("Motores parados nr");
break;
// Hacia adelante a tope
case ADELANTE:
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ADELANTE_RAPIDO; // motor izquierdo adelante
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ADELANTE_RAPIDO; // motor derecho adelante
// printf ("Hacia adelante nr");
break;
// Hacia la izquierda ***
case IZQUIERDAS:
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_PARADO; // motor izquierdo parado
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ADELANTE_RAPIDO; // motor derecho hacia adelante
// printf ("A izquierdas nr");
break;
// Hacia la derecha ***
case DERECHAS:
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ADELANTE_RAPIDO; // motor izquierdo hacia adelante
duty_pwm[MOTOR_DERECHO]=MOTOR_PARADO; // motor derecho parado
// printf ("A derechas nr");
break;
// Hacia atras ***
case 5:
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ATRAS_RAPIDO; // motor izquierdo hacia atras
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ATRAS_RAPIDO; // motor derecho hacia atras
// printf ("Atras nr");
break;
case 6: // Giro izquierda
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ATRAS_RAPIDO; // motor izquierdo hacia atras
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ADELANTE_RAPIDO; // motor derecho hacia adelante
// printf ("Giro izquierdas nr");
break;
case 7: // Giro derechas
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ADELANTE_RAPIDO; // motor izquierdo hacia adelante
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ATRAS_RAPIDO; // motor derecho hacia atras
// printf ("Giro derechas nr");
break;
case 8: // marchas lentas centrada
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_CENTRADO; // motor izquierdo centrado
duty_pwm[MOTOR_DERECHO]=MOTOR_CENTRADO; // motor derecho centrado
// printf ("Marcha lenta centrado. Preparado para ajustesnr");
break;
case 9: // marchas lenta1 hacia adelante
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ADELANTE_LENTO1; // motor izquierdo lento hacia adelante
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ADELANTE_LENTO1; // motor derecho lento hacia adelante
// printf ("Marcha lenta 1 hacia adelantenr");
break;
case 10: // marchas lenta2 hacia adelante
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ADELANTE_LENTO2; // motor izquierdo lento 2 hacia adelante
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ADELANTE_LENTO2; // motor derecho lento 2 hacia adelante
// printf ("Marcha lenta 2 hacia adelantenr");
break;
case 11: // marchas lenta1 hacia atras***
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_IZQUIERDO_ATRAS_LENTO1; // motor izquierdo lento hacia atras
duty_pwm[MOTOR_DERECHO]=MOTOR_DERECHO_ATRAS_LENTO1; // motor derecho lento hacia atras
// printf ("Marcha lenta 1 hacia atrasnr");
break;
default : // printf("Comando no reconocido");
}
}
/* Secuenciador ===========================================================*/
void secuenciador (void)
{
static int Contador;
set_adc_channel(0);
delay_us(3);
ldr_izquierda_valor=read_adc();
set_adc_channel(1);
delay_us(3);
ldr_derecha_valor=read_adc();
set_adc_channel(2);
delay_us(3);
ldr_centro_valor=read_adc();
if (contador++>400)
{
printf("-- Izquierda %3u ----- Derecha %3u ----- Centro %3u nr",ldr_izquierda_valor,ldr_derecha_valor,ldr_centro_valor);
Contador=0;
}
movimiento=ADELANTE;
if ((ldr_centro_valor-ldr_izquierda_valor)>50) movimiento=IZQUIERDAS;
if ((ldr_centro_valor-ldr_derecha_valor)>50) movimiento=DERECHAS;
motorizacion(movimiento);
}
/* Main =====================================================================*/
void main()
{
int16 contador;
setup_counters(RTCC_INTERNAL,RTCC_DIV_64|RTCC_8_BIT); // TIMER0: Clock Interno y Preescaler
// setup_timer_1(T1_DISABLED);
// setup_timer_2(T2_DISABLED,0,1);
// setup_comparator(NC_NC_NC_NC);
// setup_vref(FALSE);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports( ALL_ANALOG );
set_tris_b(0x00);
disable_interrupts(GLOBAL);
enable_interrupts(int_TIMER0);
enable_interrupts(int_rda);
enable_interrupts(GLOBAL); // Habilito Interrupciones
output_low(PIN_B0);
output_low(PIN_B1);
duty_pwm[MOTOR_IZQUIERDO]=MOTOR_PARADO;
duty_pwm[MOTOR_DERECHO]=MOTOR_PARADO;
retardo=0;
dato=0;
do
{
if (tick==TRUE)
{
if (duty_pwm[0])
{
output_high(PIN_B0);
permiso_pwm[0]=TRUE;
}
if (duty_pwm[1])
{
output_high(PIN_B1);
permiso_pwm[1]=TRUE;
}
tick=FALSE;
}else secuenciador();
timer0=get_timer0();
if (permiso_pwm[0]==TRUE)
{
if (timer0>=duty_pwm[0])
{
output_low(PIN_B0);
permiso_pwm[0]=FALSE;
}
}
if (permiso_pwm[1]==TRUE)
{
if (timer0>=duty_pwm[1])
{
output_low(PIN_B1);
permiso_pwm[1]=FALSE;
}
}
} while(true);
}
Antes de nada gracias Heli por tus respuestas,
he probado de insertar ese código que enviaste dando el mismo resultado.Había probado algo parecido pero aunque no le ponga el retardo, si la interrupción de TMR0 está desabilitada la salida es correcta. (aunque supingo que el buffer se hinfla XD)
El código lo he tenido que tocar un poco porque si la comparación de la variable es >254 deja de funcionar. (alguien sabe por qué ?;-)) He probado unsigned int16 y tampoco. Al final dos bucles (contador1 y contador2).
Queda así :
if (contador1++>254)
{
contador1=0;
if (contador2++>200){
printf("-- Izquierda %3u ----- Derecha %3u ----- Centro %3u nr",ldr_izquierda_valor,ldr_derecha_valor,ldr_centro_valor);
contador2=0;
}
}
Con esto consigo un delay de aprox.9 sg. entre printf.
Entonces,
la salida con TMR0 enable es:
-- AzquerAa 51A----ADeechA 19 A--- AenroA135
-- IquAera A47 --A- erAch A5 ---A CntAo 18A
-- IAquerdA 19 A--- AerchA 8 -A-- CAnto A20
-- IAquerAa 47A---- AerchA 5 A--- CAnto A19A
--IzqAiedaA14 -A-- DAreca A86--A--CeAtr 11A
--IzqAiedaA14 -A-- DAreca A86--A--CeAtro11A
saltándose cualquier carácter (incluso el retorno y avance) . Parece un machaque de información pero no veo la conexión con el TMR0.
Con TMR0 disable:
-- Izquierda 172 ----- Derecha 145 ----- Centro 164
-- Izquierda 171 ----- Derecha 144 ----- Centro 163
-- Izquierda 173 ----- Derecha 144 ----- Centro 164
-- Izquierda 171 ----- Derecha 144 ----- Centro 163
Perfecto y sin ningún tipo de error.
Otra cosa curiosa. Si está el TMR0 enabled, cuando cargo el programa con bootloader tengo que quitar tensión al micro y volvérsela a dar (no vale un reset). En cambio con TMR0 disabled no hace falta, carga el programa y a continuación empieza a emitir.
P.D. Lo de los tabuladores es verdad. Mi fuente está tabulada pero ni caso en el corta pega.
Hola TumBos, siento mucho tener que comunicarte que tu bug es un poco dificil de pillar. He probado tu código en un PIC16F876A (no en un PIC877A, pero solo he cambiado el include del comienzo y la selección de micro en el CCS) y a mi me va OK con RTCC o sin el, con el Hiperterminal y con el bootloader. No se que puede pasarte a ti.
He usado el Bootloader Plus:
http://heli.xbot.es/fd/bootloader.htm
y el CCS 3.236
¿Has probado a desconectar los motores? podría ser un fallo de alimentación.
PD. El bucle falla cuando la variable "static int contador" es mayor de 254 porque el CCS tiene la manía de hacer los "int" de 8 bits. Para hacerlos de 16 bit hay que poner "int16".
Ya no sé por donde tirar. He instalado CCS 3.236. El bootloader es el mismo que usaba(Shane Tolmie 9.50) y sigo con el mismo problema. ¿será del micro?es lo único que me queda. Los motores ni siquiera los tengo conectados. Bien filtradito todo y, nada que se empeña en darme problemas un triste puerto serie.
Gracias Heli por probarlo. Si descubro donde está el truco ya postearé la solución.
P.D. con esta versión lo del bucle >254 si que funciona (ya me había puesto unsigned int16 pero tampoco iba).Cosas de compiladores.XD supongo.