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

PIC18F2525 and OPT101 photogate timer project - has issues

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



Joined: 05 Jun 2011
Posts: 3

View user's profile Send private message

PIC18F2525 and OPT101 photogate timer project - has issues
PostPosted: Sun Jun 05, 2011 12:14 am     Reply with quote

Hi folks, I'm new here and was hoping to get some pointers as to what I might be doing wrong with my project.

My project is building a photogate timing device, specifically for measuring the shutter speeds of film cameras.

I'm using CCS C to make hex files that I program into a PIC18F2525 using a JDM programmer. I have built a circuit that receives input from an OPT101 photodiode w/ integrated amplifier, so that when the output passes into logical high it causes an interrupt which activates a timer, and when it falls back down it deactivates the timer and writes it to a character LCD. Everything works fine except when the speeds get to 1/500th of a second and faster. The result is often garbage numbers.

I built a pulse circuit to pulse a LED a certain length of time when I press a button, to simulate an ideal camera shutter. Here were the test results:

pulse width (ms) measured duration
500 510.286
250 254.35
125 128.286
67 68.15
33 34.436
16 16.15
8 8.1
4 4
2 2
1 2.136
0.5 0.25

You can see it goes well for a while, even gets more accurate as the times decrease, then it goes screwy. It gets the same incorrect numbers over and over.

The light source seems to maybe play a part in the issue, when I use a camera flash it seems to be showing reasonable timings, and even measured a low-duration flash to be 0.300ms, 0.350 or 0.400, a very reasonable bunch of numbers. The slew rate of the OPT101 amplifier is 1V/us so it can't be that.

My code is below. At a glance, does anyone see any issues that might attribute to my problem? I can answer any questions that might arise.

Thanks very much!

Code:
#include "18F2525.h"

#fuses HS,NOWDT,NOPROTECT,NOLVP,INTRC

#use delay(clock=8000000)

#include "M:\PIC\Photogate timer with LCD\flex_lcd_photogate_final.c"
//==========================

int1 button, timer_en;  //button used for ready button polling, timer_en used for ext interrupt first run, second run
int1 donebit = 0;  //donebit used to end mid-sampling loop
long count, time, rem, divtest;  //count is count of timer overflows, time is ms, rem is us, divtest is for adjustment


#int_timer0
void  timer_isr()
{
   count++;
  // waste = 0;

   set_timer0(108);
}

#int_ext
void ext_isr()
{
       timer_en = !timer_en;

       if(timer_en == 0)
       {
          enable_interrupts(int_timer0);
          ext_int_edge(H_TO_L);

          donebit = 0;
       }
       else if(timer_en == 1)
       {
          disable_interrupts(int_timer0);
          donebit = 1;
       }
}

readyprep()
{
   count = 0;  //reset count
   timer_en = 1;

   lcd_putc("\fReady\b"); // LCD ready indicator

   ext_int_edge(L_TO_H);

   enable_interrupts(int_ext);
   enable_interrupts(global);

   return 0;
}

math()
{
      time = (count / 10); //convert to milliseconds
      rem = count % 10;  //modulus for microseconds
      rem *= 50;  // convert to microseconds
     
      divtest = time % 2;
     
      if(rem == 400, divtest == 1)
         {
             time = time + 1;  //possibly necessary compensation value
             rem = rem - 400;  //possibly necessary compensation value
         }
     
      if(rem == 50)
         {
            rem = rem - 50;
         }
         return 0;
}

countroutine()
{
   readyprep();  //prepares screen and vars

  /* while(donebit == 0)  //mid-sample waiting area
      {
         delay_us(3);
      }

      disable_interrupts(global);
      disable_interrupts(int_timer0);

      math();  //computes count into ms, us

  /* if(count != 0)
   {
      readybit = 1;
   } */

   donebit = 0;

   printf(LCD_putc,"\f%lu.%03lu ms \b", time, rem);  //%lu for long ints
   delay_ms(100);

   return 0;

}



