Pages: [1]   Go Down
Author Topic: NOISE  (Read 880 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 [glow]there's some noise either internal or external, that makes the servo jerk[/glow] when the accelerometer is in rest, any good way to recommend me in [glow]removing/filtering the noise[/glow]?

Can show a diagram if possible?

Thanks in advance!
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26485
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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:
Code:
int filtered = 0;
const int FILTER_CONST = 4;
...
...

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

« Last Edit: October 29, 2009, 06:20:37 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Oxford (England)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26485
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: October 30, 2009, 02:42:20 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi AWOL, below is [glow]your code[/glow]:

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

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

[glow]And my program is[/glow]:
#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
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26485
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I see I see, thanks very much smiley

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) ?  
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26485
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
#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.
Logged

Pages: [1]   Go Up
Jump to: