v3.6 .fcd ADC code changes

Forum for problems or queries regarding Flowcode Comms Components. Eg LIN, I2C, SPI, RS232, CAN, IrDA etc

Moderators: Benj, Mods

Post Reply
jimhumphries
Posts: 112
Joined: Wed Oct 12, 2005 6:29 pm
Location: USA
Been thanked: 1 time
Contact:

v3.6 .fcd ADC code changes

Post by jimhumphries »

I noticed that there are substantial code changes to the AD portion of the v3.6 16F876.fcd file (relative to the v3.2 version). Can you explain the changes? In particular, can you describe how the variable MX_ADC_SAMP_TIME is used? In my v3.2 application I modify the 16F876.fcd to minimize the sample time to achieve the highest allowable (reliable) conversion rate. I'm not sure I know how I would do this for the v3.6 file or if I even need to.

Thanks,

Jim

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:

Re: v3.6 .fcd ADC code changes

Post by Benj »

Hello Jim

At the moment the variable MX_ADC_SAMP_TIME is loaded with a value of 40 as standard in all FCD files. This sets up a software loop to wait 40 cycles with the ADC connected to the correct channel. This allows the ADC capacitor to charge up before taking a sample. If we are switching ADC channels eg sampling multiple channels then this value of 40 should be fine. However if you are not switching channels and sampling one channel only then you can lower this value to suit your desired sample speed. There is also a conversion speed setting that is usually available in the ADCON0 or ADCON1 registers. Please see the current FCD file sample setting and the device datasheet to see if you can optimize your conversion speed for your application.

jimhumphries
Posts: 112
Joined: Wed Oct 12, 2005 6:29 pm
Location: USA
Been thanked: 1 time
Contact:

Re: v3.6 .fcd ADC code changes

Post by jimhumphries »

Ben:

Thanks.

Since you added the variable MX_ADC_SAMP_TIME rather than just entering the value "40" (as in the v3.2 code) my optimistic side says that you plan to do something with it - like configuring the sample time and conversion clock relative to the processor clock. I keep hoping you guys will do this so I don't have to (C is Greek to me). Is this a possibility for v4 and, if not, would you guys consider writing the code to do this as a patch? A few more questions - will the v3.2 16F876.fcd file work under v3.6 (I haven't tried this) and can you describe what the MX_ADC_TRIS_REG and MX_ADC_TRIS_MSK variables do.

Thanks again,

Jim

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:

Re: v3.6 .fcd ADC code changes

Post by Benj »

Hello Jim

V4 Analogue components will have the modifiable feature you are looking for. It is unlikely for previous FCD files to work correctly with Flowcode and is unrecommended. The ADC TRIS REG and Mask variables control the data direction of the analogue pin without affecting any of the other pins on the port. If you need help modifying the code to a particular purpose then we are here to help.

jimhumphries
Posts: 112
Joined: Wed Oct 12, 2005 6:29 pm
Location: USA
Been thanked: 1 time
Contact:

Re: v3.6 .fcd ADC code changes

Post by jimhumphries »

Ben:

That's great news regarding v4 components and, yes, I could really use your help with the v3.6 16F876.fcd file.

My objective has been to maximize the ADC conversion rate for the 16F876 running at 4 MHz (consistent with the recommendations in the Microchip data sheet). This is important to me because I do a software peak detection and the detection accuracy is dependent on minimizing the interval between two successive samples.

The ADC portion of the code from my modified v3.2 16F876.fcd file and the code from the v3.6 file are shown below:

v3.2 (modified)
ADCCapture="char ta, cnt;\nadcon1 = 0x00;\nta = trisa;\ntrisa = trisa | 0x2F;\nadcon0 = 0x41 | (%a << 3);\ncnt =0;\nwhile (cnt <2) cnt++;\nadcon0 = adcon0 | 0x04;\nwhile (adcon0 & 0x04) ;\ntrisa = ta;\nadcon1 = 0x07;\nadcon0 = 0x40;\n"
ADCHigh="return adresh;\n"
ADCLow="char adclow;\nadclow = adresl;\nreturn adclow;\n"
ADCFull="short iRetVal;\niRetVal = (adresh << 2);\niRetVal += (adresl >> 6);\nreturn (iRetVal);\n"


