Wobbly resistance readings

Post here first, or if you can't find a relevant section!
arpruss
Posts: 83
Joined: Sat Dec 21, 2019 10:06 pm

Wobbly resistance readings

Post by arpruss »

In my USB paddle game controller project (https://github.com/arpruss/paddlecontrollers), I was initially getting a lot of wobble in reading the controller pots (which were 400K pots): the paddles in the Pong game were shaking very visibly. This seems to be especially bad when the paddles are plugged into my Raspberry PI 3+.

My electronics was straightforward: ground to one end of pot, 3.3V to other end, and ADC to the sweeper, and then analogRead().

I wanted to share what I did to alleviate the problem, and also ask if anybody has any better ideas. Maybe some of what I did is unnecessary.

First, I tried a simple low-pass filter, where I replace each reading with something like currentValue = reading * (1-alpha) + currentValue * alpha. I tried some alpha values, and I could remove the wobble, but the result was unplayable lag. I am guessing this is roughly the digital version of adding a capacitor, no?

I then went for a really complicated algorithm:

1. Each time the ADC is read, it is actually read 8 times (with no pauses in between) and averaged. When I talk of ADC "raw" readings below, that "raw" reading is actually an average from 8 readings.
2. Add hysteresis: when an raw reading deviates less than 40 units (on the 4096 unit ADC range) from the previous value sent to the host, the new reading is discarded, and the previous value is sent to the host.
3. But the hysteresis is 2% of the range, so it prevents precise control. So, to allow for precise control, if there are 8 successive hysteresis rejections, send to the host the average of the 8 rejected hysteresis readings (and the average then becomes the new value for the hysteresis rejection filter next time). This generates some lag for small pot movements, but lag is more of a problem for large movements.

This works fairly well, but seems really complicated.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Wobbly resistance readings

Post by stevestrong »

You have to make sure that no digital IO process takes place during ADC acquisition. otherwise it will be very disturbed.
arpruss
Posts: 83
Joined: Sat Dec 21, 2019 10:06 pm

Re: Wobbly resistance readings

Post by arpruss »

That's a nice idea. Disabling interrupts for the read does seem to help a little bit. But doesn't solve the problem entirely.

UPDATES:

1. I've also noticed another weird thing: there is a kind of "afterimage" from the first pot reading.

I did this experiment: keep pot 2 unmoved and turn pot 1 from the lowest to the highest value. As a result, the value from pot 1 changes by about 0.7% (in the same direction).

If I don't read pot 1 in the code, turning it affects nothing.

Solution: use a different ADC for each pot. I feel I shouldn't need to do that, but it helps:

Code: Select all

uint16 analogRead2(uint8 pin) {
    return adc_read(pin == ANALOG1 ? &adc1 : &adc2, PIN_MAP[pin].adc_channel);
}
3. I just realized that I'm using one of the fake 103c8's that I think are 103c6's.
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: Wobbly resistance readings

Post by ag123 »

i think this is related to the potentiometer, variable resistance as well.
i actually tried this experiment once, take a 2B pencil color an area on a paper with a rather thick layer of graphite
then measure the resistance. you would see the resistance fluctuate significantly between measurements with a multimeter.
so this is not limited to stm32
my thoughts are to try different materials in the build of the variable resistance, e.g. nichrome or kanthal wire variable resistance would possbly work better
misfet
Posts: 2
Joined: Sun Apr 12, 2020 11:17 pm

Re: Wobbly resistance readings

Post by misfet »

Greetings,

If you read the documentation on the adc for whichever device you are using, I think you will find that it needs a reasonable current allowance. Connecting from a 400k pot I would expect to find well outside the recommended range. The signal should go from the pot to an opamp to the adc. I think your observations indicate this is causing some of your issues.

Supply the required current, and improve the signal to noise ratio.

Also, mcu's are noisy. In the past I have found setting all disused io to input pullup, or pulldown has made a sizable difference to noise at the adc's. Do not leave disused io floating. In addition to reducing software activity per Steve's comment. Both of these points are usually buried deep in product documentation.

Improve the S/N ratio, and reduce the noise. As ag points out, pots are considered noisy components. With a good current feed to the adc's, you can reliably use higher speed sampling and then average the result. This gets around noisy components.

mf
arpruss
Posts: 83
Joined: Sat Dec 21, 2019 10:06 pm

Re: Wobbly resistance readings

Post by arpruss »

1. Pulling down the other pins doesn't seem to do anything in my testing.

2. In further testing, turning off interrupts during acquisition doesn't seem to matter much.

3. I found that the limiting factor in my project is USB sending, which happens in the background. That means that I can increase the sampling time to 239 ADC cycles and average 80 readings per pot, without changing the data rate (83 Hz). That makes a difference, and I was able to reduce the hysteresis to 0.5%.

The main lesson for me so far was to use separate ADCs for the two pots.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Wobbly resistance readings

Post by stevestrong »

The USB (and other HW interfaces as well) can massively introduce noise in your A/D conversion.

In one of my projects I sampled 4 input audio signals with one bluepill and transmitted the sampled data to another one over SPI in the time after the sampling period.
So during acquisition no other HW interface was active. This way I could get rid of sporadic noise and greatly improve SNR.

Btw, median instead mean average could also improve filtering.
arpruss
Posts: 83
Joined: Sat Dec 21, 2019 10:06 pm

Re: Wobbly resistance readings

Post by arpruss »

I don't know how exactly to check if USB is finished transmitting, though I suppose I could just add a simple delay(13) (I know that the transmission takes about 12ms). However, the cost of waiting for USB to finish transmitting is that I introduce more latency, and so I wouldn't be able to afford as many samples.

Currently, all my filtering has removed any jitter other than an occasional rare flip of the least significant bit (on a 10 bit output). This is good enough for me.

I just added the same filter into an old project, where I converted a Gameport joystick to USB, and it works way better.
mrburnette
Posts: 633
Joined: Thu Dec 19, 2019 1:23 am
Answers: 7

Re: Wobbly resistance readings

Post by mrburnette »

Respectfully:

All the talk about opAmps, multiple software reads, and the use of delay(x) is really rather dangerous suggestions.

Please read cd00211314-how-to-get-the-best-adc-accuracy

Some critical takeaways:
The ADC includes the oversampling hardware which
accumulates data and then divides without CPU help.
The oversampler can accommodate from 2 to 256 time
samples and right shift from one to eight binary digits.
The sequencer allows the user to convert either up to 19
channels in ascending or descending order or up to 8
channels in a user-defined order.
Two sampling periods can be programmed. Each
channel is assigned one of these two values.
The ADC offers a self-calibration mechanism for the
offset. It is recommended to run the offset calibration on
the application if the reference voltage changes more
than 10% so this would include emerging from Reset or
from a low-power state where the analog voltage supply
has been removed and reinstated.
In my many years of playing around on the bench and a now&then consulting opportunity, most A/D issues are from reference voltage concerns. Do not spin cpu cycles unnecessarily, let the hardware work as intended.

Critical A/D needs are best satisfied by a separate analog reference. The default digital domain voltage can be very noisy. Double-sided PCB that only implement a single ground-plane are poorly designed boards. Unused and floating analog inputs to the mux should be grounded (to analog ground plane.)

Bypass capacitors need to have a very low ESR.

Ray
arpruss
Posts: 83
Joined: Sat Dec 21, 2019 10:06 pm

Re: Wobbly resistance readings

Post by arpruss »

Updates:

1. I opened my hardware up, and I am using 30K pots, not 400K as stated before. My mistaken.

2. While I don't have any noticeable wobbling on my Windows laptop with all my changes, I have lots of wobbling on my Raspberry PI, mainly on the second pot. I wonder if this is due to the PI's power supply being overworked.

3. Delaying the acquisition until the USB send is finished doesn't seem to help.
Post Reply

Return to “General discussion”