0
Offline
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« on: October 29, 2009, 05:55:15 am » |
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
Online
Brattain Member
Karma: 143
Posts: 19380
I don't think you connected the grounds, Dave.
|
 |
« Reply #1 on: October 29, 2009, 06:13:49 am » |
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);
|
|
|
|
« 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.
|
|
|
|
Oxford (England)
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #2 on: October 29, 2009, 05:53:28 pm » |
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
Online
Brattain Member
Karma: 143
Posts: 19380
I don't think you connected the grounds, Dave.
|
 |
« Reply #3 on: October 30, 2009, 02:21:23 am » |
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.
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« Reply #4 on: October 30, 2009, 09:08:27 pm » |
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
Online
Brattain Member
Karma: 143
Posts: 19380
I don't think you connected the grounds, Dave.
|
 |
« Reply #5 on: October 31, 2009, 11:11:49 am » |
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.
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« Reply #6 on: October 31, 2009, 07:55:49 pm » |
I see I see, thanks very much  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
Newbie
Karma: 0
Posts: 41
Arduino rocks
|
 |
« Reply #7 on: November 01, 2009, 01:54:10 am » |
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
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« Reply #8 on: November 01, 2009, 03:10:27 am » |
Hi gradbert, you mean put the 0.1 uF capacitor between the 3.3V terminal & gnd?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Online
Brattain Member
Karma: 143
Posts: 19380
I don't think you connected the grounds, Dave.
|
 |
« Reply #9 on: November 01, 2009, 06:23:33 am » |
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.
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« Reply #10 on: November 09, 2009, 04:02:02 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
|