Delay using ADC problem on PIC18F4550 - Page 1
Forum section: electronics / general

author: Bibiricat
author_rank: Contributor
timestamp: June 03, 2013, 07:33:25 pm
content: Hello.I am trying to make a pulse delay using a potentiometer (using a ADC). The ADC works, the delay function work, but it's not a linear delay.What i want to say is that when the pot is at 0, i get no delay. When it's somewhere else, i get some delay, however, after a certain point, the delay begins to drop, until it almost get to 0 again, however the pot gets to full range.This is the code. I hope someone can help me with this.Code:#include<p18f4550.h> // Always include the header file#include <delays.h>#define REMAPPED_RESET_VECTOR_ADDRESS 0x1000/***************Bootloader************************************/#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESSextern void _startup (void);void _reset (void){_asm goto _startup _endasm}#pragma codevoid Delay(int x){int i;//Post:Delay for x*10ms.for (i=0; i<x; i++){Delay10TCYx (10); // gives a delay of 10 x 60 x 1/12 = 600/12 = 50 us}}void ADCInit(){ADCON1 = 0b00001110;//VSS,VDD ref. AN0 analog onlyADCON0 = 0x00;//clear ADCON0 to select channel 0 (AN0)ADCON2 = 0b10001000;//ADCON2 setup: Right justified, Tacq=2Tad, Tad=2*Tosc (or Fosc/2)ADCON0bits.ADON = 0x01;//Enable A/D module}void main(void){unsigned int delay;int ad_val;TRISB=0b00000001;PORTB=0b00000000;PORTBbits.RB2=1;ADCInit();while(1){if(PORTBbits.RB2 == 0)PORTBbits.RB2 = 1;if(PORTBbits.RB0 == 0)//test button press{ADCON0bits.GO_DONE = 1;//Start A/D Conversionwhile(ADCON0bits.GO_DONE != 0);//Loop here until A/D conversion completesad_val=((ADRESH<<8)+ADRESL); //get value of 10 bit adcDelay100TCYx (ad_val); //insert number in delay functionPORTBbits.RB2 = 0; //change port statusDelay10TCYx (120); //delay for a bitPORTBbits.RB2 = 1; //change back to initial port status}}}

author: AndyC_772
author_rank: Super Contributor
timestamp: June 03, 2013, 07:58:00 pm
content: When you turn the pot, what range of voltages are you getting? Could it be something daft like both ends of the pot's track being connected together, so the resistance between the wiper and the ends of the track reaches a maximum when the wiper is in the middle of the range, and zero when it's at either end?In your code, try replacing:ad_val=((ADRESH<<+ADRESL);with the simpler:ad_val=ADRES;I've a feeling that, for some devices at least, ADRES is defined in the header file as a single 16 bit register that you can reference to get the whole 16 bit result in one hit. I also have a feeling I've tried to combine ADRESH and ADRESL as you've done and had problems, but I wouldn't like to be drawn on exactly what the problem was or why it happened.Also, you have a line:Delay100TCYx (ad_val);Is it possible that ad_val can take values that are out of range for this function?Can you list your delays.h header file?

author: Bibiricat
author_rank: Contributor
timestamp: June 04, 2013, 08:47:22 am
content: The pot is working good (i get 0v at one end, and +4.88v at the other).based on youre commnets i have modified the code:ad_val=ADRES;ad_val=ad_val>>3;Delay100TCYx (ad_val);so now i shift the adc value so i get a max of 256.I haven't tested it , but will do soon.

author: PA0PBZ
author_rank: Super Contributor
timestamp: June 04, 2013, 10:52:01 am
content: Could be you have a logaritmic pot, they are almost more common than linear ones (audio equipment and such). Did you measure the voltage at regular intervals?

author: AndyC_772
author_rank: Super Contributor
timestamp: June 04, 2013, 11:11:22 am
content: Quote from: Bibiricat on June 04, 2013, 08:47:22 amIt might be simpler to set the ADC to give a left justified result, then just use ADRESH. That gives you a range of 0-255 without the need for a 16 bit read followed by a shift.If you keep the same code structure, I think you need ad_val>>2, not 3.

author: Bibiricat
author_rank: Contributor
timestamp: June 04, 2013, 07:36:46 pm
content: I managed to get it working, using left justified, but i encountered another problem with the interrupt. When i use a button, i get everything to work just fine, but the i use a AC trigger source, i can't get the interrupt to work, bit i am checking with the pickit 2 logic tool to see if the trigger is working, and the micro is registering a change, however, the interrupt doesn't trigger....Any idea on what else can i try ?

author: AndyC_772
author_rank: Super Contributor
timestamp: June 04, 2013, 07:57:49 pm
content: With most (all?) PIC18 devices, there are several interrupt enable bits to set - there's probably a PIE bit, an interrupt priority bit for that particular interrupt source, the bit which selects between legacy vs prioritised interrupts, then GIEH and GIEL to set. One trap that's caught me out on one or two occasions is that if you disable high priority interrupts, then low priority interrupts get disabled as well.Could you post your code again? What was wrong with it before?

author: Dennis
author_rank: Contributor
timestamp: June 12, 2013, 01:14:29 am
content: It may make the response from the delay pot a bit smoother if you use a slope function. This will allow you to span the delay to whatever degree you wish; from Fine to Course.int map(int x, int in_min, int in_max, int out_min, int out_max){// 10 bit ADC ans 256 step delay0 256 0 1024 0 0return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;}or simply (for a 256 step delay):ad_val=ADRES; // always store register value, don't use rawDelay100TCYx ( (ad_val * 256) / 1024 );