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 CCS Technical Support

reading the pin
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Tue Oct 13, 2009 9:33 pm     Reply with quote

Hey PCM, I ran the code but it has the following problems. I'm still trying to debug it, so any advice would be useful.

When I run it, I get 'PINC5 did not go HIGH, Error' repeatedly. And it comes out real fast, like 30 times every second. Thats with a 2 second delay at the end of my code as well.

From the osc I can tell that C5 has gone high, so no problems there. No problems with C1 either, that one goes high for sure and its being picked up as well.

Am I using the CCP function the right way in my code?

Thanks heaps.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 14, 2009 1:04 am     Reply with quote

Currently, one of us suggests a few changes and you implement them. Then you re-post the code and ask us to look at it again, without you
doing anything at all. Why don't you try to fix the problems. You might learn something.
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Wed Oct 14, 2009 6:04 am     Reply with quote

PCM programmer wrote:
Currently, one of us suggests a few changes and you implement them. Then you re-post the code and ask us to look at it again, without you
doing anything at all. Why don't you try to fix the problems. You might learn something.


Sorry about that, I was at work and couldnt test it out till I got home. Just thought it might have been faster to make the corrections and put it back on here to see what people thought.

but your right, i should keep trying. apologies.
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Wed Oct 14, 2009 11:34 pm     Reply with quote

Hey, just a quick question regarding timers.

If I use a 4Mhz system clock, and use the following,
Code:
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);


I am essentially telling the timer to count up every (4Mhz/4)*16 = 16 micro seconds right?

so the timer counts up every 16 us and overflows ever 255 counts, which is 0.00408seconds or 4.08 ms. Am i correct so far?

I have a piece of code where I count the number of counts between two pins going high. Its very small, milli second differences. It kind of works, but this timer overflow is making things hard for me. Is there a way I can tell the timer to just keep counting up and not stop at 255? or maybe could i use a 'for' loop to count the number of timer counts? is that possible?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 14, 2009 11:57 pm     Reply with quote

Timer0 overflows every 256 counts. You can keep a static int8 variable inside the Timer0 isr, and extend it that way. Initialize the variable to 0
in the declaration. Or, you could use a global int8 variable.

Or you could use Timer1, which is a 16-bit counter. It has a smaller maximum prescaler of 8. So you count in 8 usec increments.
8 usec x 65536 counts = 524288 usec = approx 1/2 second.
(Assuming a 4 MHz oscillator).
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Thu Oct 15, 2009 1:44 am     Reply with quote

Cool thanks. I ended up going for the second option cause it pretty much acts like a time-out loop in itself. However, I'm getting heaps of erratic 'values'. The values are meant to be the number of counts between the two pins going high.

64423
9505
64093
9558
64119
9582
64150
9826

Just out of interest, when I start the clock, I just go
Code:
 set_timer1(0);
right? cause this could set the register value to 0 and just start counting. Or is there a special 'start counting now' command?

And then to stop, I just read the timer register in question? There's no need to 'reset' it or anything because the next time I need to count, I just use the set_Timer1(0) command again.

Am I on the right track here? Thanks heaps.
bungee-



Joined: 27 Jun 2007
Posts: 206

View user's profile Send private message

PostPosted: Thu Oct 15, 2009 1:41 pm     Reply with quote

You are on the right path. Basically you need to setup timer once and then just set it to 0 on start and read the value on end. Maybe your timer overflows in a second measurement. Create simple timer ISR where you increase value of an variable, so you'll know if it overflowed or not.

So on "start timer" command you'll first set timer to 0 and also overflow variable to 0.

I suspect, that your events take longer than you expected.

How does your Timer1 setup statement look like?
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Fri Oct 16, 2009 4:38 am     Reply with quote

bungee- wrote:
You are on the right path. Basically you need to setup timer once and then just set it to 0 on start and read the value on end. Maybe your timer overflows in a second measurement. Create simple timer ISR where you increase value of an variable, so you'll know if it overflowed or not.

So on "start timer" command you'll first set timer to 0 and also overflow variable to 0.

I suspect, that your events take longer than you expected.

How does your Timer1 setup statement look like?


ah i understand. so every time it interrupts, it increases the variable and then when im printing the value, i just take note of the number of times it overflowed. thanks.

timer1 setup statement is
Code:
  setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);


and then when i want to start the timer, i go

Code:
 set_timer1(0);


and then for my second pin, im using the CCP to capture it and create an interupt when it does. and then i just use

Code:
 value = CCP_1; 


ill try adding the variable and see how things turn out. thanks for the advice.
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Fri Oct 16, 2009 5:18 am     Reply with quote

