Array readout using PSoC 5 AMUX and ADC

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

cross mob
b4balu
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

I am working on a project for array readout. I am using CY8CKIT-059.

There are 8 analog inputs that I have to read  sequentially using the ADC and AMUX.

I was wondering if there is any way I can  connect all the other inputs to ground while only one of the analog inputs is connected to the ADC. 

Thanks in advance

Balu

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

Balu,

I am currently looking at your one sensor project.

I made some changes to get it working.

My original project I posted had two major issues.

  1. The IDAC was set to Polarity: Negative (Sink).  Oops! It is now changed to Polarity: Positive (Source).
  2. The ADC_DelSig_Start() starts the ADC but DOES NOT start the conversion.  Oops!  I changed the ADC from continuous conversions to a "single-shot" and I start the conversion AFTER changing the sens_data state.   Also, I change the Input range: to 0V to 6.144V.  This works better.

I should note that with the IDAC set to 1.000mA, the maximum sense resistance that could be measured needs to be below 4.6K ohms.

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

View solution in original post

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

Baiu,

I'm working on a recommendation.

The PSoC5LP has very good analog isolation in their Amux.  Is there a specific reason that you are trying to GND all other non-active analog inputs?

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

Hi Len,

Thanks for your response.

I have a specific circuit to implement. It is the Zero potential circuit where only one row is excited at a time and all the other rows are connected to ground. Also, at the readout side, only one column in connected to the ADC (with or without an amplifier). I have attached a rough diagram. 

Is there any way I can do it using the PSoC without using many additional components?

Also, what is the state of floating pins?

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

Balu,

Take a look at my new attached project.

I adopted your array.png configuration to "read" 64 Analog inputs in the matrix with a 8x8 row/column configuration.

I changed the next_AI_isr() to increment the column then increment the row every time the column goes back to 0.

I should point out to you that your matrix configuration even when each row that is not active is "floating" and the column not active is "grounded" will corrupted the active row/column resistor by all the inactive resistors.  These inactive resistors are still connected to one another.

It would be "better" if the inactive columns are left to float.  Even in this configuration, the inactive resistors on the active row will effect the active resistor.

In general, matrix scanning is better used on digital signals.  Depending on the matrix configuration reverse current blocking diodes are used to isolate interference of other inactive switches in a digital matrix.

The common row and column connections can easily corrupt the intended analog signal to scan.  

To prove this, I noticed you created your array schematic on a simulation program.  If you complete the schematic with proper switch stimulus you can see for yourself that the current flowing through the sensing row is not what you expected due to the cross-connections.

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

Balu,

I ran three quick sims of your array with two of them slightly modified.

Here's a one channel simulation of your original array with inactive rows and columns grounded.

Len_CONSULTRON_0-1670083476484.png

In this simulation, I've took inactive rows and let them float and the columns are still grounded.

Len_CONSULTRON_1-1670083576811.png

In this simulation, I've took inactive rows and let them float and the columns are also floating.

Len_CONSULTRON_3-1670083665667.png

Here is the sim results of reading a single 1K resistor in the matrix:

Inactive Rows Inactive Columns AI_Scan
GND GND 0.624V
FLOAT GND 0.701V
FLOAT FLOAT 4.988V

You can see the more accurate reading is when all inactive rows and columns are floating.

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

Thanks for taking your time and giving an elaborate explanation @Len_CONSULTRON. I am quite new to PSoC and am yet to learn all the features and capabilities. (Moving from Arduino to PSoC)

I got the mistake in my understanding of the circuit. The zero potential circuit without Opamps will create multiple parallel current pathways that will affect the reading. I have attached herewith the new project. The program is a little lengthy and not well written, but I guess it will get the job done.

What I did is, I connected all the analog signals to an external opamp inverting amplifier. This ensures the inputs are connected to virtual ground. Then inverted the signals to connect to SAR ADC through AMux.

At the input side, I am setting each input to digital 1 sequentially and the others to digital 0 through an opamp buffer.

I have the following doubts though.

  1. Is there any difference in using Analog Mux and Analog hardware mux?
  2. Is there an easier way to do this?
  3. Is my UART use correct?
  4. I want to get data frames of 64 sensing elements which I will be processing further. Will this work?

PS: I have used only a 4x4 array instead of my actual 8x8 to reduce complexity. 

0 Likes

Balu,

I've had a chance to review your "simple" project.

You stated:


The program is a little lengthy and not well written, but I guess it will get the job done.

Have you actually tested this circuit and the code?  I don't think so.

Let me explain.

I don't see the need for the inverting opamp analog input front-end with virtual GND. (Also, I don't see the "virtual" GND.)  I don't see the advantage.

Len_CONSULTRON_0-1670190747259.png

As long as the source voltage is between 0V and the ADC max input voltage, you should be OK with just reading the AI_x directly.  No need for more external components.  

