ADC controlled Delay

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ADC controlled Delay

3,570 Views
Sandeepsharma
Contributor I
Hi I want to use 0-200mS and 0-600S delay in QG8 program. And that delay should be
adjusted or varied by the ADC value (By using Trim Pot).
If you have any program pls share with me.
 
 
Labels (1)
0 Kudos
Reply
11 Replies

1,323 Views
bigmac
Specialist III
Hello,
 
To clarify the timer situation, you will need to utilise a single channel for the TPM module.  This is for your short delay, using output compare mode.  For the long delay, you would simply count the number of overflows made by the TPM module, by decrementing a counter for each overflow.  When the counter reaches zero, the required delay has completed.  If the TPM overflow period is made greater than 200 ms, there is a simpler way to generate the short delay than that previously outlined.
 
I will assume the use of interrupts, rather than polling the TPM flags.  You will need to code the following functions -
Read ADC result for each channel
Start long delay
Start short delay
TPM overflow ISR
TPM channel ISR (output compare)
 
The action required at the completion of each delay period would occur within the respective ISR.
 
To accommodate your bus frequency of 4.1856 MHz, I might suggest use of prescale factor 16.  This will result in the TPM incrementing every 3.82 us, and a TPM overflow period of 3.82 * 65536 us = 250.5 ms.  This meets the requirement for the simplified short delay.
 
For the long delay, the ADC reading will need to be scaled to produce the required initial count setting.  For a period of 600 seconds (and an ADC reading of 1023) the initial count value would need to be 600/0.2505 = 2395.  This would require a scaling factor for the ADC reading of 2395/1023 = 2.341.  However, a floating point calculation is not necessary since the scaling factor can be closely approximated by the integer fraction 7/3.  Therefore, integer calculations can be used.
 
Assuming ADC channel 0 is used for the long delay, the following function would set up the required count value.  The addition of 1 to the calculated value will ensure that the count value is non-zero.
 
long count;  /* Global variable */
 
void long_delay( void)
{
   count = getADC(0)*7/3 + 1;
}
 
The TPM overflow interrupt would need to include the following code -
 
TPMSC_TOF = 0;  /* Clear flag */
if (count) {    /* Check for not already zero */
   count--;
   if (count == 0)  {
      // Long delay action
   }
}
 
For the short delay, the TPM channel register will need to be set to a value corresponding to the current TPM counter value plus an amount corresponding the required delay.  Again the ADC reading will need to be suitably scaled.  For a period of 200 ms (and an ADC reading of 1023) increment value would need to be 200000/3.82 = 52356.  This would require a scaling factor for the ADC reading of 52356/1023 ~= 51.
 
Assuming ADC channel 1, and TPM channel 0 is used for the short delay, the following function would set up the TPM channel.  The addition of 1 to the calculated value will ensure that the increment value is always non-zero.
 
void short_delay( void)
{
   TPMC0V = TPMCNT + getADC(1)*51 + 1;
   TPMC0V_CH0F = 0;  /* Ensure flag is clear */
   TPMC0V = 0x50;    /* Enable OC (software) interrupt */
}
 
The TPM channel interrupt would need to include the following code -
 
TPMC0SC_CH0F = 0;  /* Clear flag */
TPMC0SC = 0;       /* Disable further Ch 0 interrupts */
// Short delay action
 
The ADC channel read might use the following code -
 
word getADC( byte chan)
{
   AD1SC1 = chan & 0x1F;  /* Start conversion */
   while (!ADCSC1_COCO);  /* Wait for conversion complete */
   return ADCR;
}
 
You will also need to set the ADC clock within your initialisation code.
 
Regards,
Mac
0 Kudos
Reply

1,323 Views
bigmac
Specialist III
Hello,
 
I don't have any specific code, but I might adopt the following strategy -
 
Firstly, I will assume that the ADC uses 10-bit mode, for maximum resolution, so the output reading will lie somewhere between 0-1023.  Two separate ADC channels might be used, one for each delay setting.
 
For the 600 second delay, I would consider counting the number of TPM overflows, using an overflow period of about 600 ms.  The number of overflows required would match the ADC reading.  Assuming that the TPM modulo value would remain at its default setting, the required TPM clock frequency would be 109.2 kHz (a period of 9.155 us).  Assuming a TPM prescale value of 64, this would give a bus frequency requirement of 6.99 MHz (perhaps 7 MHz, or thereabouts).
 
For the 200 ms delay requirement, a TPM channel could be used, operating in output compare mode (software interrupt only).  The output compare interrupts could then be counted until they reached the current ADC value.  This would require an output compare period of about 200 us.  For a TPM clock period of 9.155us, this would give the required output compare increment of 22.
 
