Sie sind auf Seite 1von 18

SEGUIDOR DE LINEAS PIC 16F877A

Un robot seguidor de lineas esta conformado por tres


partes fundamentales:

1º Los ojos: observar la linea, que se haría obteniendo el


contraste negro que produce la linea con respecto al
entorno blanco, utilizando una serie de sensores
infrarrojos.

2º El cerebro, este va a decidir que camino


tomar según los datos que le suministren los ojos, en
este apartado se utiliza un pic para decidir el rumbo:
derecha, izquierda, adelante, atrás y las estrategias
de corrección para no perder la linea.

3º Los pies: la tracción el movimiento: dos ruedas dan el movimiento que dependiendo de las
decisiones que tome el cerebro giraran a la misma velocidad, o creara una diferencia entre
ambas para dar un giro en un sentido u otro.

El software necesario para la programación del cerebro y la simulación electrónica es PIC-C


para la programación e ISIS PROFESSIONAL para la simulación electrónica.

Ahora hablemos del apartado que corresponde a la programación que es el mas importante
en este robot: el cerebro, PIC 16F877A.

Control de puertos:

El pic posee 5 puertos de entrada salida I/O son A,B,C,D,E. cada puerto tiene 8 pines que se
numeran de 0 a 7. Su configuración para decidir qué pines serán salidas o entradas se hace
mediante la funcion SET_TRIS_X(HEX) donde X sera el puerto que se quiere configurar y HEX
un numero hexadecimal de la forma 0xYZ , Y: numero hexadecimal de rango 0 a F, controla los
pines 7,6,5,4. Z: numero hexadecimal de rango 0 a F, controla los pines 3,2,1,0.

Control de PIN:

Entrada: para obtener el estado lógico (0-1) de un pin de entrada por cada ciclo de programa
se utiliza la función INPUT(PIN_XN), X:para el puerto, N: para el pin (0-7).

Ejemplo: while ( !input(PIN_B1) );

Salida: para llevar el estado lógico (0-1) a un pin de salida existen varias funciones que se
pueden utilizar:
OUTPUT_BIT(PIN_XN,ESTADO): X:puerto, N:pin, ESTADO: el estado lógico (0-1) que se desea
sacar por el pin de salida.

OUTPUT_HIGH(PIN_XN): X:puerto, N:pin, esta funcion lleva la salida del pin automaticamente
a 1 logico.

OUTPUT_LOW(PIN_XN): X:puerto, N:pin, esta funcion lleva la salida del pin automaticamente a
0 logico.

Control de PWM:

En este pic los pines de salida del PWM están en el puerto c específicamente en los pines
PIN_C2 que corresponde al PWM1 y el PIN_C1 que corresponde al PWM2. Para obtener una
señal particular en cualquiera de los PWM se debe calcular el periodo del pic, el periodo del
PWM con la frecuencia deseada, y asi calcular el PR2 necesario para configurar la señal de
salida del PWM. El PWM está asociado al TIMER2.

Ejemplo: si se quiere como salida una frecuencia de 20khz con un ciclo de servicio o trabajo
del 50% entonces se hacen los cálculos siguientes:

Periodo del PWM = 1/20khz = 50us

Periodo del pic = 1/20Mhz = 50ns

PR2 = (periodo PWM/(4*periodo PIC*Prescaler))-1

PR2 = (50us/(4*50ns*1))-1=249

Teniendo esta información podemos configurar el PWM por código.

setup_ccp1(ccp_PWM); //activa el pin_c2 como salida PWM, antes activar el pin como salida.

setup_timer_2(prescaler,PR2,postscaler);

setup_timer_2(t2_div_By_1,249,1); //

Ahora debemos calcular el tamaño del DUTY (ciclo de servicio) que aumentara o disminuira el
tiempo de señal alta por cada ciclo, como se muestra en la figura:

DUTY= t alta,

Un led con poca iluminación.


Un led con mucha iluminación

DUTY = Periodo PWM * ciclo de servicio(porcentaje) / periodo PIC * Prescaler

DUTY = 50us*0.5/(50ns*1) = 500 (al 50%)

set_pwm_duty(500);

Habiendo conocido la teoría necesaria para comprender las partes necesarias para la
programación ahora veremos el código en pic-c.
Simulacion en isis

Cargando el codigo en isis, usando el .hex generado por pic-c abriendo las propiedades del pic.
#include<p18f452.h>

#include<adc.h> //libreria conversor

#include<delays.h>

#include<timers.h>

#include<pwm.h>

#define SINGLE_OUT 0b00000000

#define PWM_MODE1 0b11111110

int
arranque=0,dato1,dato2,dato3,dato4,dato5,dato6,dato7,dato8,d1=0,d2=0,d3=0,d4=0,d5=0,d6=0,d7=0,d
8=0,valor,der=0,izq=0;

void velocidad1()// subrutina velocidad 1

OpenTimer2(TIMER_INT_OFF&T2_PS_1_16);

SetOutputPWM1(SINGLE_OUT,PWM_MODE1);

OpenPWM1(11);

OpenPWM2(11);

SetDCPWM1(50);

SetDCPWM2(50);

