NOISE

Hi there,

I am new to arduino. Recently I tried the Arduino Duemilanove, which was the basic board. I connected a accelerometer to the analog input and PWM was successfully generated. The servo did move accordingly, however I realise that there's some noise either internal or external, that makes the servo jerk when the accelerometer is in rest, any good way to recommend me in removing/filtering the noise?

Can show a diagram if possible?

Thanks in advance!

I connected a accelerometer to the analog input and PWM was successfully generated. The servo

You fed a servo PWM?

Sorry, that is not the right way to drive a servo - have a look at the Servo libraries.

A very simple filter:

int filtered = 0;
const int FILTER_CONST = 4;
...
...

int newVal = analogRead (potPin);
filtered = (filtered - (filtered / FILTER_CONST)) + (newVal / FILTER_CONST);

I thought servos used 50hz PWM as a control signal?
2.5% to 12.5% duty cycle to give end-to-end control.

50Hz yes, PWM no; well, not exactly.
The rate and duty cycles you mention will work, but the standard PWM pins don't run at 50Hz, more like 4 or 500Hz, which a standard R/C servo won't like.
Strictly speaking, R/C servos use Pulse Position Modulation (PPM), not Pulse Width Modulation (PWM).
The distinction is a fine one.

Hi AWOL, below is your code:

int filtered = 0;
const int FILTER_CONST = 4;
...
...

int newVal = analogRead (potPin);
filtered = (filtered - (filtered / FILTER_CONST)) + (newVal / FILTER_CONST);

And my program is:
#include <LiquidCrystal.h>
#include <SoftwareServo.h>

SoftwareServo rudder; // create servo object to control a servo
SoftwareServo aileron; // create servo object to control a servo
SoftwareServo pitch; // create servo object to control a servo

//=====================================Accelerometer============================================
int x_pot = 0; // analog pin used to connect the potentiometer
int x_val; // variable to read the value from the analog pin
int x_display; // variable to read the value from the analog pin

int y_pot = 1; // analog pin used to connect the potentiometer
int y_val; // variable to read the value from the analog pin
int y_display; // variable to read the value from the analog pin

//=====================================Joystick=======================================================
int x_joy = 2; // analog pin used to connect the potentiometer
int z_val; // variable to read the value from the analog pin
int z_display; // variable to read the value from the analog pin

int y_joy = 3;
//===================================Switch================================================
int buttonPin = 7;
int buttonState =0;

LiquidCrystal lcd(6, 7, 8, 2, 3, 4, 5);

void setup()
{
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
//rudder.attach(12); // attaches the servo on pin 9 to the servo object
aileron.attach(11); // attaches the servo on pin 9 to the servo object
pitch.attach(10); // attaches the servo on pin 9 to the servo object
}

