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

How to use both pins in ccp2 ?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

How to use both pins in ccp2 ?
PostPosted: Wed Jul 17, 2019 1:38 am     Reply with quote

Hello everyone,

In my project I have 2 dc motors and an ultrasonic sensor. They both work fine separately. I use 18f4550. The problem is, the motors use ccp1 (RC2) and ccp2 (RC1). My ultrasonic sensor also uses ccp2(RB3). I am trying to converge the 2 codes. The problem is they both use same code lines for different pins.
Code:

setup_ccp1(CCP_PWM); //Enable 2
setup_ccp2(CCP_PWM); //Enable 1
setup_timer_2(T2_DIV_BY_4, 99, 1); //30kHz, 0-399

In pwm setup, i use ccp_pwm, but in ultrasonic code i use ccp_capture_fe. They are on different pins. I also change the status of CCP2 interrupt on ultrasonic code. How do i make the compiler to separate the 2 pins (RB3 and RC1)? Is it possible?

This is the ultrasonic code.
Code:

#if !defined(__PCH__)
 #error USB CDC Library requires PIC18
#endif

#include <18F4550.h>
#DEVICE ADC=10
#fuses HSPLL,NOWDT,MCLR,PROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN,CCP2B3
#use delay(clock=48000000)
//#include <usb_bootloader.h>
#include "usb_cdc.h"

#define rp_getc usb_cdc_getc
#define rp_putc usb_cdc_putc
#define BLUE_LED PIN_D5 //Blue LED
#define RED_LED PIN_D6   //Red LED
#define TRIGGER PIN_B2 //any suitable pin
#define ECHO PIN_B3 //CCP2 input

int value;
int32 distance;
int16 calculate_Distance();

void main()
{
   usb_cdc_init();
   usb_init();
   output_low(TRIGGER);
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_CAPTURE_FE);
   setup_comparator(NC_NC_NC_NC); 
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); //calc above
   while(true)
   {
      usb_task();
      printf(rp_putc, "%ld\n\r",calculate_Distance());
   }
}

int16 calculate_Distance()
{
      value = rp_getc();
      delay_ms(20);   
      if(value == 'a')
      {
         output_high(BLUE_LED);
         output_high(TRIGGER);
         delay_us(20);
         output_low(TRIGGER);
         set_timer1(0); //clear timer
         CCP_2=0; //clear CCP;
         clear_interrupt(INT_CCP2);
         clear_interrupt(INT_TIMER1);
         while (!interrupt_active(INT_CCP2) && !interrupt_active(INT_TIMER1)); {} //     //Here an edge was seen
         if (interrupt_active(INT_CCP2))
         {
             distance=(int32)CCP_2*4/55; //this gives integer distance in mm - 4m=55555 counts
             distance=distance/10;  //conversion distance from mm to cm
             if (distance>10 && distance<400)
             {
                  output_low(BLUE_LED);
                  output_high(RED_LED);
             }
             else
             {
                  output_low(RED_LED);
                  output_high(BLUE_LED);
             }
            // delay_ms(100); //pause before next reading
             printf(rp_putc, "%ld\n\r",distance);
             return distance;
         }
         else
         {
              //Here timer timed out
              printf(rp_putc,"O"); //overtime
              delay_ms(100);
              return 0;
         }
      }
 
}


Thank you so much!
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Wed Jul 17, 2019 3:47 am     Reply with quote

Yes and no....

All you need to do is setup the CCP to be a capture at the start of the distance
routine, and set it back to be a PWM at the end of the routine.
However, it will not generate a PWM, while it is being used for capture.
Understand it is not a question of 'using both pins'. The CCP setup for PWM
does not perform capture. It does not 'have' a capture input in this mode.
Also uses a different timer in capture mode than PWM mode.

Only one peripheral, and 'one job or the other'. It can't do both at the same
time. So your PWM output, will have to stop while you read the distance.
Whether this matters or not is down to how the PWM is actually used.

Alternatively, consider not using the CCP for the distance measurement.
You could simply reset a timer, and then when the pulse arrives, read this.
Since you are already setting timer1 to zero for your timeout, use this.
Just wait for the change on the CCP input pin, and read timer1 when this
happens.
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Wed Jul 17, 2019 7:14 am     Reply with quote

