ADC interupts?

For Flowcode users to discuss projects, flowcharts, and any other issues related to Flowcode 2 and 3.

Moderators: Benj, Mods

Post Reply
serstel
Posts: 22
Joined: Thu Jan 25, 2007 1:34 am
Been thanked: 1 time
Contact:

ADC interupts?

Post by serstel »

Hello
With the Analog to digital converter taking so much time in convertion is it possible to start the convertion and have an interupt wating utill adcon0 register bit 1 is done, while in the mean time the pic is doing some other calculations? If it is possible how can I do it?

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hello

It is quite possible to achieve this. What you need to do is work out approximatley how long the conversion takes. To do this you could start the conversion and then start the Timer0. You will need to enable interrupts for the timer0. You could say light a LED if the conversion is done when the timer times out or light another LED if the conversion is not done. This way you can tune the value you load the timer with to create a interrupt delay as close as possible to the ADC sample time.

Place this code into the Supplementary code defines window

Code: Select all

void FCD_ADC0_SampleADC(char ADC_Chan);
char FCD_ADC0_ReadAsByte();
short FCD_ADC0_ReadAsInt();
Place this code into the Supplementary code functions window
Please note that the Sample ADC function may need editing depending on the PICmicro you are using.

Code: Select all

void FCD_ADC0_SampleADC(char ADC_Chan)
{
	char ta, tb, cnt;
	adcon1 = 0x00;
	ansel=0x7F;
	ta = trisa;
	tb = trisb;
	#if (ADC_Chan == 0)
	  trisa = trisa | 0x01;
	#endif
	#if (ADC_Chan == 1)
	  trisa = trisa | 0x02;
	#endif
	#if (ADC_Chan == 2)
	  trisa = trisa | 0x04;
	#endif
	#if (ADC_Chan == 3)
	  trisa = trisa | 0x08;
	#endif
	#if (ADC_Chan == 4)
	  trisa = trisa | 0x10;
	#endif
	#if (ADC_Chan == 5)
	  trisb = trisb | 0x40;
	#endif
	#if (ADC_Chan == 6)
	  trisb = trisb | 0x80;
	#endif
	adconADC_Chan = 0x81 | (0 << 3);
	cnt = 0;
	while (cnt < 220) cnt++;
	adcon0 = adcon0 | 0x04; //Start conversion
	//while (adcon0 & 0x04); //Dont wait just carry on with prog
	//trisa = ta;
	//trisb = tb;
	//ansel = 0x00;
	//adcon0 = 0x80;
}

char FCD_ADC0_ReadAsByte()
{
	return adresh;
}

short FCD_ADC0_ReadAsInt()
{
	short iRetVal;
	iRetVal = (adresh << 2);
	iRetVal += (adresl >> 6);
	return (iRetVal);
}
Using C Code blocks
You can call the ADC routines by using a C code block with the following

Code: Select all

FCD_ADC0_SampleADC(0); //Sample ADC Channel 0
FCV_SAMPLE = FCD_ADC0_ReadAsByte();  //Store value into variable sample
In your Tmr0 Interrupt routine

C Code Block

Code: Select all

while (adcon0 & 0x04); //While ADC Still Working
trisa = ta; 
trisb = tb;
ansel = 0x00; //Set I/O to digital
adcon0 = 0x80;

User avatar
Steve
Matrix Staff
Posts: 3422
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

What you need to do is to create a custom interrupt that looks for the ADC interrupt flag (ADIF).

You will also need to write your own C code to start the ADC conversion. This can be similar to Ben's example, but does not need to be so general because you know exactly which ADC channel you are using.

In the macro that is called by the ADC interrupt, you will need to turn the ADC off and set all bits to digital i/o. You should also store the ADC result (by accessing adresh and possibly adresl and saving it to a global Flowcode variable).

Keep the ADC interrupt macro as short as possible, and deal with any ADC conversion within your main program.