void loop()
{
buttonState = digitalRead(buttonPin);
if(buttonState == HIGH){
x_val = analogRead(x_pot); // reads the value of the potentiometer (value between 0 and 1023)
y_val = analogRead(y_pot); // reads the value of the potentiometer (value between 0 and 1023)
x_val = map(x_val, 350,500 , 0, 179); // scale it to use it with the servo (value between 0 and 180)
y_val = map(y_val, 350, 500, 0, 179); // scale it to use it with the servo (value between 0 and 180)
}
else if(buttonState == LOW)
{
x_val = analogRead(x_joy); // reads the value of the potentiometer (value between 0 and 1023)
y_val = analogRead(y_joy); // reads the value of the potentiometer (value between 0 and 1023)
x_val = map(x_val, 30,140 , 0, 179); // scale it to use it with the servo (value between 0 and 180)
y_val = map(y_val, 30, 140, 0, 179); // scale it to use it with the servo (value between 0 and 180)
}
//x_val = map(x_val, 30,60 , 0, 179); // scale it to use it with the servo (value between 0 and 180)
aileron.write(x_val); // sets the servo position according to the scaled value
//aileron_right.write(x_val); // sets the servo position according to the scaled value
// waits for the servo to get there

// y_val = map(y_val, 30, 70, 0, 179); // scale it to use it with the servo (value between 0 and 180)
pitch.write(y_val); // sets the servo position according to the scaled value
//delay(15); // waits for the servo to get there

/* x_val = analogRead(z_pot); // reads the value of the potentiometer (value between 0 and 1023)
z_val = map(z_val, 300, 800, 0, 179); // scale it to use it with the servo (value between 0 and 180)
rudder.write(z_val); // sets the servo position according to the scaled value
*/

// delay_val = analogRead(delay_pot); // reads the value of the potentiometer (value between 0 and 1023)
// delay_display = map(delay_pot, 0, 1023, 0 ,100); // scale it to use it with the servo (value between 0 and 180)

delay(15);
SoftwareServo::refresh();
// Print a message to the LCD.

/*
x_display = map(x_val, 0, 179, 0, 100);
y_display = map(y_val, 0, 179, 0 ,100);
lcd.clear();
if( x_display == 50 ){
lcd.setCursor(0,0);
lcd.clear();
lcd.print("Roll:");
lcd.print(x_display-50);
lcd.print("% neutral"); }
else if( x_display >50){
lcd.setCursor(0,0);
//lcd.print("Pitch: 40%");
//lcd.setCursor(0,1);
//lcd.print("Yaw: 40%");
//delay(2000);
// lcd.clear();
lcd.print("Roll:");
lcd.print(x_display-50);
lcd.print("% left");

}
else {
lcd.setCursor(0,0);
//lcd.print("Pitch: 40%");
//lcd.setCursor(0,1);
//lcd.print("Yaw: 40%");
//delay(2000);
lcd.print("Roll:");
lcd.print(50-x_display);
lcd.print("% right"); }

if( y_display == 50 ){

lcd.setCursor(0,1);
lcd.print("Pitch:");
lcd.print(y_display);
lcd.print("% neutral");

}
if(y_display >50){

lcd.setCursor(0,1);
lcd.print("Pitch:");
lcd.print(y_display-50);
lcd.print("% down");

}
else {

lcd.setCursor(0,1);
lcd.print("Pitch:");
lcd.print(50-y_display);
lcd.print("% up");

}
*/
}

basically I'm not using the LiquidCrystal.h, its just a additional thing. in which part of my program do you insert the code?

thks

in which part of my program do you insert the code?

Anywhere you need a filtered value.
You'll need a separate variable "filtered" for each value that you want to filter.

You might be better off not using the "softwareservo" library, and just use the standard "Servo" libray - it doesn't need a "refresh" and is possibly a little more accurate.

Please use the Code (#) button when posting code.

I see I see, thanks very much :slight_smile:

But I think I know what is the problem that cause the "noise". Basically I'm using a accelerometer to control the servo, the output of the accelerometer is not constant (eg. 350, 354, 348), and this might be the reason that cause the servo to be shaky. Do you have any way to make average out the accelerometer signal or PWM output to make it a constant (eg. [350 + 354 + 348] / 3 = 350.67) ?

I have an accelerometer that runs on 3.3v. The voltage regulator I was using was generating a very small amount of noise. So small that I needed to use an oscilloscope to see it. But the noise in the power supply was causing noticable noise in the reading from the accelerometer. flitering the power with a capacitor fixed the issue

Hi gradbert, you mean put the 0.1 uF capacitor between the 3.3V terminal & gnd?

Do you have any way to make average out the accelerometer signal

I already posted one - just substitute your accelerometer readings for the analogue readings in the example I gave in post #2.
Or if you prefer, substitute the PPM values for the servo.

Thanks AWOL, the program worked almost perfect, the x-axis & y-axis servo no longer 'jerk'. However, there's another problem.

When I turn the accelerometer on the x-axis, the servos for x-axis & y-axis move together. Similarly, when I turn the accelerometer on the y-axis, the servos for x-axis & y-axis move together also.

#include <LiquidCrystal.h>
#include <SoftwareServo.h> 


SoftwareServo rudder;  // 

create servo object to control 

a servo 
SoftwareServo aileron; 

 // create servo object to 

control a servo 
SoftwareServo 

pitch;  // create servo object 

to control a servo 
//============================

==============================

==============================

======
//============================

=========Accelerometer========

==============================

======
int x_pot = 0;  // 

analog pin used to connect the 

potentiometer
int x_val;    // 

variable to read the value 

from the analog pin 
int 

x_display;    // variable to 

read the value from the analog 

pin 

int y_pot = 1;  // analog 

pin used to connect the 

potentiometer
int y_val;    // 

variable to read the value 

from the analog pin 
int 

y_display;    // variable to 

read the value from the analog 

pin 
//============================

==============================

==============================

===========
//============================

=========Joystick=============

==============================

============
int x_joy = 2;  // 

analog pin used to connect the 

potentiometer
int z_val;    // 

variable to read the value 

from the analog pin 
int 

z_display;    // variable to 

read the value from the analog 

pin 

int y_joy = 3;
//============================

==============================

==============================

==========
//============================

=======Switch=================

==============================

=
int buttonPin = 7; 
int 

buttonState =0;

// 

LiquidCrystal display with:
// 

rs on pin 6
// rw on pin 7
// 

enable on pin 8
// d4, d5, d6, 

d7 on pins 2, 3, 4, 5
LiquidCrystal lcd(6, 7, 8, 2, 

3, 4, 5);
//============================

==============================

==============================

===
//============================

Simple Averaging 

Filter========================

================
const int 

numReadings = 10;

int readings

[numReadings];      // the 

readings from the analog input
int index = 0;                 

 // the index of the current 

reading
int total = 0;          

        // the running total
int average = 0;               

 // the average

//============================

==============================

==============================

====



int filter(int num) {
  // 

subtract the last reading:
  

total= total - readings

[index];         
  // read 

from the sensor:  
  readings

[index] = num; 
  // add the 

reading to the total:
  total= 

total + readings[index];       
  // advance to the next 

position in the array:  
  

index = index + 1;             

       

  // if we're at the 

end of the array...
  if (index 

>= numReadings)              
  

  // ...wrap around to the 

beginning: 
    index = 0;      

                     

  // 

calculate the average:
  

average = total / numReadings; 
 
  return average;
}
















void setup

()
{ 
  // initialize the 

pushbutton pin as an input:
  

pinMode(buttonPin, INPUT);    
 

 //rudder.attach(12);  // 

attaches the servo on pin 9 to 

the servo object
  

aileron.attach(11);  // 

attaches the servo on pin 9 to 

the servo object
  

pitch.attach(10);  // attaches 

the servo on pin 9 to the 

servo object
 //lcd.clear();
 

//lcd.print("Ngee Ann ");
  

//lcd.setCursor(0,1); 
  

//lcd.print("Polytechic");
 // 

delay(5000);
 /* lcd.clear();
  

lcd.print("Flight Simulator");
 

 lcd.setCursor(4,1); 
  

lcd.print("Ver 3.0");
  delay

(2000);
  lcd.clear();
*/
 for 

(int thisReading = 0; 

thisReading < numReadings; 

thisReading++)
    readings

[thisReading] = 0;  
}

 
void 

loop() 
{ 
  buttonState = 

digitalRead(buttonPin);
  if

(buttonState == HIGH){
  x_val 

= analogRead(x_pot);           

 // reads the value of the 

potentiometer (value between 0 

and 1023) 
  y_val = 

analogRead(y_pot);            

// reads the value of the 

potentiometer (value between 0 

and 1023) 
  x_val = filter

(x_val);
  y_val = filter

(y_val);
  x_val = map(x_val, 

350,500 , 0, 179);     // 

scale it to use it with the 

servo (value between 0 and 

180) 
  y_val = map(y_val, 350, 

500, 0, 179);     // scale it 

to use it with the servo 

(value between 0 and 180)  
  }
 

 else if(buttonState == LOW)
  

{
  x_val = analogRead(x_joy);  

          // reads the value 

of the potentiometer (value 

between 0 and 1023) 
  y_val = 

analogRead(y_joy);            

// reads the value of the 

potentiometer (value between 0 

and 1023)
  x_val = filter

(x_val);
  y_val = filter

(y_val);
  x_val = map(x_val, 

30,140 , 0, 179);     // scale 

it to use it with the servo 

(value between 0 and 180) 
  

y_val = map(y_val, 30, 140, 0, 

179);     // scale it to use 

it with the servo (value 

between 0 and 180)  
  } 
  

//x_val = map(x_val, 30,60 , 

0, 179);     // scale it to 

use it with the servo (value 

between 0 and 180) 
  

aileron.write(x_val);          

        // sets the servo 

position according to the 

scaled value 
  

//aileron_right.write(x_val);  

                // sets the 

servo position according to 

the scaled value 
      // 

waits for the servo to get 

there 
 
  
 // y_val = map

(y_val, 30, 70, 0, 179);     

// scale it to use it with the 

servo (value between 0 and 

180)  
  pitch.write(y_val);    

              // sets the 

servo position according to 

the scaled value 
  //delay

(15);     // waits for the 

servo to get there  
  
/*  

x_val = analogRead(z_pot);     

       // reads the value of 

the potentiometer (value 

between 0 and 1023) 
  z_val = 

map(z_val, 300, 800, 0, 179);  

   // scale it to use it with 

the servo (value between 0 and 

180)  
  rudder.write(z_val);   

               // sets the 

servo position according to 

the scaled value 
  */
  
 // 

delay_val = analogRead

(delay_pot);    // reads the 

value of the potentiometer 

(value between 0 and 1023) 
 // 

delay_display = map(delay_pot, 

0, 1023, 0 ,100);  // scale it 

to use it with the servo 

(value between 0 and 180) 
  
  

delay(15);
  

SoftwareServo::refresh();
  // 

Print a message to the LCD.
 
  

/*
  x_display = map(x_val, 0, 

179, 0, 100);
  y_display = 

map(y_val, 0, 179, 0 ,100);
  

lcd.clear();
   if( x_display 

== 50  ){
  lcd.setCursor(0,0);
 

 lcd.clear();
  lcd.print

("Roll:");
  lcd.print

(x_display-50);
  lcd.print("% 

neutral"); }
 else if( 

x_display >50){
  

lcd.setCursor(0,0);
  

//lcd.print("Pitch: 40%");
  

//lcd.setCursor(0,1);
  

//lcd.print("Yaw: 40%");
  

//delay(2000);
 // lcd.clear();
 

 lcd.print("Roll:");
  

lcd.print(x_display-50);
  

lcd.print("% left");
 
   
  }
  

else {
   lcd.setCursor(0,0);
  

//lcd.print("Pitch: 40%");
  

//lcd.setCursor(0,1);
  

//lcd.print("Yaw: 40%");
  

//delay(2000);
  lcd.print

("Roll:");
  lcd.print(50-

x_display);
  lcd.print("% 

right");  }
  
  if( y_display 

== 50  ){
  
  lcd.setCursor

(0,1);
  lcd.print("Pitch:");
  

lcd.print(y_display);
  

lcd.print("% neutral");
  
  }  
 

 if(y_display >50){
    
  

lcd.setCursor(0,1);
  

lcd.print("Pitch:");
  

lcd.print(y_display-50);
  

lcd.print("% down");
  
  }
  

else {
  
  lcd.setCursor(0,1);
  

lcd.print("Pitch:");
  

lcd.print(50-y_display);
  

lcd.print("% up");
  
  }
  */  
}

What's the problem? I don't understand.