Ttelmah wrote:
Yes and no....

All you need to do is setup the CCP to be a capture at the start of the distance
routine, and set it back to be a PWM at the end of the routine.
However, it will not generate a PWM, while it is being used for capture.
Understand it is not a question of 'using both pins'. The CCP setup for PWM
does not perform capture. It does not 'have' a capture input in this mode.
Also uses a different timer in capture mode than PWM mode.

Only one peripheral, and 'one job or the other'. It can't do both at the same
time. So your PWM output, will have to stop while you read the distance.
Whether this matters or not is down to how the PWM is actually used.

Alternatively, consider not using the CCP for the distance measurement.
You could simply reset a timer, and then when the pulse arrives, read this.
Since you are already setting timer1 to zero for your timeout, use this.
Just wait for the change on the CCP input pin, and read timer1 when this
happens.


Thank you for your answer Ttelmah!

I've kinda hoped that there is a way to separate those pins and manipulate them both as i wanted. So i will try to use timer and another pin. Since i took the code from a post here, there are some code lines i don't know.

Code:
distance=(int32)CCP_2*4/55


In here the ccp_2 behaves like a function? Does it return the time it has been high/low?

There are timer flags but no timers itself. I am confused.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Wed Jul 17, 2019 7:37 am     Reply with quote

CCP_2 is a register. It contains the value that was latched from the timer
at the moment the pin triggered, It is defined in the .h file for the processor.
In capture mode (you can program whether it is to capture the rising
or falling edge), when the required edge is seen, the value in Timer1 (or
optionally Timer3), is stored into this register.
Your code would have simply have to do the same. You can use the existing
pin. So something like:
Code:

