Arduino uno Adc problem  - Page 1
Forum section: electronics / general

author: parasbhanot
author_rank: Contributor
timestamp: February 23, 2016, 10:36:09 am
content: hello everybody,i am working on project in which joystick is used to control two bipolar stepper motors with A4988 drivers. But the problem is that output of the ADC from both x axes and y axes pins is fluctuating . For x axis pin it is between 514 and 516 and for y axis pin it is between 519 and 521.when joystick is at rest position.This is the code i am using :Code:int joyPin1 = 0; // slider variable connecetd to analog pin 0int joyPin2 = 5; // slider variable connecetd to analog pin 5int value1 = 0; // variable to read the value from the analog pin 0int value2 = 0; // variable to read the value from the analog pin 1void setup() {Serial.begin(9600);}void loop() {value1 = analogRead(joyPin1);delay(10);value2 = analogRead(joyPin2);Serial.print("x value :");Serial.print(value1);Serial.print(" ");Serial.print("y value :");Serial.println(value2);delay(1000);}i have tested the above code on the following boadsArduino Uno clonesimple atmega328p with usbasp as programmer on perfboardoriginal Arduino LeonardoOnly original Arduino Leonardo is giving clean ADC output with value of 515 for x axis and 520 for y axis when joystick is at rest .atmega328p with usbasp as programmerhas more noisy outputs than myArduino UNO clone.Is this a known problem with ADC ofarduino Uno?Is there any special circuitry onArduino Leonardofor noise Reduction ?

author: FreddyVictor
author_rank: Regular Contributor
timestamp: February 23, 2016, 11:45:40 am
content: this is perfectly normalsuggest you implement a dead-band in your code to remove this

author: dannyf
author_rank: Super Contributor
timestamp: February 23, 2016, 11:50:26 am
content: What you observe is normal for any adc.However, the arduino adc function is incorrectly coded.

author: macboy
author_rank: Super Contributor
timestamp: February 24, 2016, 06:35:03 pm
content: Noise is normal. You can filter the noise both in hardware in and in software.Add a small capacitor from each analog input to ground. Try 1 uF. If the response to joystick movement becomes too slow, reduce the value of the capacitor.Average multiple samples. For example, take 16 samples and add them all together, then divide by 16 (by bit-shifting to the right by 4, not by using actual divide which is slower). The ADC can do at least 5000 samples per second by default, and much more if you manipulate the ADC clock.

author: Jeroen3
author_rank: Super Contributor
timestamp: February 24, 2016, 08:10:01 pm
content: Try an (exponential) moving average filter. Not just an normal averaging filter, because that alsodecimates. Which you might not want to.And while you're at it, left align the adc (there a option bit for that), since you need at least 10 bits for the adc. That automatically rounds to 16 bit, so why not use those 6 bits?When left aligning the range will go up to 0 to 65535, but the resolution of your adc won't!A filter now also doesoversampling, how negligible that may be here, but it means that is can also display 100.5 adc point, as in 6432 left aligned.Which could be the result of your filter.Don't try floating points, keep everything in integer math and divisions in multiples of 2. If you can.I'm 100% sure someone has already done this before on an arduino atmega. But never usefloaton an 8 bit avr.But in the end 0 to 255 might work just fine for your joystick anyways. So lowering the hardware resolution could suffice as quick fix.Here you go.https://github.com/AsheeshR/Microsmoothsee ema_filter

author: parasbhanot
author_rank: Contributor
timestamp: February 25, 2016, 05:28:31 pm
content: problem solved.Thank you everyonei tried to take an average but y-axis pin still produced (+/-)1 error.This is my average code :Code:#define sample 20 // no of sampleint joyPin1 = 0; // slider variable connecetd to analog pin 0int joyPin2 = 5; // slider variable connecetd to analog pin 1int value_1 = 0; // variable to read the value from the analog pin 0int value_2 = 0; // variable to read the value from the analog pin 1int xCod;int yCod;void setup() {Serial.begin(9600);}void loop() {int tempX =0;int tempY =0;for (int i=0 ; i<sample; i++){xCod = analogRead(joyPin1);tempX += xCod ;delay(100);yCod = analogRead(joyPin2);tempY += yCod ;}value_1 = (tempX)/sample;value_2 = (tempY)/sample;// -----------------------------------------------------------------------Serial.print("x value :");Serial.print(value_1);Serial.print(" ");Serial.print("y value :");Serial.println(value_2);delay(1000);}So i decided to neglect the noisy values when joystick is at rest position.This is what i did :Code:int joyPin1 = 0; // slider variable connecetd to analog pin 0int joyPin2 = 5; // slider variable connecetd to analog pin 1int value1 = 0; // variable to read the value from the analog pin 0int value2 = 0; // variable to read the value from the analog pin 1void setup() {Serial.begin(9600);}void loop() {int valueX ;int valueY;value1 = analogRead(joyPin1);delay(100);value2 = analogRead(joyPin2);valueX =value1 ;valueY =value2 ;if(value1 >516){Serial.print("x value :");Serial.print(valueX-515);Serial.print(" ");}else if(value1 <514){Serial.print("x value :");Serial.print(515-(valueX));Serial.print(" ");}else {Serial.print("x value :");Serial.print(0);Serial.print(" ");}if(value2 >521){Serial.print("y value :");Serial.println(valueY-520);}else if(value2 < 519){Serial.print("y value :");Serial.println(520-(valueY));}else{Serial.print("y value :");Serial.println(0);}delay(1000);}so instead of taking average i simply defined dead-zones and neglected +1/-1 values.

author: retrolefty
author_rank: Super Contributor
timestamp: February 25, 2016, 07:57:37 pm
content: Quote from: parasbhanot on February 25, 2016, 05:28:31 pmThat sounds like a reasonable solution. Any ADC measurement is going to be subject to a +/- 1 count value, regardless of what some software types might expect. ADC is where software meets the real world, it's just a matter of matching the application to the performance specifications.

author: FreddyVictor
author_rank: Regular Contributor
timestamp: February 25, 2016, 10:38:35 pm
content: Quote from: parasbhanot on February 25, 2016, 05:28:31 pmglad you have made progressyes, a dead-zone is good solution for your particular situationI would suggest that you remove your hard-coded centre values and simply perform an initial read for calibration to find out the centre values.Also, I seem to recall that for ATmega, the first ADC reading may be inaccurate and should be discarded