Author Topic: Arduino uno Adc problem  (Read 3650 times)

0 Members and 2 Guests are viewing this topic.

Offline parasbhanotTopic starter

  • Contributor
  • Posts: 16
  • Country: in
Arduino uno Adc problem
« on: February 23, 2016, 10:36:09 am »
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: [Select]

 
 int joyPin1 = 0;                 // slider variable connecetd to analog pin 0
 int joyPin2 = 5;                 // slider variable connecetd to analog pin 5
 int value1 = 0;                  // variable to read the value from the analog pin 0
 int value2 = 0;                  // variable to read the value from the analog pin 1

 void 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 boads

  • Arduino Uno clone
  • simple atmega328p with usbasp as programmer on perfboard
  • original Arduino Leonardo

Only 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 programmer has more noisy outputs than my Arduino UNO clone.

Is this a known problem with ADC of arduino Uno ?
Is there any special circuitry on Arduino Leonardo for noise Reduction ?

 
« Last Edit: February 23, 2016, 12:31:48 pm by parasbhanot »
 

Offline FreddyVictor

  • Regular Contributor
  • *
  • Posts: 164
  • Country: gb
Re: Arduino uno Adc problem
« Reply #1 on: February 23, 2016, 11:45:40 am »
this is perfectly normal

suggest you implement a dead-band in your code to remove this
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Arduino uno Adc problem
« Reply #2 on: February 23, 2016, 11:50:26 am »
What you observe is normal for any adc.

However, the arduino adc function is incorrectly coded.
================================
https://dannyelectronics.wordpress.com/
 

Online macboy

  • Super Contributor
  • ***
  • Posts: 2279
  • Country: ca
Re: Arduino uno Adc problem
« Reply #3 on: February 24, 2016, 06:35:03 pm »
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.
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4091
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: Arduino uno Adc problem
« Reply #4 on: February 24, 2016, 08:10:01 pm »
Try an (exponential) moving average filter. Not just an normal averaging filter, because that also decimates. 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 does oversampling, 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 use float on 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/Microsmooth see ema_filter
« Last Edit: February 24, 2016, 08:13:32 pm by Jeroen3 »
 

Offline parasbhanotTopic starter

  • Contributor
  • Posts: 16
  • Country: in
Re: Arduino uno Adc problem
« Reply #5 on: February 25, 2016, 05:28:31 pm »
 :)
problem solved.
Thank you everyone

i tried to take an average but y-axis pin still produced (+/-)1 error.

This is my average code :

Code: [Select]
#define sample 20     // no of sample

 
 int joyPin1 = 0;                 // slider variable connecetd to analog pin 0
 int joyPin2 = 5;                 // slider variable connecetd to analog pin 1
 
 int value_1 = 0;                  // variable to read the value from the analog pin 0
 int value_2 = 0;                  // variable to read the value from the analog pin 1
 
 int xCod[sample];
 int yCod[sample];

 void setup() {
 
  Serial.begin(9600); 
 }


 void loop() {

    int tempX =0;
     int tempY =0;
   
   
  for (int i=0 ; i<sample; i++){
   
    xCod[i] =  analogRead(joyPin1);
        tempX += xCod[j] ;
    delay(100);
    yCod[i] =  analogRead(joyPin2);
        tempY += yCod[j] ;       
       
  }

  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: [Select]

 int joyPin1 = 0;   // slider variable connecetd to analog pin 0
 int joyPin2 = 5;   // slider variable connecetd to analog pin 1
 int value1 = 0;    // variable to read the value from the analog pin 0
 int value2 = 0;    // variable to read the value from the analog pin 1

 void 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.
 

Offline retrolefty

  • Super Contributor
  • ***
  • Posts: 1648
  • Country: us
  • measurement changes behavior
Re: Arduino uno Adc problem
« Reply #6 on: February 25, 2016, 07:57:37 pm »
:)
problem solved.
Thank you everyone

i tried to take an average but y-axis pin still produced (+/-)1 error.

This is my average code :

Code: [Select]
#define sample 20     // no of sample

 
 int joyPin1 = 0;                 // slider variable connecetd to analog pin 0
 int joyPin2 = 5;                 // slider variable connecetd to analog pin 1
 
 int value_1 = 0;                  // variable to read the value from the analog pin 0
 int value_2 = 0;                  // variable to read the value from the analog pin 1
 
 int xCod[sample];
 int yCod[sample];

 void setup() {
 
  Serial.begin(9600); 
 }


 void loop() {

    int tempX =0;
     int tempY =0;
   
   
  for (int i=0 ; i<sample; i++){
   
    xCod[i] =  analogRead(joyPin1);
        tempX += xCod[j] ;
    delay(100);
    yCod[i] =  analogRead(joyPin2);
        tempY += yCod[j] ;       
       
  }

  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: [Select]

 int joyPin1 = 0;   // slider variable connecetd to analog pin 0
 int joyPin2 = 5;   // slider variable connecetd to analog pin 1
 int value1 = 0;    // variable to read the value from the analog pin 0
 int value2 = 0;    // variable to read the value from the analog pin 1

 void 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.

  That 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.

 

Offline FreddyVictor

  • Regular Contributor
  • *
  • Posts: 164
  • Country: gb
Re: Arduino uno Adc problem
« Reply #7 on: February 25, 2016, 10:38:35 pm »
:)
problem solved.
Thank you everyone
<snip>
glad you have made progress :)

yes, a dead-zone is good solution for your particular situation

I 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
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf