CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Question about ext_int_edge use !
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

Question about ext_int_edge use !
PostPosted: Tue Feb 03, 2009 7:58 am     Reply with quote

Hello everybody !

I have a problem with a program.

First of all, as usual, I'm using pic18f452 @ 10 MHz and CCS C compiler version 4.057.

PROBLEM : the output of the next code should be 1110101010 and in reality is 1111111111.

I have two boards : 1 sends a IR code ( only 10 bits using the RC5 protocol) and the other should receive the command.

So .... first the receiver code ( which I'm having trouble with) :


Code:


#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define tsop  pin_b0
#define min   2000
#define max   3000
 int16 timer_value=0;
 char buffer[10];
 char temp;
 int i;
 char flag;

#int_ext                                              //IR bits detected by edge triggering
void ext_isr()  {
   //disable_interrupts(int_ext);                   // i don't know ... is this right here ?
   set_timer1(0);                                     // set timer to zero
  while(!(input(tsop)));                              //measure how long the input is low
  timer_value = get_timer1();
  if ( (min < timer_value) && (timer_value < max))    // if it's low for 900 uS -> OK
    if (input(tsop))                                  //now, if the pin is high
    buffer[i++]='1';                                  //then it's a "1"
    else
    buffer[i++]='0';                                  //else it's a "0"
    flag=1;
}
void main() {

setup_timer_1(t1_internal|t1_div_by_1);
flag=0;

while(1) {
 
ext_int_edge(0,H_to_L); //falling edge
enable_interrupts(int_ext); //enable external interrupt
enable_interrupts(global); //enable interrupts
  if (flag==1){
   for(i=0; i<10;i++){
   flag=0;
   printf("%c",buffer[i]); }
     }
}
 



The following code is working as it should. Here is the transmitter part :

Code:

#include <16f877.h>
//#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

char slave_cmd[10]={'1','1','1','0','1','0','1','0','1','0'};



//=============================================================================
void check_for_SLAVE(void) {
 char i;
  for(i=0;i<9;i++)
   {
    if (slave_cmd[i]=='0')
      {
        output_high(pin_e1);
        delay_us(900);
        output_low(pin_e1);
        delay_us(900);
      }
      else
      {
        output_low(pin_e1);
        delay_us(900);
        output_high(pin_e1);
        delay_us(900);
      }
   }     
delay_ms(100);
}

//==========================================
void main() {
   
   //--------------------------------------------------
   setup_timer_1(t1_internal|t1_div_by_1);
   ext_int_edge(0,h_to_l);
   enable_interrupts(int_ext);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   
   while(1)
   {
   check_for_SLAVE();
   }
 
}



Thank you very much !

Andrew.
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 03, 2009 9:33 am     Reply with quote

Any ideas ? Anyone ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 03, 2009 2:53 pm     Reply with quote

There's tons of RC5 code out there. Do a Google search for CCS code
with this search string:
Quote:
RC5 "INT_EXT"

This will get you CCS code that uses INT_EXT interrupts for the decoder.
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 04, 2009 3:35 am     Reply with quote

Hello PCM Programmer !

Thank you 4 your answer.

The code is inspired by this loginway article : http://loginway.net/the-rc5-decoder-based-on-a-pic16f877a-and-pic-01-developement-board/.

So ...what i'm trying to do is to determine straight forward if the received signal is a "1" or a "0".

The "ext_int_edge" work's like this (please corect me if i'm wrong) :
- when the signal from the TSOP goes low i enter the ISR routine.
- if the output stays low for a period of about 900 uS then it's a valid IR bit.
- so... 900 uS have passed ...i check the state of the pin ...if the pin is high...then the bit is a "1", else it's a "0".

Is this logic bad ? Why do i get 10 bits of "1" ? ... Please take a look at my implementation and point me in the right way.


I must mention that the transmitter part is working properly. I've tested it with a oscilloscope and verified it.

Thank you !!
Ttelmah
Guest







PostPosted: Wed Feb 04, 2009 4:22 am     Reply with quote

The logic is wrong.
There are a number of problems:
The first is with your transmit. You need to take the line back to 'high', when the transmit finishes. At present, if the last bit sent is a '0', the line will remain low. Then there won't be a falling edge for the first start bit at all....
The second though is with the logic of the receive. If you look at your bit pattern - 1110101010. The pattern of hghs and lows sent (with the above fault fixed), will be (starting with a '1' as the line idles between the characters) -
Code:
 
fixed pitch font needed here to see properly
1010101100110011001101
 1  1  1   1     1      1     1

Your code as it stands, only triggers on the falling edges, The ones in the second line show where it'll trigger. So it will trigger correctly for the first three bits, but then will trigger in the middle of the fourth bit. At this point, your test half a bit time latter, will still see a low, and return a '1'. It won't then trigger at all for the next '1', but will again trigger at the falling edge in the middle of the next bit, and will again see this as a 1....

Best Wishes
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 04, 2009 2:08 pm     Reply with quote

Hello Ttelmah !

Thak you for your response.

You are right about the transmitter code ... point taken ! Wink

Now...about the receiver code :

Let's take an example so i can understand why it is not working:

Code:


------     ------         --------     ------
      |   |  |   |       |   |    |   |
      |___|  |   |___ ___|   |    |___|
      |      |       |       |        |
idle  | "1"  |  "0"  |  "1"  |  "0"   | idle


Ok...so the interrupt triggers on the falling edge. Then ... after 900 us low , if the pin is high, that means that it's a "one" and i wait for next falling edge .
The next falling edge comes, after 900 us low, if the pin is still low, that means that there must have been a "zero".

You say:
Quote:

then will trigger in the middle of the fourth bit. At this point, your test half a bit time latter, will still see a low, and return a '1'.


Why is this happening, when the pin is still low ? If the pin is still low after 900 us the it should be a zero. Shocked

Where is the mistake ?.... Please clarify this to me.

I know that somewhere is a mistake but i don't understand where.

Thank you for your patience !!
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 04, 2009 2:24 pm     Reply with quote

Basically ... I'm retaining the value of the last bit.
Or so it should be !

Hmm...i'm confused ....pls give me a hand in solving this ! Shocked
Ttelmah
Guest







PostPosted: Wed Feb 04, 2009 4:38 pm     Reply with quote

Look at your own picture.
First bit, falling edge at the start of the bit. You wait 900uSec (really ought to be a couple of uSec longer to allow for the transmitter taking _time_ to actually set/clear the bit in the loop. If the signal has gone high, it implies a '1'. Now your next interrupt trigger, is in the middle of the next bit. Your test would then work (with the commment about the timing). However your next interrupt is now, not in the next bit at all (you miss the '1', since there is no falling edge in it at all...). You would then interrupt in the middle of the last '0', and 900uSec latter, see a high!...
With your approach, if you get the timings 'right', you would _only_ detect a '0', as a zero, if it is immediately followed by a '1'. You also will only detect a '1, if if follows another '1'.
What you need to do, is start the clock at the _first_falling edge, and then sample at 1800uSec intervals after this point, if you find a falling edge, you have a 0, if you have a rising edge, you have a 1.
In fact you will only sample seven times in your nine bits, and would return 1110001 for those seven bits.
However your code, doesn't wait for 900uSec, it waits for the next rising edge. The value sampled then will always be '1' (after all the signal _has_ risen). At this point, if the time was longer than 900uSec, it doesn't increment the counter, or write a value into the buffer at all. So the only bits it'll write to the buffer, are 1's, when it happens to find them...
So all it'll do, is write four 1's to the buffer, for the nine bits sent.

Best Wishes
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Thu Feb 05, 2009 12:56 pm     Reply with quote

Hello Ttelmah !

Based on your last post, the following implementation is my latest shot at sloving this problem, but unfortunately it is still not working.

Code:


#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define tsop   pin_b0

 char buffer[10];
 char temp;
 char i;
 char count;
 int1 timer_flag;
 int1 done=false;
 
 
#int_ext                             
void ext_isr()  {
   disable_interrupts(int_ext);
   enable_interrupts(INT_TIMER1);
   set_timer1(61036);                 // overflow in 1,8 ms
   }

#int_timer1
void timer1_isr() {

for(i=0; i<9; i++) {

if (timer_flag){
       
       set_timer1(61036);   
    if (input(TSOP))
        temp='1';
    else
        temp='0';
        timer_flag=false;
        }
    else
        {
        set_timer1(61036);
    if (input(TSOP))
        temp='1';
    else
        temp='0';
        timer_flag=true;
         }
buffer[i]=temp;
done=true;
      }
}   

void main() {

setup_timer_1(t1_internal|t1_div_by_1);
ext_int_edge(0,H_to_L); //falling edge
enable_interrupts(int_ext); //enable external interrupt
enable_interrupts(global); //enable interrupts
 do {
     if (done)
     
     done=false;
     printf("%s",buffer);
     
    } while (1);
}



How can i make this right ?

Thank you for your input !!
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Thu Feb 05, 2009 12:59 pm     Reply with quote

Where should i put the FOR LOOP ?

Without the FOR loop the program kind'a works, but I need to printf the result to the serial port, and for this I need a string ( BUFFER[10]).

Hmm...I don't know what else to try. Sad
Ttelmah
Guest







PostPosted: Thu Feb 05, 2009 4:17 pm     Reply with quote

First, shorten the time set in int_ext.

Think about it for a moment, you need to sample in the second half of each bit time. So you want to sample at perhaps 1100uSec in the first bit, and then then 1800uSec latter till the data is finished. Remember also that entering the interrupt takes time, so set the timer value to give a timeout in about 1790uSec from the point where you enter the timer routine.

Then, you don't want a 'for' loop. Have a global counter 'bitnumber'. Set it to 10 in int_ext. Then in the timer routine, after setting the new timer value, save the bit, and decrement it. If it is '0', disable the timer interrupt, and set a flag to say 'val_complete'. Re-enable int_ext as well here.

In your main code, if 'val_complete' is set, clear it, and print the value.

Best Wishes
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Mon Feb 09, 2009 2:04 pm     Reply with quote

Hello Ttelmah !

Thank you for answering my post and sorry i didn't aswer it.

I didn't get a chance to actualy test the code posted below...so if you can take a look over it and see if it makes sense, i will deeply apreciate it.

As u see i've made some minor modifications because i think that without the extra "IF" statement in the timer isr, the value of the bitnumber variable would have been reinitialized to 10 on each "0".

Is this right ?..What's your opinion ?

So...here is my latest implementation considering your sugestions:

Code:


#include <18f452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define tsop   pin_b0
 char buffer[10];
 char bitnumber=0;
 int1 val_complete=false;
 
 
#int_ext                              //IR bits detected by edge triggering
void ext_isr()  {
   disable_interrupts(int_ext);
   enable_interrupts(INT_TIMER1);
   //set_timer1(61036);                 // overflow in 1,8 ms
   //set_timer1(63286);                 // overflow in 900 us
   //set_timer1(61061);                 // overflow in 1,790 ms
   bitnumber=10;
   set_timer1(62786);                   // overflow in 1,1 ms

}

#int_timer1
void timer1_isr() {

       set_timer1(61061); // overflow in 1,790 ms
   if (input(TSOP)){
       buffer[bitnumber]='1';
       bitnumber--;}
   else
      { buffer[bitnumber]='0';
        bitnumber--; }
   
   if (bitnumber==0){
       disable_interrupts(INT_TIMER1);
       enable_interrupts(int_ext);
       val_complete=true; }   
   
}   

void main() {

setup_timer_1(t1_internal|t1_div_by_1);
ext_int_edge(0,H_to_L);                //falling edge
enable_interrupts(int_ext);            //enable external interrupt
enable_interrupts(global);             //enable interrupts
while(1) {
   if (val_complete)
     val_complete=false;
     printf("%s",buffer); }

}



Thank you !
Ttelmah
Guest







PostPosted: Mon Feb 09, 2009 3:15 pm     Reply with quote

1) Move the decrement of bit_number outside the if statement. Doesn't really matter, but no point in having two copies, one in each branch...
I have put it into the test (decrementing before testing).
2) The big one. Clear the timer interrupt before enabling it in int_ext. Clear int_ext, before enabling it in the timer. Otherwise both _will_ have already triggered in the past, resulting in the routines being incorrectly called...
So:
Code:

