switching analog mux using pwm interrupt

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Naz99
Level 3
Level 3
10 likes given 25 sign-ins 5 questions asked

hello, I am using psoc 5lp cy8ckit-059 prototyping kit and I have built a single differential circuit as in the attachment. The plan is I want to calculate the voltage between pga_1 output and pga_2 output to find the voltage different. first the A_Mux_1 select chan 0 to let the ADC read the pga_1 output value and then the A_Mux_1 switch to chan 1 to let the ADC read pga_2 output value. The voltage that I want is the different between output 1 and output 2. So, the analog mux switching must be fast and i decide to use interrupt from pwm to do the switch.  I stuck with the A_Mux_1 switching using interrupt from pwm because when I see the serial print it shows the chan is always 0 and it seems the ADC doesn't read the chan 1 value.  

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Nazhan,

Basically your code is stuck in the ISR.   This is evident when you use the debugger with your code.

Setting a breakpoint in main() shows that the code is not executing the for(;;) loop.

The reason for this is that you didn't Start the ADC_DelSig_1.

Because of this when you were executing the ADC_DelSig_1_GetResult16() then was nothing to get and you were stalled waiting for the conversion to complete (in this case the conversion didn't start).

I've rewritten your code in two different projects.  I've attached a workspace with both of these projects.

diff_pwm1 - It performs the two channel reads (PGA_1 and PGA_2) and then performs the difference calculation.  The biggest change I made to your code is that ISR is now attached to the EOC of the ADC_DelSig.   This guarantees that the conversion is complete for the current channel and then gathers the ADC data and stores it in the respective channel RAM.   It  then switches the Amux to the next channel to scan.   The PWM will start the conversion of the next data.

diff_pwm2 - This code is similar to diff_pwm1 except that I got rid of VDAC8_4, OpAmp_1 and Amux_1.  PGA_1 is now connected to the '+' input of the ADC and PGA_2 is connected to '-' input of the ADC.   The code is significantly simplified.

Note:   I don't know your specific design criteria.   However, if the end intent is the value of PGA_1 - PGA_2 then a single ADC reading of the difference in diff_pwm2 is better and more accurate than the two ADC readings of diff_pwm1.  If for no other reason then if PGA_1 and PGA_2 are constantly changing, then a delay between the two readings could have significant errors in the difference calculations.

Another thing is the value of using 8mV as the Vref in the '-' input is not much better (or at all better) than using the ADC in single-ended mode.

An analog expert such as DennisS_46   might have better insights.

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

5 Replies
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Nazhan,

You're using a a ADC_DelSig at 16-bit resolution.   This limits your ADC conversion rate to 11Ksamples/sec.

Lowering your resolution to 8-bits will double your conversion rate.

However changing to the ADC_SAR at 12-bits, the conversion rate is 667Ksamples/sec.

Additionally if you're worried about the delay between PGA1 reading and PGA2 reading, you can use the two ADC_SARs available and synchronize the SOCs.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Nazhan,

I regret being the bearer of bad news.  I've reviewed your code and found multiple issues with your code.

Here's a list with the worst issues at the top:

  • You never start the PWM_1 component which drives your SOC (Start of conversion) to the ADC_DelSig.  There you only get one channel of data and the ISR is never triggered.
  • Once the PWM_1 is started, the ISR fires but there is no synchronization between the ISR which switches the Amux and starts the next conversion and the main() task.   It is possible to get out-of-sync and read the wrong channel's data.  Suggestion:  In the ISR before you switch the previous Amux channel:
    • Check to make sure the ADC conversion is done for the previous channel read
    • When completed, read the ADC result and store it into a RAM variable for the channel (ie chan0_results, chan1_results).  
    • Switch the Amux channel.
  • In the main() task you GetResult16() for the ADC but aren't waiting for the Conversion to be completed.  This can give you the wrong or partial results.   You need to wait for a complete conversion before reading the results.   If you take my previous suggestion above, then all you have to do in main() is display the ADC results converted to mV for each channel.

In a previous post, I suggested you can use two ADC_SARs to simultaneously read both PGA output results.

I have another suggestion.  You are using an ADC_DelSig in differential mode.  The '-' input of the ADC_DelSig is connected to a VDAC @ 8mV through a OpAmp in unity gain mode.   What is the value of this?

My suggestion is to place the PGA_1 output on the '+' input of the ADC and the PGA_2 output on the '-' input of the ADC.   This will automatically provide a signed value of the difference between PGA_1 and PGA_2.   It also makes this conversion of BOTH inputs at the same time.

Len
"Engineering is an Art. The Art of Compromise."
lock attach
Attachments are accessible only for community members.

Thank you Len for the answer. For this project, I want the ADC del to read at 16-bits and the conversion rate to be atleast 4k sps and it should not be too much from that. So I use external clock on the ADC del to make the conversion rate at above 4k sps. The VDAC @ 8mV through the Op amp is used as reference voltage and I want the adc del to find the difference between diff(chan0 - chan1) and reference voltage. I tried to switch the analog mux using pwm interrupt but when I programmed it nothing show up in the serial display. I think my coding is wrong but I have no idea how to fix it.

0 Likes
lock attach
Attachments are accessible only for community members.

Nazhan,

Basically your code is stuck in the ISR.   This is evident when you use the debugger with your code.

Setting a breakpoint in main() shows that the code is not executing the for(;;) loop.

The reason for this is that you didn't Start the ADC_DelSig_1.

Because of this when you were executing the ADC_DelSig_1_GetResult16() then was nothing to get and you were stalled waiting for the conversion to complete (in this case the conversion didn't start).

I've rewritten your code in two different projects.  I've attached a workspace with both of these projects.

diff_pwm1 - It performs the two channel reads (PGA_1 and PGA_2) and then performs the difference calculation.  The biggest change I made to your code is that ISR is now attached to the EOC of the ADC_DelSig.   This guarantees that the conversion is complete for the current channel and then gathers the ADC data and stores it in the respective channel RAM.   It  then switches the Amux to the next channel to scan.   The PWM will start the conversion of the next data.

diff_pwm2 - This code is similar to diff_pwm1 except that I got rid of VDAC8_4, OpAmp_1 and Amux_1.  PGA_1 is now connected to the '+' input of the ADC and PGA_2 is connected to '-' input of the ADC.   The code is significantly simplified.

Note:   I don't know your specific design criteria.   However, if the end intent is the value of PGA_1 - PGA_2 then a single ADC reading of the difference in diff_pwm2 is better and more accurate than the two ADC readings of diff_pwm1.  If for no other reason then if PGA_1 and PGA_2 are constantly changing, then a delay between the two readings could have significant errors in the difference calculations.

Another thing is the value of using 8mV as the Vref in the '-' input is not much better (or at all better) than using the ADC in single-ended mode.

An analog expert such as DennisS_46   might have better insights.

Len
"Engineering is an Art. The Art of Compromise."
lock attach
Attachments are accessible only for community members.

Nazhan,

Here is an LTSpice sim of your TopDesign analog components.

Len_CONSULTRON_0-1650887565667.png

I've attached it here.

Len
"Engineering is an Art. The Art of Compromise."