Professional Documents
Culture Documents
ENCODER
I. Nguyên lý:
Ta sử dụng L298 để đảo chiều quay cho động cơ. ADC sẽ dùng
để điều chỉnh độ rộng xung cho PWM. Dùng ngắt để đếm xung
đo được từ động cơ encoder . Còn timer1 để tạo thời gian trích
mẫu tính toán để ra được tốc độ của động cơ, sau đó truyền
thông tốc độ của động cơ lên máy tính.
Trong đó:
TS: Thời gian lấy mẫu (ms)
nS: Số xung Encoder xuất ra trong thời gian TS
V = (nS*1000*60)/(N*TS) (vòng/phút)
IV. Code
Thư viện ADC
void ADC_Init()
{
ADCON0 = 0x81; //kenh0, tan so 32, kich hoat
ADC
ADCON1 = 0x80; //kieu ghi du lieu vao thanh
ghi(du lieu 16bit theo thu tu 10bit)
}
unsigned int ADC_Read(unsigned char channel)
{
if(channel > 7)
return 0;
ADCON0 &= 0xC5;
ADCON0 |= channel << 3;
__delay_ms(2);
GO_nDONE = 1;
while(GO_nDONE);
return((ADRESH<<8) + ADRESL);
}
Thư viện LCD
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
void Lcd_Port(char a)
{
if(a & 1)
D4 = 1;
else
D4 = 0;
if(a & 2)
D5 = 1;
else
D5 = 0;
if(a & 4)
D6 = 1;
else
D6 = 0;
if(a & 8)
D7 = 1;
else
D7 = 0;
}
//////////////////
void Lcd_Cmd(char a)
{
RS = 0; // => RS = 0
Lcd_Port(a);
EN = 1; // => E = 1
__delay_ms(4);
EN = 0; // => E = 0
}
/////////////////
void Lcd_Init()
{
Lcd_Port(0x00);
__delay_ms(20);
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
/////////////////////////////////////////////////////
Lcd_Cmd(0x02);
Lcd_Cmd(0x02);
Lcd_Cmd(0x08);
Lcd_Cmd(0x00);
Lcd_Cmd(0x0C);
Lcd_Cmd(0x00);
Lcd_Cmd(0x06);
}
//////////////
Lcd_Clear()
{
Lcd_Cmd(0);
Lcd_Cmd(1);
}
//////////////////
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a == 1)
{
temp = 0x80 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
else if(a == 2)
{
temp = 0xC0 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
}
////////////
void Lcd_Write_Char(char a)
{
char temp,y;
temp = a&0x0F;
y = a&0xF0;
RS = 1; // => RS = 1
Lcd_Port(y>>4); //Data transfer
EN = 1;
__delay_us(40);
EN = 0;
Lcd_Port(temp);
EN = 1;
__delay_us(40);
EN = 0;
}
#ifndef XC_HEADER_TEMPLATE_H
#defineXC_HEADER_TEMPLATE_H
#include <xc.h> // include processor files - each
processor file is guarded.
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XC_HEADER_TEMPLATE_H */
#include <xc.h>
long freq;
#define TMR2PRESCALE 4
//#define _XTAL_FREQ 20000000
int PWM_Max_Duty()
{
return
(_XTAL_FREQ/(freq*TMR2PRESCALE));
}
PWM2_Init(long fre)
{
PR2 =
(_XTAL_FREQ/(fre*4*TMR2PRESCALE))-1;
freq = fre;
}
#if TMR2PRESCALAR == 1
T2CKPS0 = 0
T2CKPS1 = 0
#elif TMR2PRESCALAR == 4
T2CKPS0 = 1;
T2CKPS1 = 0;
#elif TMR2PRESCALAR == 16
T2CKPS0 = 1;
T2CKPS1 = 1;
#endif
TMR2ON = 1; // kích ho?t timer2
TRISC2 = 0; //cho phép ccp1 ho?t ??ng
}
//////
PWM2_Start()
{
CCP2CONbits.CCP2M3 = 1;
CCP2CONbits.CCP2M2 = 1;
#if TMR2PRESCALE == 1
T2CKPS0 = 0;
T2CKPS1 = 0;
#elif TMR2PRESCALE == 4
T2CKPS0 = 1;
T2CKPS1 = 0;
#elif TMR2PRESCALE == 16
T2CKPS0 = 1;
T2CKPS1 = 1;
#endif
TMR2ON = 1;
TRISC1 = 0;
}
/////
//cai dat va chon do rong xung
void duty_cycle(unsigned char ccp, unsigned int
duty)
{
switch (ccp) {
case 1:
{
if (duty < 1024) {
duty = ((float) duty / 1023) * PWM_Max_Duty();
CCP1X = duty & 2;
CCP1Y = duty & 1;
CCPR1L = duty >> 2;
}
}
break;
case 2:
{
if (duty < 1024) {
duty = ((float) duty / 1023) * PWM_Max_Duty();
CCP2X = duty & 2;
CCP2Y = duty & 1;
CCPR2L = duty >> 2;
}
}
break;
}
}
Main chính
#include <xc.h>
#include <pic.h>
#include <pic16f877a.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
// CONFIG
#pragma config FOSC = HS // Oscillator
Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog
Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up
Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out
Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage
(Single-Supply) In-Circuit Serial Programming
Enable bit (RB3 is digital I/O, HV on MCLR must
be used for programming)
#pragma config CPD = OFF // Data EEPROM
Memory Code Protection bit (Data EEPROM code
protection off)
#pragma config WRT = OFF // Flash Program
Memory Write Enable bits (Write protection off; all
program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program
Memory Code Protection bit (Code protection off)
#include "ADC.h"
#include "LCD.h"
#include "PWM.h"
#define timerstart 3035
unsigned int xungdem, xungdo, chieu, aaa;
char s[20], c[20];
void main(void) {
unsigned int toc_do;
TRISD = 0x00;
TRISC = 0x00;
TRISBbits.TRISB0 = 1;
TRISAbits.TRISA0=1;
TRISBbits.TRISB1=1;
PWM2_Init(10000);
Lcd_Init();
Timer1_Init();
ADC_Init();
INTCONbits.GIE = 1 ; // ngat toan cuc
INTCONbits.INTE = 1; // ngat cuc bo
OPTION_REGbits.INTEDG = 1; //ngat
canh len
while(1)
{
if(chieu==1)
{
sprintf(s,"(Thuan) duty:%d",aaa/10-2);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(s);
}
if(chieu==0)
{
sprintf(s,"(Nguoc) duty:%d",aaa/10-2);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(s);
}
Lcd_Write_Char(37);
Lcd_Write_Char(" ");
toc_do =(xungdo*600)/334;
Lcd_Set_Cursor(1,1);
sprintf(c,"Toc Do: %d v/p ",toc_do);
Lcd_Write_String(c);
aaa=ADC_Read(0);
duty_cycle(2, aaa);
PWM2_Start();
}