|
|
View previous topic :: View next topic |
Author |
Message |
ze.vana
Joined: 11 Jun 2011 Posts: 15
|
Rotary Encoder final |
Posted: Sun Sep 04, 2011 8:14 am |
|
|
Here in my Country there are not dsPIC or PICs with QEI MODULATE ,then I decided to do
that project. This is ROTARY ENCODER'S final version with 32 bits, he measures counterclockwise
and anti-counterclockwise rotations. I've tested it with industrial TTL encoders (Heidenhein and Sick
2500 pulse/revolution , both from Germany) used in CNC machines, and I can guarantee, it makes
measurements super fast, without losing position.
First project:
http://www.ccsinfo.com/forum/viewtopic.php?. I’ve copied the flex_lcd from this Forum, I hope the author does not mind, this Forum has helped me a lot, thanks all you guys!
Email [email protected]
Code: |
#include <18F4520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=40M)
#use RS232(baud=9600, parity=N, bits=8,xmit=pin_c6, rcv=pin_c7)
#include <flex_lcd.c>
#define tog1 (pin_d6)
#define led (pin_d0)//#define led (pin_d7)em casa é o d0
//#define DIR_1 (pin_d0)
//#define ZERO_2 input(pin_C3)//REFERENC input
#define DIR_2 (pin_d1)
#define ZERO input(pin_d2)
#define MENOS input(pin_d3)
int1 referen=0;
char signal;
int16 tmr0;
int16 tmr0xn=0;
int32 result0=0,real;
#bit pir0=0x0ff2.2 //timer0 overflow
int16 tmr1;
int16 tmr1xn=0;
int32 result1=0;
#bit pir1=0x0f9e.0 //timer1 overflow
int1 stopped;
int8 zerado = 0;
int16 tmr1H,tmr1L,tmr0H,tmr0L;//see line 129
int32 MAX=0,MIN=200,MEDIA,differen;//see line 122
#INT_TIMER2
void intt2_isr()
{
set_timer2(0);
tmr1=GET_TIMER1(); //get counter UP value
tmr0=GET_TIMER0(); //get counter DOWN value
// differen= result1 - real;
if(pir1==1)
{
tmr1xn++;
pir1=0;
}
if(pir0==1)
{
tmr0xn++;
pir0=0;
}
//--auto zero-------------------------- //positive
if(differen > 200000 && stopped==1 && zerado != 1 && signal== 43 && real < 65000)//zerar 1
{ //see line 131
result1= media;
set_timer1(media);
set_timer0(0);
tmr0xn=0;
tmr1xn=0;
zerado=1;
} //positive
if(differen > 200000 && stopped==1 && zerado != 2 && signal== 43 && real < 65000)//zerar 2
{ //see line 150
result1= media;
set_timer1(media);
set_timer0(0);
tmr0xn=0;
tmr1xn=0;
zerado=2;
}
//----auto zero--end--------------------
/*
if(referen==0 && zero_2==1)
{
result1= 0;
set_timer1(0);
set_timer0(0);
tmr0xn=0;
tmr1xn=0;
referen=1;
}
*/
}
#INT_TIMER3
void ext3_isr()
{
SET_TIMER3(0);
min=max;
if(real < min)
{
min= real;
}
if(real > max )
{
MAX =real;
}
if(max > min )
{
media = min;
}
else
{
media= max;
}
}
void main(){
set_tris_a(0xff);
set_tris_b(0xff);
set_tris_c(0xff);
SET_TRIS_D(0x00);
output_d(0x00);
//TIMER0 16 bits as counter /DOWN
SETUP_TIMER_0(RTCC_EXT_H_TO_L|RTCC_DIV_1);
SET_TIMER0(0);
DISABLE_INTERRUPTS ( GLOBAL );
// TIMER1 16 bits as counter /UP
SETUP_TIMER_1(T1_EXTERNAL | T1_DIV_BY_1 );
ext_int_edge(H_TO_L);
set_timer1(0);
//TIMER2 INTERNAL
SETUP_TIMER_2( T2_DIV_BY_1,0xc0,2);
set_timer2(0);
enable_interrupts(int_timer2);
enable_interrupts(global);
//TIMER3 INTERNAL
SETUP_TIMER_3(T3_INTERNAL |T3_DIV_BY_4); // TIMER3 INTERNAL
SET_TIMER3(1000);
enable_interrupts(INT_TIMER3 );
enable_interrupts(global);
lcd_init();//It must be here or else you got instability.
stopped=1;
tmr1L=0; tmr1H=100;tmr0L=0;tmr0H=100;
while(true)
{
tmr1L=GET_TIMER1(); //get timer0/1 initial value
tmr0L=GET_TIMER0(); //see line 150
differen= result1 + result0;//value to zero encoder
result0=(65536 * tmr0xn) + tmr0;//gets 32 bits timer0/1
result1=(65536 * tmr1xn) + tmr1;
if(result1 >= result0)
{
real= result1 -result0;// get plus real value
signal='+';
}
else
{
real= result0 -result1;// get minus real value
signal='-';
}
printf(LCD_PUTC"\f\%c%Lu %Lu\n",signal,real,differen );
printf(LCD_PUTC "\n1:%Lu 0:%Lu",result1,result0 );
//printf("\f r:%lu t1:%lutmr1xn:%lu", result0 ,tmr0,tmr0xn);tests
//printf("\f %u",signal );
delay_ms(100);
tmr1H=GET_TIMER1(); // get timer0/1 final value
tmr0H=GET_TIMER0(); //see line 119
if(tmr1H == tmr1L && tmr0H == tmr0L)// if all equal, encoder is stopped
{ //see line 129
delay_ms(700);
stopped=1;//flag
output_high led;
}
else
{
stopped=0;
output_low led;
}
}
}
|
|
|
|
quadro
Joined: 09 Feb 2012 Posts: 4
|
|
Posted: Thu Feb 09, 2012 7:43 am |
|
|
Thanks for very useful code.
I'm working on position and speed reading, but I'm using 18f4431.
18f4431 has some disadvantages (program memory low, price high...).
I have a lot of 18f46k20. Your code is a big advantage for me. Thanks. |
|
|
ze.vana
Joined: 11 Jun 2011 Posts: 15
|
|
Posted: Thu Feb 09, 2012 3:00 pm |
|
|
Thanks for appreciating.
Well I have received some questions on how it works, then as my english is not so good. And I think this code could be a little difficult to understand, I am putting the basic code.
The used additional Hardware I can send by email for who want.
BASIC CODE:
Code: |
//BASIC CODE
#include <18F4520.h> //<18F452colt.h> or coltbootloader
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=40M)
#include <flex_lcd.c>
//encoder--------------------------------------------encoder-----
int16 T0,T1,R; //float R; //R is the result from T1-T0
//--------------------------
void print_lcd(void){
T1= GET_TIMER1(); //get counter UP value
T0= GET_TIMER0(); //get counter DOWN value
R= T1-T0; //R is the result from Timer1-Timer0
printf(LCD_PUTC"\f\REAL:%Lu \n",R);
printf(LCD_PUTC"\nR=T1:%Lu-T0:%Lu",t1,t0 );
delay_ms(200);
if(t0 > t1){ //Tmr0 never can be grater than Tmr1,
SET_TIMER0(0); //if so reset Timers
SET_TIMER1(0);
}
}
//#int_timer2
void timer_t2()
{
set_timer2(250);
// lcd_init();
// delay_ms(100);
// print_lcd();
}
//encoder------------end--------------------------encoder--------
void main (void)
{
set_tris_a(0xff);
set_tris_b(0x00);
set_tris_c(0xff);
set_tris_d(0xff);
//TIMER0 16 bits as counter /DOWN
SETUP_TIMER_0(RTCC_EXT_H_TO_L|RTCC_DIV_1);
SET_TIMER0(0);
// TIMER1 16 bits as counter /UP
SETUP_TIMER_1(T1_EXTERNAL | T1_DIV_BY_1 );
set_timer1(0);
lcd_init();
delay_ms(500);
while(true)
{
print_lcd();
}
} |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|