You're use of opamps (in follower mode) to drive the row stimulus is not only overkill but it when the opamp input is set to 0 "Pin_x_Write(0)" it actuals GNDs the stimulus for that row instead of letting it float (which is the best result from my previous post).

Len_CONSULTRON_1-1670191203111.png

IMHO, you would be better off with having Pin_x configured in "Open drain, drives high" mode and directly driving the row stimulus.

In your main() code you have the following repeated 4 times.

main()
{
...
        Pin_x_Write(1);
        CyDelay(5);
        
        AMux_Select(0);
        int px1 = ADC_SAR_GetResult16(); 
        AMux_Select(1);
        int px2 = ADC_SAR_GetResult16();
        AMux_Select(3);
        int px3 = ADC_SAR_GetResult16(); 
        AMux_Select(4);
        int px4 = ADC_SAR_GetResult16();

        Pin_x_Write(0);
        CyDelay(5);        
...
}

The issue here is you are assuming that a new ADC conversion occurs when IMMEDIATELY after switching the AMux to a new channel.  Also, the ADC_SAR_GetResults16() is a non-blocking function.  In other words, it doesn't wait for the conversion to complete before returning.  Therefore, most likely the results of px1 through px4 will be the same.

Here is a text clip from the description of the ADC_SAR_GetResults16() function in the ADC_SAR.c file.

