Buenas a todos
Estoy realizando un proyecto con el pic184550 para controlar una brujula electronica que esta empotrada en un servomotor que permite el movimiento en 180°, de manera que si yo le indico una posicion especifica, ante perturbaciones al movimiento del sistema este vuelva a la posicion inicial (en mi caso a los 90°).
He tenido problemas para poder obtener datos de la brujula por medio de la comunicacion I2C asi que queria poner el codigo de lo que he realizado para ver si me puedan ayudar a encontrar el error que estoy cometiendo.
Gracias de antemano a todos los aportes
Como preambulo les explico ciertas caracteristicas del sistema:
- La brujula permite obtener por medio de la comunicacion I2C su posicion en grados con respecto a una referencia de 0° en direccion al Norte.
- Dentro de las especificaciones de la brujula se pide que el bus de comunicacion trabaje a una frecuencia de 160kHz y en caso de excederse hasta 1MHz utilizar delays de 50us entre las escrituras al registro de la brujula.
- El servomotor tiene una libertad de movimiento de hasta 180°
- La posicion fija o posicion en estado estable es a los 90°, es por esto que se calcula el error para calcular el tiempo del delay para permitir el movimiento del servomotor.
CODIGO:
#include <18F4550.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES MCLR //Master Clear pin enabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1 //No PLL PreScaler
#use delay(clock=20000000)
#use i2c(Master,Fast,sda=PIN_B0,scl=PIN_B1)
#define boton PIN_A3 // Entrada del boton
#define izq PIN_A1
#define der PIN_A2
#define led_0 portd,0 //Salidas a LED
#define led_1 portd,1
#define led_2 portd,2
#define led_3 portd,3
#define led_4 portd,4
#define led_5 portd,5
#define led_6 portd,6
#define led_7 portd,7
void leer_brujula();
void pwm_der();
void pwm_izq();
int brujula;
int referencia = 90;
int error;
int time;
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);
// TODO: USER CODE!!
while(true)
{
if (!input(boton))
{
leer_brujula(); //Llamo al modulo de comunicacion I2C para leer la posicion que tiene la brujula en grados
output_d(brujula); //Imprime en el puerto D el dato en bits que corresponde a los grado leido desde la brujula
if(brujula != 90) //Como el servomotor tiene una libertad de 180° se establece 90° como la posicion a la que debe regresar el sistema, posicion estable
{
if(brujula < 90){
error = referencia-brujula; //Se calcula la diferencia entre la posicion leida por la brujula y los 90°
time = error*5; //Se calcula el tiempo de delay que permanece en alto la señal que activa el movimiento del servo hacia la derecha
output_low(izq);
output_high(der); //Se activa la señal que mueve el servomotor a la derecha
delay_ms(time); //Tiempo que tarda la señal en alto
output_low(der);*/
}
if(brujula > 90){
error=brujula-consigna; //Se calcula la diferencia entre la posicion leida por la brujula y los 90°
time=error*5; //Se calcula el tiempo de delay que permanece en alto la señal que activa el movimiento del servo hacia la izquierda
output_high(izq); //Se activa la señal que mueve el servomotor a la izquierda
output_low(der);
delay_ms(time); //Tiempo que tarda la señal en alto
output_low(izq);*/
}
}
else{
output_low(der); //Mantiene en bajo la señal de movimiento del servomotor a la derecha
output_low(izq); //Mantiene en bajo la señal de movimiento del servomotor a la izq
output_d(brujula); //pone el valor de la brujula en binario en los pines RD0 A RD7
}
}
}
}
void leer_brujula()
{
int respaldo;
i2c_start(); //Start
i2c_write(0b11000000); //Control **Dirección del dispositivo con el último bit (R/W) en cero
i2c_write(0b1); //Direccion **Número de registro a leer
i2c_stop(); //Stop
i2c_start(); //Start
i2c_write(0b11000001); //Control para lectura **Número de registro a leer con el último bit (R/W) en uno
respaldo = i2c_read(); //Se lee los grados de la brujula y lo guardo en respaldo
brujula = respaldo; //guardo la información en la variable global grados
i2c_stop(); //Stop*/
}
---------------------------------------------------------------------------------------------------------------------------------------
Dentro de las posibles ideas que tengo que esto no me esta realizando lo que espero que sucediera es en cuanto a los tiempos de comunicacion del I2C. Creo que al trabajar con un cristal de 20MHz deberia de existir una manera de establecer la comunicacion al tiempo de 160KHz como especifica la hoja de datos de la brujula electronica, pero tengo falta de concepto en esa área.
Agradeceria bastante si alguien me pudiera ayudar en ver si tengo algun error en la forma que defino la comunicacion I2C y si tengo problemas de tiempos que talvez estoy leyendo varias veces el dato y no permite al pic realizar el analisis del grado leido desde el registro de la brujula.
Muchas Gracias de antemano por la ayuda B)