v3.6
ADCCapture="//set up ADC conversion\nchar old_tris, cnt;\n#define MX_ADC_SAMP_TIME 40\n#define MX_ADC_TRIS_REG trisa\n\n//find appropriate bit\n#if (%a == 0)\n #define MX_ADC_TRIS_MSK 0x01\n adcon1 = 0x04;\n#endif\n#if (%a == 1)\n #define MX_ADC_TRIS_MSK 0x02\n adcon1 = 0x04;\n#endif\n#if (%a == 2)\n #define MX_ADC_TRIS_MSK 0x04\n adcon1 = 0x02;\n#endif\n#if (%a == 3)\n #define MX_ADC_TRIS_MSK 0x08\n adcon1 = 0x04;\n#endif\n#if (%a == 4)\n #define MX_ADC_TRIS_MSK 0x20\n adcon1 = 0x02;\n#endif\n\n//sanity check\n#ifndef MX_ADC_TRIS_MSK\n #pragma error ADC conversion code error - please contact technical support\n#endif\n \n//store old tris value, and set the i/o pin as an input\nold_tris = MX_ADC_TRIS_REG;\nMX_ADC_TRIS_REG = MX_ADC_TRIS_REG | MX_ADC_TRIS_MSK;\n\n//turn ADC on\nadcon0 = 0x81 | (%a << 3);\n\n//wait the acquisition time\ncnt = 0;\nwhile (cnt < MX_ADC_SAMP_TIME) cnt++;\n\n//begin conversion and wait until it has finished\nadcon0 = adcon0 | 0x04;\nwhile (adcon0 & 0x04) ;\n\n//restore old tris value, and reset adc registers\nMX_ADC_TRIS_REG = old_tris;\nadcon1 = 0x07;\nadcon0 = 0x80;\n#undef MX_ADC_TRIS_REG\n#undef MX_ADC_TRIS_MSK\n#undef MX_ADC_SAMP_TIME\n"
ADCHigh="return adresh;\n"
ADCLow="char adclow;\nadclow = adresl;\nreturn adclow;\n"
ADCFull="short iRetVal;\niRetVal = (adresh << 2);\niRetVal += (adresl >> 6);\nreturn (iRetVal);\n"


In the v3.2 file I changed the sample time by reducing the value 40 to the value 2 in the "nwhile (cnt <2)" statement. I think this is handled in the v3.6 code by changing "n#define MX_ADC_SAMP_TIME 40" to "n#define MX_ADC_SAMP_TIME 2".

In the v3.2 file I change the acquisition clock by writing 0X41 to the adcon0 register instead of 0X81 - "nadcon0 = 0x41" and I return the register to 0X40 instead of 0X80 when the conversion is complete - "nadcon0 = 0x80;" (ADC clock = (system clock/4)/8 instead of ADC clock = (system clock/4)/32).

I think I can do the same thing in the v3.6 code - "turn ADC on\nadcon0 = 0x81" becomes "turn ADC on\nadcon0 = 0x41" and "nadcon0 = 0x80;" becomes "nadcon0 = 0x40;".

Should that do it?

Since the conversion rate is also determined in part by the acquisition code execution time, terse code is good, voluminous code isn't good. Looking at the C files for code compiled with the v3.2 fcd and the v3.6 fcd, the v3.6 fcd compiled code has significantly more steps (although the length of the ASM code looks to be about the same for both). The v3.2 version performance is almost acceptable at 4 MHz (it is fine at 20 MHz) but the v3.6 version seems to have more "latency" so anything you can do to help me minimize the code would really help.

I use the thermometer component in the peak detector because I need to access both the high and low bytes (the v3.2 potentiometer component didn't let me do this). To detect a peak I first compare the high byte values from two successive reads of the same input channel - if the second read is less than the first I mark a peak immediately and exit the routine (the peak has already passed and the signal values are decending). If the second read is equal to the first (the peak hasn't passed yet) I compare the low bytes - I keep sampling until the second low-byte read is less than the first (the signal values are descending) then I mark a peak and exit the routine. In this way I get an acceptable performance mix of speed and precision.

Can I make a custom "thermometer" that strips out the code for changing channels and any other general purpose code that wouldn't be needed for successively sampling from the same channel and that has the shortest allowable sampling time and highest allowable conversion rate? Or, can I create additional ADC macros that, say, initialize registers so I don't have to include that code in the actual signal acquisition routine (like the LCD clear and cursor macros)?

Thanks,

Jim

Post Reply