Servomotor con fotoresistencia (PIC 18F45K50) (DUDAS)

Hola! Tengo algunas dudas sobre mi practica, se que ya casi lo tengo hecho solo que hay un error que no hace que gire bien el motor, espero que me puedan ayudar con mi programacion. Estoy usando X-trainer para programar el PIC 18F45K50.

Me pidieron hacer una practica en donde usaré:
*Dos fotos resistencias
* Un servomotor

Funcionamiento:
*Al detectar luz en una de las foto resistencias girará el servomotor hacia la derecha.
*Al detectar luz en la otra foto resistencias girará el servomotor hacia la izquierda.
*Cuando no detecte luz en ninguna de las foto resistencias que gire exactamente en 90 grados. (En medio del servo).


Este es mi codigo:

Código:
#include <18F45K50.h>
#DEVICE ADC=10;
#use delay (internal=48Mhz)
#build(reset=0x02000,interrupt=0x02008)
#org 0x0000,0x1FFF{}



int flagt0;
// int16 ton=2500; //1500,2500.
int16 variable;
float vad;
int16 v2;
float vad2;

#int_TIMER0
void TIMER0_isr(){
output_high(PIN_C2);
flagt0=1;
set_timer0(5780);// calculandolo en 20ms
}
int16 pos(int x)
{
int16 tiempo;
tiempo=11.11*x+500;
return tiempo;
}

void main(){
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc_ports(sAN0 |sAN1);
set_tris_c(0b11111011);

setup_timer_0(T0_INTERNAL|T0_DIV_4);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
   set_adc_channel(0);
    set_adc_channel(1);
   delay_ms(10);
  
   output_low(PIN_C2);
 while(TRUE)
 {
 variable=read_adc();
  v2=read_adc();
 vad = (5.0 * variable)/1024.0;
vad2 = (5.0 * v2)/1024.0;


 
  if (vad2 >= 4.0)
 {
 if (flagt0==1)
 {
 int16 angle=pos(180);
 delay_us(angle);
 output_low(PIN_C2);
 flagt0=0;
 }
 }
   if (vad >= 4.0)
 {
 if (flagt0==1)
 {
 int16 angle=pos(90);
 delay_us(angle);
 output_low(PIN_C2);
 flagt0=0;
 }
 }
 if (vad == vad2)
 {
  output_low(PIN_C2);
 }
  else
  {
  int16 angle=pos(0);
 delay_us(angle);
 output_low(PIN_C2);
 flagt0=0;
  }
 
 }
 }
 

D@rkbytes

Moderador
Solo tú entiendes el código porque no está comentado y lo único que está comentado es irrelevante.
Sin embargo, veo cosas extrañas...
Parece que utilizarás un bootloader.
La variable "tiempo" la declaras de 16 bits pero la usas como si fuera float al multiplicar por 11.11
La precarga del Timer0 a 16 bits con el preescaler 1:4 debería ser de 5536 para obtener un desborde más preciso cada 20 mS @ 48 MHz.
Cosa que no se va a cumplir porque según la hoja de datos la máxima frecuencia para HFINTOSC es de 16 MHz.
18F45K50 HFINTOSC.jpg
O sea que por ese lado ya vas mal y tendrás que cambiar el tipo de oscilador o la frecuencia.
Funcionamiento:
*Al detectar luz en una de las foto resistencias girará el servomotor hacia la derecha.
*Al detectar luz en la otra foto resistencias girará el servomotor hacia la izquierda.
*Cuando no detecte luz en ninguna de las foto resistencias que gire exactamente en 90 grados. (En medio del servo).
¿Y qué pasaría cuando las dos foto resistencias reciban luz al mismo tiempo?

Edit:
Encontré algo importante.
Como debes estar usando dos canales del ADC, debes establecer qué canal debe ser leído.
Esto lo estás haciendo solo al principio del programa y el canal predominante será el AN1
Esto no es correcto:
C:
    enable_interrupts(GLOBAL);
    set_adc_channel(0);
    set_adc_channel(1);
    delay_ms(10);
Debes establecer el canal ADC cada vez que quieras usarlo.
C:
    while (TRUE)
    {
        set_adc_channel(0);        // Establecer el canal AN0
        delay_us(20);
        variable = read_adc();
        
        set_adc_channel(1);        // Establecer el canal AN1
        delay_us(20);
        v2 = read_adc();
        
        vad = (5.0 * variable) / 1024.0;
        vad2 = (5.0 * v2) / 1024.0;
 
Darkbytes un par de preguntas te hago: si en un 16F887 declaramos #fuses INTRC_IO, como es correcto declarar el delay?

#use delay(clock=4Mhz)
#use delay(internal=4Mhz)

o las dos son validas?
Y la otra pregunta es, en este pic para declarar el pin RA0 como analogico, como no lei la hoja de datos ponia la siguiente instruccion :

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(AN0);

y no habia manera de que compilara hasta que cambie AN0 por 0x01 y entonces si, ya que es en hexagesimal, luego me dado cuenta que el error estaba en que hay que poner delante de AN0 una s, con esto ya si funciona.

Mi pregunta en este tema es la siguiente y es por que no me queda suficientemente claro el tema: supongamos que quiero hacer RA0, RA1 y RA2 analogicos y el resto entradas digital, la instruccion correcta seria esta?

setup_adc_ports(sAN0 | sAN1 | sAN2);
 

D@rkbytes

Moderador
Si usas #use delay (CLOCK = 4 MHz) tienes que usar el fuse INTRC_IO
Si usas #use delay (INTERNAL = 4 MHz) el compilador establece el fuse INTRC_IO
me he dado cuenta que el error estaba en que hay que poner delante de AN0 una s, con esto ya si funciona.
En el archivo 16F887.h se encuentran los nombres asignados y las constantes usadas por el compilador.
supongamos que quiero hacer RA0, RA1 y RA2 analógicos y el resto entradas digital, la instrucción correcta seria esta?

setup_adc_ports(sAN0 | sAN1 | sAN2);
Las configuraciones del conversor AD también las puedes encontrar en el archivo .h correspondiente.
Y sí, esa configuración es correcta porque en el PIC16F887 se pueden establecer los canales independientemente.
 
Creo que deberíais leeros mas las documentaciones de los integrados y adaptaros a usar menos bibliotecas del compilador.
Tan difícil es configurar el pic como pone el fabricante.
Si no estoy mal el comando delay_ms usa tmr0 y se define el ajuste en el compilador con delay.
No se por que pero yo deje de usar muchos comandos propios del compilador por razones de fallos y por no parar nunca el programa. No tengo 14 años para programar de esa manera

Un saludo
Otra las conversiones AD tienen mas ajustes a relación del osc y el tiempo de conteo RC del conversor AD. Leer mejor esa parte y la ecuación del contador, la suele tener puesta en la ficha del pic en la sección de conversiones AD...
Que tampoco pasa mucho. Las configuraciones de un pic son complicadas y mas de las series 18 en adelante... Eso sin contar con interrupciones de primer segundo y tercer grado
 
Última edición:

Temas similares


Arriba