Yes! I think it works! Well at least I think it does. For some reason, I'm getting values that are closer to what I need. I just hope I haven't hacked it.

This is what I got in the end, I've stripped all the unwanted code so its easier for you to see. I'm most worried about calling the interupts. Where do I enable them? Where do I disable them?
Code:

#include <16F690.h>
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, HS
#use delay(clock = 4000000)
#use rs232(baud=19200, xmit=PIN_B7, rcv=PIN_B5)

   int16 ctr;
   int tripped=0;
   long value=0;
   int  counter=0;

#int_CCP1
void  CCP1_isr(void)
{
   disable_interrupts(INT_CCP1);
   tripped=1;
}

#int_TIMER1
void  TIMER1_isr(void)
{

   counter = counter + 1;  //variable to check if timer1 has overflowed
   disable_interrupts(INT_TIMER1);
}


void main()
{
 
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   enable_interrupts(GLOBAL);
           
   for(;;){
   
      contact_slave3();                 //After this, PINC1 should go high, followed closely by PINC5
   
      for (ctr=0;ctr<64000;ctr++) {     //Wait for PINC1 to go high until timeout
         if(input(PIN_C1)) {
            set_timer1(0);              //set timer value to 0, start counting
            enable_interrupts(INT_TIMER1); //feature to know if timer1 overflows
            ctr=1;                      //PINC1 went high, set ctr=0, break
            break;
         }
      }
     
      if (ctr==1){                                    //at this point, C1 went high, start timer and wait for CCP/C5 to go high
        setup_ccp1(CCP_CAPTURE_RE);       
        enable_interrupts(INT_CCP1);                 
             
            if(tripped) {
               value = CCP_1;                        //value at timer register when C5 went high
               value = value + (counter * 65536);    //take into account number of timer timer1 overflowed
               printf("Value is: %Lu us",value);     //print value
               printf("Counter is: %d", counter);    //print counter number
               tripped=0;                            //reset 
               counter=0;
               value=0;
            }
            else{
            printf("\r\nC5 didnt go high\r\n");
            }
           
      }
      else{                             //PINC1 did not go high, error
        printf("\r\nC1 didnt go high\r\n");
      }
     
    delay_ms(2000);
    tripped = 0;   
   }
}



The first reading always seems to be a mess-up for me, but it seems to settle and sometimes gives a bad reading. Ideally I'm looking for readings around 5000 us or less. Preferably less.

Value is: 22204 us Counter is: 2
Value is: 7595 us Counter is: 1
Value is: 28443 us Counter is: 1
Value is: 50347 us Counter is: 1
Value is: 5769 us Counter is: 1
Value is: 7075 us Counter is: 1
Value is: 7088 us Counter is: 1
Value is: 7079 us Counter is: 1
Value is: 7069 us Counter is: 1

And you're right, I learnt it does takes longer than I expected. But somehow I thought microcontroller worked really really fast.
bungee-



Joined: 27 Jun 2007
Posts: 206

View user's profile Send private message

PostPosted: Fri Oct 16, 2009 1:44 pm     Reply with quote

hobby_85 wrote:


#include <16F690.h>
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, HS
#use delay(clock = 4000000)
#use rs232(baud=19200, xmit=PIN_B7, rcv=PIN_B5)

int16 ctr;
int tripped=0;
long value=0;
int counter=0;

#int_CCP1
void CCP1_isr(void)
{
disable_interrupts(INT_CCP1);
tripped=1;
}

#int_TIMER1
void TIMER1_isr(void)
{

counter = counter + 1; //variable to check if timer1 has overflowed
disable_interrupts(INT_TIMER1); <--- You do not need this
}