#int_ext                              //IR bits detected by edge triggering
void ext_isr()  {
   disable_interrupts(int_ext);
   set_timer1(62786);                   // overflow in 1,1 ms
   clear_interrupts(INT_TIMER1);
   enable_interrupts(INT_TIMER1);
   bitnumber=10;
}

#int_timer1
void timer1_isr() {

   set_timer1(61061); // overflow in 1,790 ms
   if (input(TSOP))
       buffer[bitnumber]='1';
   else
       buffer[bitnumber]='0';
       
   if (--bitnumber==0) {
       disable_interrupts(INT_TIMER1);
       clear_interrupts(INT_EXT);
       enable_interrupts(int_ext);
       val_complete=true;
   }     
}   

You have exactly the testing I described. Can't see any 'extra' if.

Best Wishes
Andrew83



Joined: 16 Sep 2008
Posts: 51

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 10, 2009 7:09 am     Reply with quote

So...i've tested the program and it still doesn't work !

In the hyperterminal window it outputs an endless row of "P".

It seems to be stuck in the WHILE in the main().

The program executes 1 time when it receives a IR signal but then remains in the main() although the variable val_complete is now false.

Any ideas why is this happening ?

I trully don't understand what's happening !
Ttelmah
Guest







PostPosted: Tue Feb 10, 2009 7:15 am     Reply with quote

You have got the brackets missing....
Currently the test for the value being 'complete', only affects the clear operation, not the print.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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