|
|
View previous topic :: View next topic |
Author |
Message |
jpos99
Joined: 10 Aug 2012 Posts: 14
|
Multiple ADC reading with PWM sync |
Posted: Fri Aug 10, 2012 9:18 am |
|
|
Hello, I'm testing this compiler and one of the things I would like to do is multiple analogue readings.
I'm using PIC18F4431 with compiler version 4.093. With it I'm generating a PWM pulse and I want to read two analogue inputs when there is the PWM impulse, with a certain delay of course.
The code that I have so far is:
Code: |
setup_adc(ADC_CONT_AB | ADC_CLOCK_INTERNAL);
setup_adc_ports(sAN1 | sAN1 );
read_adc(ADC_START_ONLY);
setup_power_pwm(PWM_CLOCK_DIV_4 | PWM_SINGLE_SHOT | PWM_DEAD_CLOCK_DIV_16, 1,0,2000,0,1, 63);
set_adc_channel(0);
analog1=read_adc(ADC_READ_ONLY);
set_adc_channel(1);
analog2=read_adc(ADC_READ_ONLY);
|
To do the multiple readings is just like the code that I entered or I need something more?
Its true I have some values but they are not correct. I think the PWM sync is off and the second reading does not exit.
Thank you all in advance. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 10, 2012 2:32 pm |
|
|
I'm not certain about what you really want to do. I don't know if you
want to use the Special Event Trigger from the Power PWM module to
control the A/D module, with dual simultaneous A/D channel reading.
Or, do you just want to read channel 0, and then channel 1, etc.
This thread has an example of how to do dual-channel simultaneous
sampling with the A/D converter:
http://www.ccsinfo.com/forum/viewtopic.php?t=42256
This is an advanced topic. If you are a newbie, it's going to be too difficult.
Quote: | setup_adc_ports(sAN1 | sAN1 );
|
In the code above, you specify sAN1 two times. That's not necessary. |
|
|
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Mon Aug 13, 2012 4:14 am |
|
|
Thank you PCM Programmer.
Yes I want to read the current and voltage in my load sync with the PWM signal. But as my PWM signal has some restriction. I'm generating a single shot in a interrupt routine using the Timer5 and all this is working fine, only with the readings I'm having some problems because the pulse are to fast, 10us or less.
With the example that you mention I will work to get my results. If I have any more questions I will post.
I've corrected the: setup_adc_ports(sAN1 | sAN1 ); it was an error thank you. |
|
|
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Fri Aug 17, 2012 5:25 am |
|
|
I successfully implemented the dual ADC reading. But as I mentioned in the last post I'm trying to read the current and voltage in my load. They are pulses, a representation of my PWM signal. Because my frequency is low and my pulse is very fast I had some issues with it, so I put the PWM as a single shot in a interrupt routine generated by the timer5 and is working fine, the timer5 gives the period for the PWM and in the interrupt routine I have the PWM generation.
My next step was in the same routine put the ADC reading. Done.
My question:
1) The reading is giving me no value, I think that the ADC its not synced with the PWM, because if I connect a continous voltage the ADC returns a value.
I've even put a max value record for it but nothing.
Code: |
#int_global
#int_timer5
void isr()
{
max1 = 0;
max2 = 0;
// Select pins AN0 and AN1, in Groups A and B, respectively.
setup_adc_ports(sAN1 );//| SAN1);
// Tell ADC to read continuously from input Groups A and B.
setup_adc(ADC_CLOCK_DIV_2 | ADC_CONT_B );
// Tell the ADC to put the conversion results in the fifo.
ADC_FIFOEN = 1;
read_adc(ADC_START_ONLY); // Set the GO bit in ADCON0
delay_us(10); // Wait 10us, per the 18F4431 data sheet
//Inicialliza o PWM em Single Shot
setup_power_pwm(PWM_CLOCK_DIV_4 | PWM_SINGLE_SHOT | PWM_DEAD_CLOCK_DIV_16, 1,0,3000,0,1, 63);
// Wait for the first A/D result to become available in the fifo then read it.
while(ADC_BFEMT);
analog1 = make16(ADRESH, ADRESL);
if(analog1>max1)
max1=analog1;
// Wait for the 2nd A/D result to become available in the fifo, then read it.
while(ADC_BFEMT);
analog2 = make16(ADRESH, ADRESL);
if(analog2>max2)
max2=analog2;
} |
I think the problem is related to times, what I mean is the delay between the PWM generation in the PIC and the current reading through a LEM to be available in the PIC is 5us for what I measure with a scope. I've put to put delays in the routine but still no reading. The PIC data sheet gives a minimum sample time of 56ns and my pulse is 50us long and the period is 100ms.
2) Silly question but the ADC reading is only called when I in the interrupt routine? (code above).
Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 17, 2012 12:48 pm |
|
|
Quote: | #int_global
#int_timer5
void isr()
|
Read the CCS manual before you use any of their compiler extensions.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
#int_global is used rarely and only in very specialized cases. You don't
put it in front of every isr directive.
Quote: | // Select pins AN0 and AN1, in Groups A and B, respectively.
setup_adc_ports(sAN1 );//| SAN1);
|
Here, you know you're going to be reading analog pins AN0 and AN1,
but then you only setup AN1 as analog ? Why ? My example code
for dual readings sets up both inputs as analog pins.
Then, you are doing the ADC setup every time in the Timer5 isr. Why ?
It should be setup once, at the start of main(). You haven't said what
the overall purpose of your code is. I'm not even sure that you need
an interrupt routine.
I don't really want to do this program for you. To answer your questions
about triggering the dual ADC I would basically have to do that whole
section of the project. I would have to devise a test program to prove
that it's working. I would have to do it all.
Look at this sample code from Microchip. It may help you:
Quote: |
CE031 - dsPIC SMPS ADC Triggered by PWM
|
And maybe some other sample code, nearby to that one in the list.
http://www.microchip.com/CodeExamplesByFunc.aspx
It's written in bit-access style, but it could be translated to CCS functions
if you look closely at the .LST file and compare it to the sample code. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sat Aug 18, 2012 2:50 am |
|
|
Quote: | The PIC data sheet gives a minimum sample time of 56ns and my pulse is 50us long and the period is 100ms. | I take this to mean:-
(1) Your PWM pulse is 50us wide,
(2) You are wanting to sample in that 50us window.
In another post Quote: | Yes I want to read the current and voltage in my load sync with the PWM signal. But as my PWM signal has some restriction. I'm generating a single shot in a interrupt routine using the Timer5 and all this is working fine, only with the readings I'm having some problems because the pulse are to fast, 10us or less. | So, is your pulse width 50us or <10us?
Either way you should be able to devise a test which tells you WHEN you are taking your ADC samples.
The microchip data sheet says that you SHOULD be able to sync the ADC to ANY time within the PWM pulse.
Have a look at the registers to see how your code is setting them up, cross-refer to the data sheet will tell you if they are being set as intended.
Mike |
|
|
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Sat Aug 18, 2012 7:23 am |
|
|
Thank you Mike.
Answering you question, right now the pulse is 50us but I want a minimum of 10us or less.
The problem with no value on the ADC reading was because of the PWM. I came up with a way to see the delay between the PWM pulse and the signal of current on the PIC pin, and with a scope measure a 250us delay so the code was modified.
I put the PWM generation first, the delay of 260us an then the ADC reading, is now looking like this:
Code: |
#int_global
#int_timer5
void isr()
{
max1 = 0;
max2 = 0;
// Select pins AN0 and AN1, in Groups A and B, respectively.
setup_adc_ports(sAN1 );//| SAN1);
// Tell ADC to read continuously from input Groups A and B.
setup_adc(ADC_CLOCK_DIV_2 | ADC_CONT_B );
// Tell the ADC to put the conversion results in the fifo.
ADC_FIFOEN = 1;
//Inicialliza o PWM em Single Shot
setup_power_pwm(PWM_CLOCK_DIV_4 | PWM_SINGLE_SHOT | PWM_DEAD_CLOCK_DIV_16, 1,0,3000,0,1, 63);
delay_us(260); // Delay because of the PWM modulo to came in action
read_adc(ADC_START_ONLY); // Set the GO bit in ADCON0
// Wait for the first A/D result to become available in the fifo then read it.
while(ADC_BFEMT);
analog1 = make16(ADRESH, ADRESL);
max1=analog1;
// Wait for the 2nd A/D result to become available in the fifo, then read it.
while(ADC_BFEMT);
analog2 = make16(ADRESH, ADRESL);
max2=analog2;
}
|
The problem was with sync but I wasn't understanding why until doing this test that allowed me to see the delay.
For those that came across with a problem like this, the test that a made was to put a bit toggle after the PWM code and with the scope measure the two signal the bit toggle and the signal that a I wanted to measure put the trigger on the bit toggle and see the delay, simple as that. Hope this helps any one out there.
Now is working fine, until I try to complicate the system a bit more. |
|
|
|
|
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
|