void velocidad2()// subrutina velocidad 2

OpenTimer2(TIMER_INT_OFF&T2_PS_1_16);

SetOutputPWM1(SINGLE_OUT,PWM_MODE1);

OpenPWM1(11);

OpenPWM2(11);

SetDCPWM1(30);

SetDCPWM2(30);

void main(void)

ADCON1=0x00; // determinar entradas analogas y digitales

TRISA=0xFF; // se programan las entradas analogas

TRISE=0x07; // se programan las entradas analogas

TRISCbits.RC3=0; //LED 1
TRISDbits.RD0=0; //LED 2

TRISDbits.RD1=0; //LED 3

TRISDbits.RD2=0; //LED 4 - INDICATIVO DE EL BOTON DE ARRANQUE

TRISCbits.RC7=1; //BOTON ARRANQUE

TRISCbits.RC6=1; //BOTON PARO

TRISDbits.RD5=0; //entradas puente H

TRISDbits.RD6=0; //entradas puente H

TRISBbits.RB6=0; //entradas puente H

TRISBbits.RB7=0; //entradas puente H

OpenADC(ADC_FOSC_8 & ADC_RIGHT_JUST & ADC_8ANA_0REF,ADC_CH0 & ADC_INT_OFF); //


Programacion general CAD (conversor analogo digital)

PORTDbits.RD5=0;

PORTDbits.RD6=0;

PORTBbits.RB6=0;

PORTBbits.RB7=0;

PORTDbits.RD0=0;

PORTCbits.RC3=0;

PORTDbits.RD1=0;

PORTDbits.RD2=0;

while(1)

valor=500;

if(PORTCbits.RC7==1)// si oprimimos boton arranque

arranque=1;

while(arranque==1)

PORTDbits.RD2=1;

SetChanADC(ADC_CH0);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion


dato1=ReadADC();

SetChanADC(ADC_CH1);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato2=ReadADC();

SetChanADC(ADC_CH2);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato3=ReadADC();

SetChanADC(ADC_CH3);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato4=ReadADC();

SetChanADC(ADC_CH4);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato5=ReadADC();

SetChanADC(ADC_CH5);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato6=ReadADC();

SetChanADC(ADC_CH6);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato7=ReadADC();

SetChanADC(ADC_CH7);

ConvertADC(); //comienza conversion

while(BusyADC()); // espera hasta que se efectue la conversion

dato8=ReadADC();

if(dato1>=valor) { d1=1; } // le asignamos valor a


la lectura del sensor

else { d1=0; }
if(dato2>=valor) { d2=1; }

else { d2=0; }

if(dato3>=valor) { d3=1; }

else { d3=0; }

if(dato4>=150) { d4=1; }

else { d4=0; }

if(dato5>=150) { d5=1; }

else { d5=0; }

if(dato6>=valor) { d6=1; }

else { d6=0; }

if(dato7>=valor) { d7=1; }

else { d7=0; }

if(dato8>=valor) { d8=1; }

else { d8=0; }

if(d4==1 && d5==1) // sensores de la mitad acitvados

izq=0;

der=0;

PORTDbits.RD5=1;

PORTDbits.RD6=0;

PORTBbits.RB6=0;

PORTBbits.RB7=1;

PORTDbits.RD0=1;

PORTCbits.RC3=0;

PORTDbits.RD1=0;

velocidad1();

if(d4==1 && d5==0) // un poco a la izquierda

PORTDbits.RD5=1;

PORTDbits.RD6=0;

PORTBbits.RB6=0;
PORTBbits.RB7=0;

PORTCbits.RC3=1;

PORTDbits.RD0=0;

PORTDbits.RD1=0;

toavelocia1();

if(d4==0 && d5==1) // un poco a la derecha

PORTDbits.RD5=0;

PORTDbits.RD6=0;

PORTBbits.RB6=0;

PORTBbits.RB7=1;

PORTCbits.RC3=0;

PORTDbits.RD0=0;

PORTDbits.RD1=1;

toavelocia1();

if(d3==1 && d2==1 && d5==0)

PORTDbits.RD5=1;

PORTDbits.RD6=0;

PORTBbits.RB6=1;

PORTBbits.RB7=0;

PORTCbits.RC3=1;

PORTDbits.RD0=0;

PORTDbits.RD1=0;

toavelocia2();

if(d4==0 && d6==1 && d7==1)