serstel
Posts: 22
Joined: Thu Jan 25, 2007 1:34 am
Been thanked: 1 time
Contact:

Post by serstel »

In the component macro for the ADC there are 3 options. SampleADC,ReadAsByte,ReadAsInt. I was under the impression that the SampleADC option starts the conversion and only when another macro is added to the flowchart with one of the other two options enabled will the program actually acuire the value.
Also how can I make a ADC interrupt that looks for the ADIF flag? In the custom interupt option it needs: Enabble Register, Enable Bit, Flag Register, Flag Bit. I assume that the flag register is ADIF and the Flag bit is bit 6. What goes inside the Enabble Register and Enable Bit boxes?
(Note: I am using a 18f4550 pic microcontroller and I read 2 analog values from chanels 0 and 1. the values come from a rate gyro so I must read them very often in a second.)
Sorry for all the trouble but I have only just started using Flowcode and although my questions are a bit too much, I am just a newbee :oops:

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hi Serstel

Ok in the custom interrupt properties window you want something like this (note that these settings are for the 18F4550 PICmicro sampling ADC channel 0 - for other devices refer to their datasheet)

Custom Interrupt Name = ADC_INT
Enable Register = pie1
Enable Bit = ADIE
Flag Register = pir1
Flag Bit = ADIF

The ADC sample process is now started by using a C Code Block with the following code.

Code: Select all

char cnt = 0;
adcon1 = 0x0E;  //Enable ADC0 Input(Change for different ADC Channel)
adcon2 = 0x03;  //Set ADC Sample Time
trisa = trisa | 0x01;  //(Change for different ADC Channel)
adcon0 = 0x01;   //Switch on ADC(Change for different ADC Channel)
while (cnt <220) cnt++;  //Allow ADC Capacitor to charge / discharge
adcon0 = adcon0 | 0x02;  //Start Conversion Process
The Interrupt will sample ADC channel 0. To configure other ADC channels please refer to the device datasheet.

When the ADC has finished converting the signal the macro ADC_INTERRUPT will run. Using a C Code block add the following lines to disable the ADC, retrieve the sample data and allow proper function of the digital I/O pins.

Code: Select all

adcon1 = 0x0f;  //Enable Digital I/O 
adcon0 = 0x00;  //Disable ADC Module 
trisa = trisa & 0xFE;  //Restore Tris Registers(Change for different ADC Channel)
FCV_SAMPLE = (adresh << 2);
FCV_SAMPLE += (adresl >> 6);
Last edited by Benj on Fri Jan 26, 2007 4:28 pm, edited 3 times in total.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

An example Flowcode V3 program is available from the following link

http://www.matrixmultimedia.com/software/ADC_INT.fcf

In this example program the Analogue converter is started and ended using an interrupt.

The top line of the LCD shows the output of the LCD.
The bottom line of the LCD shows the number of cycles between the ADC being started and the result being generated.

serstel
Posts: 22
Joined: Thu Jan 25, 2007 1:34 am
Been thanked: 1 time
Contact:

Post by serstel »

umm... for some reasom I can't simulate the file. it stays always in the loop. there is no value in the LCDDisplay. the sample is always -1.

Mark
Posts: 209
Joined: Thu Oct 19, 2006 11:46 am
Location: Bakewell, UK
Has thanked: 20 times
Been thanked: 16 times
Contact:

Post by Mark »

Benj,

Thanks for this code. I was needing to set up a custom interrupt (RS232 input), being able to use the mnemonics is a big help, as is an your example as a guide.

Serstel, The example flowcode file has C code in it and this does not simulate, the Flowcde simulator only simulates Flowcode. However, it should work when if download it to a HP-488 board (for example).

Mark
Go with the Flow.

serstel
Posts: 22
Joined: Thu Jan 25, 2007 1:34 am
Been thanked: 1 time
Contact:

Post by serstel »

Thanks for your help everybody.

Post Reply