View previous topic :: View next topic |
Author |
Message |
asunca
Joined: 09 Sep 2005 Posts: 36
|
rotary encoder and printf.... |
Posted: Mon Sep 26, 2005 1:46 am |
|
|
i am building an encoder and nearly finished with it. but the problem is though i ve written the code well but the printf function doesnt show itself. the slotted optocoupler counts the number of the passing black lines on a circle and sends it out to lcd. speed is "hiz"
Code: |
#include <16F877.h>
#device adc=8
#use delay(clock=4000000)
#fuses NOWDT,XT, PUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
unsigned char sayac=0;
int16 count=0;
int8 hiz=0;
unsigned char sn=0;
#include <LCD.C>
#int_rtcc
void rtcc_isr()
{
sayac++;
sn++;
if(sayac==2)
{
sayac=0;
hiz=count/6;
count=0;
}
if(sn>=20)
{
sn=0;
printf(lcd_putc,"%d",hiz);
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
set_timer0(0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
set_tris_a(63);
enable_interrupts(INT_rtcc);
enable_interrupts(GLOBAL);
while(1)
{
while(pin_A1==1); //beyaz
count++; //artir
while(pin_A1==0); // siyah
}
}
|
"count" is incremented and according to timer0 interrupt speed (variable: hiz) is calculated. and displayed every seconds. interrupt is on the second count of timer0 (65.5*2 miliseconds). |
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Mon Sep 26, 2005 7:13 am |
|
|
Don't know if it applies to the 8-bitters like the PIC, but i've always been advised in embedded systems programming not to attempt printf() in an ISR. |
|
|
asunca
Joined: 09 Sep 2005 Posts: 36
|
|
Posted: Mon Sep 26, 2005 7:37 am |
|
|
i think you are right. i ve thought of it before but i had no choice. is there another way?? thanks |
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Mon Sep 26, 2005 8:45 am |
|
|
I would guess you would put that printf in your while(1) loop. That is:
Code: |
while(1)
{
...
if (hiz != hiz_previous)
{
printf(...); // print out hiz
hiz_previous = hiz;
}
...
}
|
The reason why i introduced an "hiz_previous" variable is to avoid printf'ing hiz if it didnt change.
-Mike |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Mon Sep 26, 2005 9:45 am |
|
|
Always keep ISR's as short as possible. If some major function is needed, simply set a flag, in the ISR, and have that flag evaluated somewhere in the main body.
Ronald |
|
|
asunca
Joined: 09 Sep 2005 Posts: 36
|
|
Posted: Mon Sep 26, 2005 10:40 am |
|
|
lets see if that will work. i ll inform you as soon as it is tried. thanks to every one |
|
|
asunca
Joined: 09 Sep 2005 Posts: 36
|
|
Posted: Tue Sep 27, 2005 2:33 am |
|
|
i ve tried the new method but sorry to say that didnt work. in the main program while loop cannot terminate because of something i dont know. and when i print hiz for try "hiz++ " , the increment of it is like : 10, 20, 30.. an extra zero or integer near it. what is the reason for it?
here is the new one:
Code: |
#include <16F877.h>
#device adc=8
#use delay(clock=4000000)
#fuses NOWDT,XT, PUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
unsigned char sayac=0;
unsigned char count=0;
unsigned char hiz=0;
unsigned char sn=0;
int1 flag=0;
#include <LCD.C>
#int_rtcc
void rtcc_isr()
{
sayac++; // count variable
sn++;
if(sayac==2) // 65,5*2= 131 miliseconds passed
{
sayac=0;
hiz=count*2;
count=0;
}
if(sn>=20) // say that one second passed
{
flag=1; // printf flag set
sn=0;
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
set_timer0(0);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
delay_ms(1);
set_tris_a(63);
printf(lcd_putc,"\fReady...");
enable_interrupts(INT_rtcc);
enable_interrupts(GLOBAL);
while(1)
{
//while(pin_A1==0); // old ones
//count++; // old ones
//while(pin_A1); // old ones
if (pin_a1)
{
count++;
while(pin_a1);
}
if (flag)
{
printf(lcd_putc,"\fHIZ=%u",hiz);
flag=0;
}
}
}
|
i have tried the hiz_previous logic that will probably do but for now no need to place it (thanks to mike)
itimer interrupt works but the program flow doesnt enter to inner loops of isr. as i told above, main loop is stuck somewhere...?? |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Tue Sep 27, 2005 8:29 am |
|
|
You are evaluating PIN_A1 incorrectly. It should be:
Code: |
while(1)
{
//while(pin_A1==0); // old ones
//count++; // old ones
//while(pin_A1); // old ones
if (input(pin_a1)) // NOTE the input() function here
{
count++;
while(input(pin_a1)); // NOTE the input() function here too
}
if (flag)
{
printf(lcd_putc,"\fHIZ=%u",hiz);
flag=0;
}
}
|
The funcion input() looks at the status of the Input pin. Give that a try now.
Also, on a side note, the ISR will probably be entering and exiting multiple times while the printf() statement does it's thing. The value of your variable might be changing while the printf() is printing.
Ronald |
|
|
asunca
Joined: 09 Sep 2005 Posts: 36
|
|
Posted: Tue Sep 27, 2005 8:49 am |
|
|
i ve had a quick try and that seemed to work.. ronald thank you.. i am doing the details now.. i ll come back.. bysss |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Sep 27, 2005 9:30 am |
|
|
Some comments:
1) Style notation
This is not a good style to define IO pins.
set_tris_a(63); // At first glance doesn´t have any meaning.
using:
set_tris_a(0x3F); // you can know which bit is H and wich is L.
using
set_tris_a(0b0111111);// you can see which bit is H and wich is L.
2) Test against zero for shortest code.
Remember to initilize your variables before using them.
Code: |
#int_rtcc
void rtcc_isr()
{
sayac--;
if( !sayac )
{ sayac=2;
hiz=count*2;
count=0;
}
sn--;
if( !sn )
{ sn=20;
flag=1; // printf flag set
}
}
|
3) In the Mike´s suggestion I would add:
Code: |
...
if(hiz != hiz_previous)
{
disable_interrupts(INT_rtcc);
printf(...); // print out hiz
enable_interrupts(INT_rtcc);
hiz_previous = hiz;
}
...
|
Humberto |
|
|
asunca
Joined: 09 Sep 2005 Posts: 36
|
|
Posted: Wed Sep 28, 2005 4:48 am |
|
|
i did all you told ,it works ok but has a little problem. when the rotor gives up turning, the lcd is stuck at a number sometimes and sometimes it shows zero as expected. what is missing ?? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Sep 28, 2005 6:57 am |
|
|
Pls could you post the whole code that demostrate the problem ?
Humberto |
|
|
asunca
Joined: 09 Sep 2005 Posts: 36
|
|
Posted: Wed Sep 28, 2005 7:22 am |
|
|
Code: |
#include <16F877.h>
#device adc=8
#use delay(clock=20000000)
#fuses NOWDT,HS, PUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
unsigned char sayac=0;
unsigned char sayim=0;
unsigned char hiz_previous=0;
unsigned char hiz=0;
unsigned char sn=0;
int1 flag=0;
#include <LCD.C>
#int_rtcc
void rtcc_isr()
{
sayac++;
sn++;
if(sayac==2)
{
hiz=sayim*2;
sayim=0;
sayac=0;
}
if(sn>=20)
{
flag=1;
sn=0;
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
set_timer0(0);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
delay_ms(1);
set_tris_a(0b00111111);
printf(lcd_putc,"\fReady...");
enable_interrupts(INT_rtcc);
enable_interrupts(GLOBAL);
while(1)
{
//while(input(pin_A1==0));
//sayim++;
//while(input(pin_A1));
if (input(pin_a1))
{
sayim++;
while(input(pin_a1));
}
if (flag)
{
disable_interrupts(INT_rtcc);
if (hiz != hiz_previous)
{
printf(lcd_putc,"\fHIZ=%u",hiz);
hiz_previous=hiz;
}
sayim=0;
flag=0;
enable_interrupts(INT_rtcc);
}
}
}
|
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Sep 28, 2005 7:34 am |
|
|
Code: |
unsigned char sayac=0;
unsigned char sayim=0;
unsigned char hiz_previous=0;
unsigned char hiz=0;
unsigned char sn=0;
|
By default in CCS variables are unsigned integers.
Just disable the RTCC while using the LCD, test this way:
Code: |
if (flag)
{
if (hiz != hiz_previous)
{
disable_interrupts(INT_rtcc);
printf(lcd_putc,"\fHIZ=%u",hiz);
enable_interrupts(INT_rtcc);
hiz_previous=hiz;
}
sayim=0;
flag=0;
}
|
Humberto |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Wed Sep 28, 2005 10:20 am |
|
|
Humberto wrote: |
Just disable the RTCC while using the LCD, test this way:
|
For many apps, it would be ill advised to give up the ghost on your count to update a display. The count should be inviolate.
Scott |
|
|
|