{
PORTDbits.RD5=0;

PORTDbits.RD6=1;

PORTBbits.RB6=0;

PORTBbits.RB7=1;

PORTCbits.RC3=0;

PORTDbits.RD0=0;

PORTDbits.RD1=1;

toavelocia2();

if(d8==1 && d7==1 && d6==1 && d5==1) //Giro con curva izquierda
de 90 gradoa

izq=1;

if(izq==1)

PORTDbits.RD5=0;

PORTDbits.RD6=1;

PORTBbits.RB6=0;

PORTBbits.RB7=1;

toavelocia2();

if(d4==1 && d5==1)

izq=0;

if(d1==1 && d2==1 && d3==1 && d4==1) //Giro con curva derecha
de 90 gradoa

der=1;

if(der==1)

PORTDbits.RD5=1;
PORTDbits.RD6=0;

PORTBbits.RB6=1;

PORTBbits.RB7=0;

toavelocia2();

if(d4==1 && d5==1)

der=0;

if(d7==1 && d8==1 && d6==0 && d5==1 ) //Giro con curva izquierda
de 45 gradoa

izq=1;

if(izq==1)

PORTDbits.RD5=0;

PORTDbits.RD6=1;

PORTBbits.RB6=0;

PORTBbits.RB7=1;

toavelocia2();

Delay10KTCYx(25);

if(d4==1 && d5==1)

izq=0;

if(d2==1 && d1==1 && d3==0 && d4==1) //Giro con curva derecha
de 45 gradoa

der=1;

if(der==1)
{

PORTDbits.RD5=1;

PORTDbits.RD6=0;

PORTBbits.RB6=1;

PORTBbits.RB7=0;

toavelocia2();

Delay10KTCYx(25);

if(d4==1 && d5==1)

der=0;

if(PORTCbits.RC6==1)// si se orpime boton STOP

PORTDbits.RD2=0;

PORTDbits.RD5=0;

PORTDbits.RD6=0;

PORTBbits.RB6=0;

PORTBbits.RB7=0;

PORTCbits.RC3=0;

PORTDbits.RD0=0;

PORTDbits.RD1=0;

arranque=0;

}
Functional Description
The QTR-8A reflectance sensor array is intended as a line sensor, but
it can be used as a general-purpose proximity or reflectance sensor. The
module is a convenient carrier for eight IR emitter and receiver
(phototransistor) pairs evenly spaced at intervals of 0.375" (9.525 mm).
Each phototransistor is connected to a pull-up resistor to form a voltage
divider that produces an analog voltage output between 0 V and VIN
(which is typically 5 V) as a function of the reflected IR. Lower output
voltage is an indication of greater reflection.

The outputs are all independent, but the LEDs are arranged in pairs to
halve current consumption. The LEDs are controlled by a MOSFET with
a gate normally pulled high, allowing the LEDs to be turned off by setting
the MOSFET gate to a low voltage. Turning the LEDs off might be
advantageous for limiting power consumption when the sensors are not
in use or for varying the effective brightness of the LEDs through PWM
control.

The LED current-limiting resistors for 5 V operation are arranged in two


stages; this allows a simple bypass of one stage to enable operation at
3.3 V. The LED current is approximately 20-25 mA, making the total
board consumption just under 100 mA. The schematic diagram of the
module is shown below:
For a similar array with three sensors, consider our QTR-3A reflectance
sensor array. The sensors on the QTR-8A are also available individually
as the QTR-1A reflectance sensor, and the QTR-L-1A is an alternative
designed to be used with the board perpendicular to the surface.

QTR sensor size comparison. Top row: QTRX-HD-07, QTR-HD-07; middle row:
QTR-3, QTR-1, QTR-L-1; bottom row: QTR-8.

Specifications
 Dimensions: 2.95" x 0.5" x 0.125" (without header pins installed)
 Operating voltage: 3.3-5.0 V
 Supply current: 100 mA
 Output format: 8 analog voltages
 Output voltage range: 0 V to supplied voltage
 Optimal sensing distance: 0.125" (3 mm)
 Maximum recommended sensing distance: 0.25" (6 mm)
 Weight without header pins: 0.11 oz (3.09 g)
Interfacing with the QTR-8A Outputs
There are several ways you can interface with the QTR-8A outputs:

 Use a microcontroller’s analog-to-digital converter (ADC) to measure


the voltages.
 Use a comparator with an adjustable threshold to convert each analog
voltage into a digital (i.e. black/white) signal that can be read by the
digital I/O line of a microcontroller.
 Connect each output directly to a digital I/O line of a microcontroller
and rely upon its internal comparator.
This last method will work if you are able to get high reflectance from
your white surface as depicted in the left image, but will probably fail if
you have a lower-reflectance signal profile like the one on the right.

QTR-1A output 1/8" away from a QTR-1A output 3/8" away from a
spinning white disk with a black line spinning white disk with a black line
on it. on it.

Our Pololu AVR library provides functions that make it easy to use these
sensors with our Orangutan robot controllers; please see the QTR
Reflectance Sensors section of our library command reference for more
information. We also have a Arduino library for these sensors.
Breaking the Module in Two
If you don’t need or cannot fit all eight sensors, you can break off two
sensors and still use all 8 sensors as two separate modules, as shown
below. The PCB can be scored from both sides along the perforation
and then bent until it snaps apart. Each of the two resulting pieces will
function as an independent line sensor.

Included Components
This module ships with a 25-pin 0.1" header strip and a 100 Ohm
through-hole resistor as shown below.
Técnicas en ingeniería electrónica

Curso: Microcontroladores

Informe: Seguidor de linea

Docente: Euler Deza Figueroa

Integrantes:
 Ponce Camarena Wesley
 Sirlupu Lopez Christian
 Araujo Huachaca Marco

Semestre: Cuarto

Bloque:403

Fecha de entrega: 25 de junio de 2019

Das könnte Ihnen auch gefallen