void main()
{

setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(GLOBAL);

for(;;){

contact_slave3(); //After this, PINC1 should go high, followed closely by PINC5

for (ctr=0;ctr<64000;ctr++) { //Wait for PINC1 to go high until timeout
if(input(PIN_C1)) {
set_timer1(0); //set timer value to 0, start counting
enable_interrupts(INT_TIMER1); //feature to know if timer1 overflows <--- put this in your setup part of program
Reset counter here
ctr=1; //PINC1 went high, set ctr=0, break
break;
}
}

if (ctr==1){ //at this point, C1 went high, start timer and wait for CCP/C5 to go high
setup_ccp1(CCP_CAPTURE_RE); <--- put this to your setup point of program
enable_interrupts(INT_CCP1);

if(tripped) {
value = CCP_1; //value at timer register when C5 went high <--- this should be in CCP ISR not here
value = value + (counter * 65536); //take into account number of timer timer1 overflowed <--- this should be in CCP ISR not here
printf("Value is: %Lu us",value); //print value
printf("Counter is: %d", counter); //print counter number
tripped=0; //reset
counter=0;


Put into ISR parts, that should be done there.

Also you need to put part of the program into some sort of loop, when you're waiting for second signal to arrive.
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Fri Oct 16, 2009 8:30 pm     Reply with quote

Hey bungee, thanks for your help. Just one last question,

If I put the enable_interupts(ccp1) command in my program, does that start looking for the high in that pin from that point onwards only? Especially if the setup_ccp_re is at the start of the program?
bungee-



Joined: 27 Jun 2007
Posts: 206

View user's profile Send private message

PostPosted: Sat Oct 17, 2009 12:43 pm     Reply with quote

Enable interrupt for CCP stay's where it is, but setup can be moved on to beginning. You do not need to setup what kind of interrupt will CCP have multiple times, once is enough. Leave enable where it is, so that it will be active just when you want it. Wink
Guest








PostPosted: Sun Oct 18, 2009 6:42 am     Reply with quote

hey bungee, thanks for the help so far. unfortunately, i seem to be having a software bug somewhere that i cant get rid of. i just dont know where it is.

basically im using the time difference in arrival of the two signals to determine how far apart the source is. the code works, but only to an extent.

if i hold the source 1.2 meters away, then i keep getting either 11.60 meters or 19.05 meters. and its constantly around those numbers. everytime.

likewise, for 2.4m, i get 12.8m or 20.2 meters. and when i hold it 3.6meters away, i get either 13.9m or 21.42m.

if i was getting only 1 solid answer for each distance, i could possibly find a relationship and hack the code by putting a constant in somewhere. but since i keep getting two different values for each distance, i dont know what to do.

ive tried re writing the code in a different way, but same problem. would you have any suggestions on how i could debug such a problem?
Guest








PostPosted: Sun Oct 18, 2009 6:49 am     Reply with quote

I just thought I might add my code if you wanted to refer to it.
Code:

#include <16F690.h>
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, HS
#use delay(clock = 4000000)
#use rs232(baud=19200, xmit=PIN_B7, rcv=PIN_B5)

   int16 ctr;
   int tripped;
   int tripped1;
   long value;
   int  counter;
   float distance;
   int16 ctr1;

#int_CCP1
void  CCP1_isr(void)
{
   value = CCP_1;
   value = value + (counter * 65536);
   tripped=1;
   disable_interrupts(INT_CCP1);
}

#int_TIMER1
void  TIMER1_isr(void)
{
   counter = counter + 1;
}

void main()
{
 
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   enable_interrupts(GLOBAL);
   setup_ccp1(CCP_CAPTURE_RE);
           
   for(;;){
   
        contact_slave3(); //After this, PINC1 should go high, followed closely by PINC5
     
      for (ctr=0;ctr<65535;ctr++) {     //Wait for PINC1 to go high until timeout
         if(input(PIN_C1)) {
            set_timer1(0);              //set timer value to 0, start counting
            enable_interrupts(INT_TIMER1);
            counter=0;
            ctr=1;                      //PINC1 went high, set ctr=0, break
            break;
         }
      }
     
      if (ctr==1){                                    //at this point, C1 went high, start timer and wait for C5 to go high       
       
        enable_interrupts(INT_CCP1);                  //wait for rising edge of pinC5 until timeout       
              for (ctr1=0;ctr1<10000;ctr1++) {
                           
                  if(tripped) {
                 
                     delay_ms(200);                           
                     printf("TDOA is: %Lu us\r\n",value);                             
                     distance = (value) * (0.000008) * (348.4);
                     printf("Distance is:%f meters\r\n", distance);
                     tripped=0;
                     distance=0;
                     value=0;
                     tripped1 = 1;
                     break;
                  }
              }
             
            if (tripped1 == 0){
            printf("\r\nNO US DETECTED\r\n");
            tripped1=0;
           
            }
           
      }
      else{                             //PINC1 did not go high, error
        printf("\r\nSlave Node 3 RF signature not found\r\n");
       
      }
     
delay_ms(1000);
tripped = 0;
tripped1 = 0;
counter=0;

   }
   
   
}


I know the code works, but not accurate at all. Its just that I need to know how to keep getting one consistent result rather than 2. It has to be a bug I think.

Any help/tip/advice would be greatly appreciated.

Thanks
bungee-



Joined: 27 Jun 2007
Posts: 206

View user's profile Send private message

PostPosted: Mon Oct 19, 2009 1:35 am     Reply with quote

Try this:

Code:
int32   value;


You are doing this:
Code:
 value = value + (counter * 65536);
with 16bit you overflow every time you multiply. Wink
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 Previous  1, 2, 3  Next
Page 2 of 3

 
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