//at the start of the routine
int16 TIMER_val;

   //then
   while (!input(PIN_C2) && !interrupt_active(INT_TIMER1)); {} //
   if (!interrupt_active(INT_TIMER1))
   {
       //Only go here if we haven't timed out
       TIMER_val=get_timer1(); //read the timer value
       //Then use this instead of the CCP_2 value


For detecting a rising edge on the pin.
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Thu Jul 18, 2019 6:46 am     Reply with quote

Ttelmah wrote:
CCP_2 is a register. It contains the value that was latched from the timer
at the moment the pin triggered, It is defined in the .h file for the processor.
In capture mode (you can program whether it is to capture the rising
or falling edge), when the required edge is seen, the value in Timer1 (or
optionally Timer3), is stored into this register.
Your code would have simply have to do the same. You can use the existing
pin. So something like:
Code:

//at the start of the routine
int16 TIMER_val;

   //then
   while (!input(PIN_C2) && !interrupt_active(INT_TIMER1)); {} //
   if (!interrupt_active(INT_TIMER1))
   {
       //Only go here if we haven't timed out
       TIMER_val=get_timer1(); //read the timer value
       //Then use this instead of the CCP_2 value


For detecting a rising edge on the pin.


Thank you so much Ttelmah!

As i undertand, instead of using ccp2 register, we manually call the timer value from get_timer1(). I have edited the code to this.
Code:
clear_interrupt(INT_TIMER1);
         while (!input_state(ECHO) && !interrupt_active(INT_TIMER1)); {} //     //Here an edge was seen. ECHO is PIN B3
         if (!interrupt_active(INT_TIMER1))
         {
             TIMER_val=get_timer1();
             distance=(int32)TIMER_val*4/55; //this gives integer distance in mm - 4m=55555 counts
             distance=distance/10;  //conversion distance from mm to cm
             printf(rp_putc, "%ld\n\r",TIMER_val);

I always read the timer value about same(665-661) even the distance is changed. Any ideas? I have checked the sensor, it still works with old codes.

I have deleted the CCP2B3 fuse and the lines below since i use input_state.
Code:
   setup_ccp2(CCP_CAPTURE_FE);
   setup_comparator(NC_NC_NC_NC); 
temtronic



Joined: 01 Jul 2010
Posts: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jul 18, 2019 7:22 am     Reply with quote

maybe this....
Quote:
int16 TIMER_val;

I think it should be unsigned int16. The timer1 register(s) holds a 16bit value that logically would be an unsigned value.

I could be totally wrong (almost 40*C here today) but I'd change the code/compile/test....

Jay
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Thu Jul 18, 2019 7:30 am     Reply with quote

temtronic wrote:
maybe this....
int16 TIMER_val;

I think it should be unsigned int16. The timer1 register(s) holds a 16bit value that logically would be an unsigned value.

I could be totally wrong( almost 40*C here today) but I'd change the code/compile/test....

Jay


Thank you Jay,

I've tried it but unfortunately, it did not work :/

There is something i miss which effects the timer i think. I tried editing value types, resetting TIMER_val to 0 in different locations. I have tried editing the size of variables but no luck. It is always between 666 and 661.

Code:
#if !defined(__PCH__)
 #error USB CDC Library requires PIC18
#endif

#include <18F4550.h>
#DEVICE ADC=10
#fuses HSPLL,NOWDT,MCLR,PROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
//#include <usb_bootloader.h>
#include "usb_cdc.h"

#define rp_getc usb_cdc_getc
#define rp_putc usb_cdc_putc
#define BLUE_LED PIN_D5 //Blue LED
#define RED_LED PIN_D6   //Red LED
#define TRIGGER PIN_B2 //any suitable pin
#define ECHO PIN_B3 //CCP2 input

int value;
int32 distance;
int16 calculate_Distance();
int16 TIMER_val;

void main()
{
   usb_cdc_init();
   usb_init();
   output_low(TRIGGER);
   setup_ccp1(CCP_OFF);
   //setup_ccp2(CCP_CAPTURE_FE);
   //setup_comparator(NC_NC_NC_NC); 
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); //calc above
   while(true)
   {
      usb_task();
      printf(rp_putc, "%ld\n\r",calculate_Distance());
   }
}

int16 calculate_Distance()
{
      value = rp_getc();
      delay_ms(20);   
      if(value == 'a')
      {
         output_high(BLUE_LED);
         output_high(TRIGGER);
         delay_us(20);
         output_low(TRIGGER);
         TIMER_val=0;
         set_timer1(0); //clear timer
         clear_interrupt(INT_TIMER1);
         while (!input_state(ECHO) && !interrupt_active(INT_TIMER1)); {} //     //Here an edge was seen
         if (!interrupt_active(INT_TIMER1))
         {
             TIMER_val=get_timer1();
             distance=(int32)TIMER_val*4/55; //this gives integer distance in mm - 4m=55555 counts
             distance=distance/10;  //conversion distance from mm to cm
             printf(rp_putc, "%ld\n\r",TIMER_val);
             if (distance>10 && distance<400)
             {
                  output_low(BLUE_LED);
                  output_high(RED_LED);
             }
             else
             {
                  output_low(RED_LED);
                  output_high(BLUE_LED);
             }
            // delay_ms(100); //pause before next reading
             
             return distance;
         }
         else
         {
              //Here timer timed out
              printf(rp_putc,"O"); //overtime
              delay_ms(100);
              return 0;
         }
      }
 
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Jul 18, 2019 8:01 am     Reply with quote

661, is 1/2269 second. 440uSec.
Tell us more about the sensor?.

PIN_B3, when used as a digital input, is a standard 'TTL' input. Will accept
anything above 2.4v as a '1'. When used to trigger the CCP, it is a Schmidt
input, and will require the signal to go up to 4v, to be seen as a '1'.

However I realise your existing code is looking for the falling edge, not the rising edge.
Now you would actually have to ignore the edge until you see it fall. So

Code:

   int1 old, new;
   old=new=input_state(ECHO);
   while (!((old==1) && (new==0)) && !interrupt_active(INT_TIMER1))
   {
      old=new;
      new=input_state(ECHO);
   }

In place of your existing test line.

It'll then sit in the loop until it sees a point where the signal was high and
has gone low.

I suspect your sensor is actually setting it's pulse high about 2mSec after
the signal, so the existing code picks this up...
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Thu Jul 18, 2019 8:41 am     Reply with quote

Quote:
I suspect your sensor is actually setting it's pulse high about 2mSec after
the signal, so the existing code picks this up...


You are right.

The last code you suggested worked succesfully. Measurements are correct. Thank you so much Ttelmah!

Note: the sensor is hc-sr084.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Jul 18, 2019 9:51 am     Reply with quote

Good. Smile

Glad it worked.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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