The careful choice of the TPM clock frequency, will result in much simpler code, with minimal calculations necessary.
 
Regards,
Mac
 
0 Kudos
Reply

1,323 Views
Denn
Contributor I
Hello,
 
Macs solution is good.
 
My strategy is slightly different from Mac's for the fact that it didn't use TPM module.But it has a problem, that once if you want to change the bus frequency you need to calculate modify delay routine as it uses instructions cycle time for creating the reqd delay.
 
 
1) 8 bit resolution , max ADC output reading of 255.
2)  relate this max ADC output reading of 255 to 200ms/600ms by having for loop(DBNZ) counting till ADC output reading. Inside the loop some NOP or other instructions for delay.Finally some NOP instructions for fine tuning the delay required.
 
There could be some some techniques better than this.


 
Regards,
Denn
0 Kudos
Reply

1,323 Views
Sandeepsharma
Contributor I
Hi Denn,
   Thanks, but i am using 0-200mS and 0-600S(5min). 600s is a large delay, can i use TPM or do i require RTI.
 
 
0 Kudos
Reply

1,323 Views
peg
Senior Contributor IV
Hi,

Often a delay as long as 5 min does not need to be very accurate. Is this the case here?
If not you do as Mac has hinted at, set up the timer optimised for the accuracy required by the short delay, keep setting compares up based on the ADC value, then for the long delay, just count the overflows of this same counter. You may need to massage the raw ADC value to give you the right number of overflows and it will be accurate to within one overflow period which is possibly good enough. This way you can use only one timer channel to do both delays.

0 Kudos
Reply

1,323 Views
Denn
Contributor I
Hello Sandeep,
 
You are confusing me :smileywink: 600 seconds= 10 min .If you want the delay for 5 min then replace 600 by 300( easier method- text replacement Cntrl+H in code :smileywink:
 
 
You can also try this way using system tics (system tic is assumed as 1ms). Pseudo code/Code is given below.
Code:
Pseudo Code:unsigned char read_ADC(unsigned char )// fn prototype returns ADC value(0-255),I/P parameter= channel addrvoid delay(unsigned char);// delay fn prototype---------------------------------------------------------------------Inside infinite loopvar_200ms_max_ADC = read_ADC(200ms_max_channel)// 200ms_max_channel is the address of pot
                                              // giving max of 200ms delayvar_600s_max_ADC    = read_ADC(600s_max_channel)  // 600s_max_channel is the address of pot giving
                                              //max of 600s delaydelay_200ms_max(var_200ms_max_ADC);delay_600s_max(var_600s_max_ADC );-------------------------------------------------------------------   void delay_200ms_max(unsigned char ADC_value){t200ms_maxtic=0;while( t200ms_maxtic <  (ADC_value*200/255) )   {}}void delay_600s_max(unsigned char ADC_value){t600000ms_maxtic=0;while( t600000ms_maxtic < (ADC_value*600000/255) )   {}}---------------------------------------------------------Inside System Tic ISR (assuming System tics are for 1ms) increment variablest200mstic and t600000mstic.t200mstic++ ;t600000mstic++;

 
 
Regards,
Denn.






Message Edited by Denn*** on 2008-03-27 12:10 PM
0 Kudos
Reply

1,323 Views
Denn
Contributor I
Hello Sandeep,
You can go for max ADC resolution of  12 bits for more accurate delay setup.Replace 255 by 1023.
 
 
Regards,
Denn.
0 Kudos
Reply

1,323 Views
Denn
Contributor I
Hello Sandeep,
 
What is the Bus freq you are using? Also the channel address??You want program for a delay FROM 0-200MS OR 0ms-600ms ?? or both :smileywink:
 
Regards,
Denn
0 Kudos
Reply

1,323 Views
Sandeepsharma
Contributor I
Hi,
   Thanks for the response, My Internal Bus frequency is 4.1856MHz and Internal CPU Clock is 32.7kHz.
Yes I do require both delay 0-200mS and 0-600s(5min) and both controlled by separate ADC.
 
0 Kudos
Reply

1,323 Views
Denn
Contributor I
Hello Sandeep,
 
Did you find the required solution?Should you need help don't hesitate to ask.
 
Regards,
Denn.
0 Kudos
Reply

1,323 Views
allawtterb
Contributor IV
I don't think anyone has a program that does exactly this or cares to write one that does for you.  If you are having some problems with some particular part of making the program like reading the ADC or setting up a timer for a delay of the length needed then someone might be able to help you.
0 Kudos
Reply