void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT);  //setup timer
   disable_interrupts(int_timer0);
   disable_interrupts(global);

   lcd_init();  // Always call this first.

   delay_ms(100);

   lcd_putc("\fFilm Shutter\nSpeed Timer\b"); // Startup message


//**** Main While Loop**********
      while(1)
   {
     button = input(pin_A0);

     if(button == 0)
     {     countroutine();   }  // go to countroutine if ready button was pressed
     if(button == 1)
     {     delay_us(3);    }  //maintains value until ready button pressed
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sun Jun 05, 2011 2:13 am     Reply with quote

You have several separate problems.

First, problem is setting a timer _to_ a value in an ISR.
Problem is that it takes a _lot_ of time (in terms of clocks), to get into an ISR. Typically perhaps 30 instruction counts. So when you set the timer 'to' 108, it will have already counted a lot. Recorded times will therefore be inaccurate.
Generally, let the timer free run. Change your maths scaling to handle the real time interval, without trying to use 'msec'.
However, why not use the hardware available for this?. The CCP modules. Look at EX_CCPMP.C, which shows how to measure a pulse width with the CCP modules recording the rising and falling edges. Maximum pulse width of 33mSec at 8MHz, with the /1 prescaler as given, you have a choice of adding an extended timer (int_timer1, with the high word of a 32bit counter being incremented), or using a larger prescaler, depending on the range of numbers you actually need to use.

Then you talk about the slew rate of the OPT101 being 1V/uSec - re-read the data sheet. The figure you are quoting is the slew rate of the output op-amp only. The diode itself, takes time to respond to light, and this depends on the intensities involved, the load on the chip, the incident angle of the light, etc. etc... This is why you are seeing a much better response from the brighter photoflash.

Best Wishes
mattthegamer463



Joined: 05 Jun 2011
Posts: 3

View user's profile Send private message

PostPosted: Sun Jun 05, 2011 10:17 am     Reply with quote

Thanks for the response.

I followed an example program I found to make a 100us timer, which is why I had added the 108 each time. You're saying I should just alter my math to work the full 256 counts into my milli/microsecond values? I'm not sure how I could do that without trial and error, but it makes sense.

I was unaware of the function of the CCP modules. I am reading into them now, they sound like just the right thing. However, you mention that the maximum pulse width at a clock speed of 8MHz and prescaler of 1 is 33mSec. Ideally I want to be able to measure from 1s down to 1ms accurately and without issues. If I switch to the CCP capture method, will I need to have an external button or something to re-set the counter prescaler to a higher value (for example, for high speed measurements, use prescaler of 1 and for longer ones use a prescaler of 64) and new math for the results? When you say adding an extended timer, do you mean like a nested timer set up? Like, when timer0 overflows, timer1 ticks once? I'm quite new to programming, I'm concerned that I won't be able to accomplish this without hours upon hours of time invested.

I looked at the OPT101 datasheet again and couldn't find any info about the diode's speed itself. However, its says the frequency response of the chip is 14kHz. I have seen rates on other photodiode chips and they are often in the nanosec-range, so I don't think that could be an issue.

I'll look into these things further and post if I have issues. Thanks.

EDIT

I just did some experimenting and a simluation in Proteus to see how the CCP works, and it works amazingly! I'm just really concerned that the long-pulse functionality is out of my grasp.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jun 05, 2011 5:49 pm     Reply with quote

Here is one example of extending Timer1 to provide a wider operating
range for frequency capture with the CCP:
http://www.ccsinfo.com/forum/viewtopic.php?t=33153&start=30
mattthegamer463



Joined: 05 Jun 2011
Posts: 3

View user's profile Send private message

PostPosted: Sun Jun 05, 2011 5:54 pm     Reply with quote

Thanks PCM Programmer. I've got some promising numbers going, I need to finish the mechanical setup before I can determine if I need to work the code further. Thanks.
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