/*******************************************************************************
* Function Name: ADC_SAR_GetResult16
********************************************************************************
*
* Summary:
* Returns a 16-bit result for a conversion with a result that has a resolution
* of 8 to 12 bits.
* ADC_SAR_IsEndConversion() should be called to verify that the data
* sample is ready
* ...

As indicated, the ADC_SAR_IsEndConversion() should be called BEFORE each ADC_SAR_GetResults16() to wait for the conversion to complete before obtaining the results.

 

I applaud your choice to convert from the Arduino platform to the PSoC5LP platform.   I hope you find the PSoC5LP IC to be an improvement as I have.

There are specifics about this project that you have not revealed.  (Ie.  Why create a X by X matrix of fixed resistors?)  I can respect keeping certain things "close to the chest".

However, if you are willing to share with the forum, it may be possible for others such as myself to suggest a better solution.  For example, the PSoC5LP has internal HW resources such as opamps, VDACs, IDACs and other 'beautiful' things that might help create a low-cost solution where these HW resources can be connected internally at design-time without need many external wiring or components.

Now to answer your questions:


  1. Is there any difference in using Analog Mux and Analog hardware mux?

There is no internal HW difference.  The Amux is just using register control of the internal analog routing switches.  The difference in the components are the SW implementation (API calls) on how to access and control these analog switches.


2. Is there an easier way to do this?

Not really.  The use of the AMux components are to simplify and reduce your overall BoM costs.


3. Is my UART use correct?

It looks correct for using the USB_UART.

4. I want to get data frames of 64 sensing elements which I will be processing further. Will this work?


In theory, if you get the 4x4 to work, it should be scalable to a 8x8 matrix.

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

HI Len,

You are right. I haven't tested the circuit. I was trying to implement this desired circuit. (From: https://link.springer.com/article/10.1007/s12541-018-0057-4 ).  

b4balu_1-1670218739516.png

The authors had compared different readout circuits and concluded that this one gives better immunity from crosstalk. So I was trying to implement the circuit with PSoC.

The reason to implement the following circuit was to get the Trans-impedance amplifier (from the desired circuit above) and to again invert the result (to get an amplified positive AI_x) for the ADC.

b4balu_0-1670218706228.png

When the AI_x are connected to the amplifier, the potential at the 0 (vitrual gnd) but the high input impedance of inverting amplifier makes sure no current is drawn by the circuit. This was my logic. Am not sure if I was wrong there.

As for the follower mode at the input side ,

b4balu_2-1670219853000.png

I was trying to implement the buffer in the desired circuit above. Here again, when the Pin_x is set to 0, the rows are all at zero potential and that was the logic. Again, I am not sure if I am entirely correct. 

So basically, except for the excited row (Pin_x) and the analog input that is read (AI_x) all other rows and columns will be at zero potential. And my idea was there will not be any parallel parasitic current pathways (because of the high input impedance of opamps). 

Thanks a lot for pointing out the mistake in using ADC_SAR_GetResults16(). I guess I was just translating the Arduino code to PSoC without understanding the instructions clearly.

I have no issues revealing the details of the project.

I am trying to design a low crosstalk piezoresistive sensor array readout circuit. I will be experimenting with different materials. The base resistance will remain constant (when no pressure is applied) but when loaded the resistance will always decrease (and hence the possibility of parallel parasitic current pathways). The base resistance depends on the material, but right now it is around 2 kilo ohms. 

I know that PSoCs are very powerful and I can reduce the circuit and wiring complexity by a great deal, which is why I decided to switch.

Thanks again for all the answers @Len_CONSULTRON, hope I can get some more idea about the circuit implementation.

In the meanwhile, I will try to implement the circuit with floating rows and columns and see how it looks.

Balu   

 

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

Balu,

Thank you for sharing your design intent.  You are trying to create a circuit to measure a piezo-resistive matrix.

I've read the abstract of the reference you provided.   I get that the authors are trying to nullify the measurement errors induced to crosstalk across the matrix connections.

Since I don't have access to the entire paperwork, I cannot judge their work.

Personally, I can't see how cross-current flow through the non-scanned resistors will be significantly nullified.   This is especially problematic when the non-loaded and loaded resistance delta is small.  It is further complicated when the non-scanned resistors are loaded to unknown degrees.

I believe the only practical way is to use a massive cross-point switch.  You are trying to implement the matrix with X outputs by X input/outputs.   However, it might only be practical to ditch the matrix and use an individual analog switch to each resistor to be measured.

You can use CPU addressable analog cross-point switches.  They have a large pinout (as expected).  With the PSoC5 you could support a large number of resistors depending on the CPU pinout type you use.

I've have taken another "kick at this can".  

I restructured the project to support an 8x4 configuration of measuring the resistance of each element with reasonably achievable isolation to the other elements.

I've attached the project  (untested on my part) with these changes.  It uses 4 8-bit output ports to set only one bit at a time to GND.  All other port pins are floating.

The measurement is taken by using the PSoC5LP IDAC component set to 1mA.  The measurement is read at the IDAC output.   With the element at 2K ohms, the expected voltage is 2.000V.   With the element at 1K ohms => 1.000V   100 ohms => 0.100V

The ohms computation is basically Vmeas/1.000mA = Rmeas.  This is basically the same method used on DMMs to measure unknown resistances.

The output of the project displays the resistor element (stepping through all 32) ADC results and computed resistance.

As you can see from the following pic of the schematic, there is only 33 pins used for measuring the 32 resistor elements.

Len_CONSULTRON_0-1670259853819.png

I've performed a quick sim and have received very good results (high isolation).

 

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

Hi Len,

Thanks for showing me that IDAC can be used for my purpose. I didn't know how it could be used.

I have been trying out the program you had sent on my PSoC 5. For some reason it is not working. Instead of using the array, I started with just one sensor(resistor) and was trying to get the readout using the ADC and UART. 

Instead of using a switch:case, I just set a pin to low to read the resistance value and then back to high (drive mode: open drain drives low) as you had sent. Could you please take a look and tell me what I am doing wrong? I tried it with both DeltaSigma as well as SAR ADC.

Thanks, 

Balu 

0 Likes
b4balu
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

Hi Len,

Thanks for showing interest. Could you please tell me the simulation software that you are using? I will also run the simulation and see how different circuit configurations work. Also, can you have a quick look at the project I have sent here based on the one you sent me? I wanted to do a 4x4 array and hence the name (4x4_individual), but couldn't get one sensor to work. 

I think it is a simple mistake but can't find what it is.

Thanks,

Balu

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

Balu,

I am currently looking at your one sensor project.

I made some changes to get it working.

My original project I posted had two major issues.

  1. The IDAC was set to Polarity: Negative (Sink).  Oops! It is now changed to Polarity: Positive (Source).
  2. The ADC_DelSig_Start() starts the ADC but DOES NOT start the conversion.  Oops!  I changed the ADC from continuous conversions to a "single-shot" and I start the conversion AFTER changing the sens_data state.   Also, I change the Input range: to 0V to 6.144V.  This works better.

I should note that with the IDAC set to 1.000mA, the maximum sense resistance that could be measured needs to be below 4.6K ohms.

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

Hi Len,

Thanks loads for the solution. It is working now!

I did figure the first issue about the polarity of IDAC. I had changed it to source, but didn't really change the ADC from continuous to single shot. 

I tested it with one 2.2k ohm resistor. and the serial terminal was showing around 5000mV. When I put two in parallel, it showed around 2300mV (snapshot attached below).  

b4balu_0-1670555769401.png

I will check the current in the IDAC and try to understand what is happening. 

Also, just a couple of quick questions. What simulation software did you use to run those resistor network simulations? And for the row and column configuration I sent to you do you think I can use this same readout circuit? I will test them myself. Just wanted to know an opinion from you if you don't mind.

Thanks a lot again,

Balu

0 Likes

Balu,

I run the simulations using LTSpice.

It's from Analog Devices Inc.  and its FREE!!!

link: ltspice-simulator 

The row/column configuration circuit you originally provided will not provide accurate results because multiple sensors are connected to the same column.  This causes parasitic current flow through most of the other sensors.

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

Balu,

If you decide to get LTSpice here are two sims using the IDAC to save you time.

 

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

Balu,

A colleague of mine with vastly more analog experience than me looked at this post with the references you provided.

He provided the following comments:

"The schematic in his reference document does not fit single supply operation.
For example, set Row sw1 high, then the buffer output is high. This puts a positive voltage on the drive side of Rr1c1, Rr1cy... Rr1cn. The output of Rf1 is Vbuf*(-Rf/(Rr1c1||Rr2c1||Rrmc1) if row2 buffer is driven to ground. No matter the connection, the output of opamp on col1 will be negative, i.e., out of the opamp's nominal range. OOPS.
If you float the undriven rows, the output on col1 will be affected by "leakage" through Rrxc1 to Rrxc2 and Rrxc3 back to the buffered drive on Row1. AND, there is further leakage back to the inverting inputs of the transimpedance amps. The inputs of the TIAs must be biased somewhere other than Vss. I don't see a good way to reduce the cross-talk from having Rrxcy's changing the output on Rr1c1. Driving the non-addressed rows to any point will result in varying voltages as a function of the value of Rrxcy. My recommendation is to put another switch at the top of each column,  then the multiplexer is on the INPUT of the TIA. This saves a few parts. The buffers could be replaced with direct digital drives I've got to look at this more carefully. My concern is that a hard force on Rr2c3 could have the same result as a light force on Rr1c1. A sim with randomized Rxcy values might provide some information. this is an algebraic problem."

It appears from the comment that using a bi-polar supply to the opamps and TIAs have a better chance of working but still has problems.

New Question:  Is the piezo-resistive matrix intended to be used in "binary" mode?

If the end goal is to use the piezo-resistive matrix as a touch-sensitive X_Y device then you may be able to simplify the circuit even more (remove the ADC and replace with a VDAC and a Comparator).   If parasitic leakage currents are insignificant, then they may be effectively compensated for by a different setting of the threshold for the comparator.  In this method you can probably implement a row/column connection strategy to reduce the pinout requirements.

 

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

Hi Len,

Thanks for discussing my problem with your colleague. Both you and your colleague are right about the parallel parasitic resistances and the output of opamp being negative, which is why I was trying to find workarounds. 

This was what was discussed in the paper I had sent you. If you can do a google image search for "Experimental Investigation of Measurement Error in Networked Resistors Arrays Based on Zero Potential Method" you can see the 4 different circuits they have used to solve this problem or at least reduce the crosstalk. 

All the sensor array networks have this same problem. I was trying to make a 64 element 8x8 array with coplanar electrodes where the rows and columns are shorted separately (8 rows and 8 columns = 16 terminals in total) 

Also, the sensor is not binary and hence I need the analog readout for individual sensing elements.

b4balu_2-1670462689583.png

This is my electrode array with outer and inner concentric electrodes.

Thanks,

Balu

 

 

 

0 Likes

Balu,

Thanks for sharing your further research references.

I've Googled the "Experimental Investigation of Measurement Error in Networked Resistors Arrays Based on Zero Potential Method" you mentioned and found some analysis of different circuits.  

I'll be honest with you. I'm still trying to wrap my head around it to see how they are effectively cancelling out most adjacent resistor parasitic effects.

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

Balu,

Shorting input pins to the ground will short the outputs of your sensors, isn't it?

Typically, the crosstalk between channels is not significant, unless ADC sample rate is going into 100+ kHz range.

One way to reduce the crosstalk is to double the amount of channels (16), and ground each second input. Note that inputs should also be loaded to some low resistors, say 100-200 oHms, to reduce crosstalk. 

0 Likes

Hi Odissey1,

Thanks for your response.

I think the Zero potential circuit works in this fashion. My sampling rate is much lower. Could you please let me know how this is implemented? I am trying to reduce the crosstalk in the array readout.  

0 Likes
lock attach
Attachments are accessible only for community members.
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Balu,

 is correct.  There may be another method but it is not as straightforward.

I've attached a very simple project that does what you requested.  I haven't tested it yet but it should work to store each analog input into the ai_results[] array.

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

Thanks Len,

I will test the project you have sent next week. My circuit is similar to the one you sent me. I am just worried about the floating inputs. What is the condition of those pins? Are they high impedence?

 

0 Likes

Balu,

The code only allows one input to be configured as Analog-HiZ at a time.  This is the input to sample with the ADC.

All the other inputs are reconfigured to be outputs set to low (GNDed as you requested).  Therefore these inputs are not floating but grounded.

When isr_next_AI occurs are the each of the current conversion, the AI input that got converted will be reconfigured as an output low and the next input in the sequence will be configured as drivemode: Analog-HiZ.  and the ADC will be signaled to start the next conversion.

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