using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using Servo_API;
namespace Accelerometer_Example
{
public class Program
{
// Define our accelerometer inputs
static AnalogInput accX;
static AnalogInput accY;
static AnalogInput accZ;
static Servo servoX;
static Servo servoY;
static ArrayList stackX;
static ArrayList stackY;
static int capacity = 5;
public static void Main()
{
// Create the Inputs
accX = new AnalogInput(Pins.GPIO_PIN_A0);
accY = new AnalogInput(Pins.GPIO_PIN_A1);
accZ = new AnalogInput(Pins.GPIO_PIN_A2);
servoX = new Servo(Pins.GPIO_PIN_D5);
servoY = new Servo(Pins.GPIO_PIN_D6);
stackX = new ArrayList();
stackY = new ArrayList();
servoY.inverted = true;
while (true)
{
Debug.Print("X:" + accX.Read().ToString() + " Y:" + accY.Read().ToString() + " Z:" + accZ.Read().ToString());
MoveAvgX(accX.Read());
MoveAvgY(accY.Read());
Thread.Sleep(10);
}
}
public static void MoveAvgX(int x)
{
stackX.Add(x);
if (stackX.Count > capacity) stackX.RemoveAt(0);
int avg = 0;
for (int i = 0; i < stackX.Count; i++)
{
avg += int.Parse(stackX[i].ToString());
}
avg = avg / stackX.Count;
servoX.Degree = servoX.map(avg, 400, 600, 0, 180);
}
public static void MoveAvgY(int y)
{
stackY.Add(y);
if (stackY.Count > capacity) stackY.RemoveAt(0);
int avg = 0;
for (int i = 0; i < stackY.Count; i++)
{
avg += int.Parse(stackY[i].ToString());
}
avg = avg / stackY.Count;
servoY.Degree = servoY.map(avg, 400, 600, 0, 180);
}
}
}
Servo Jitters
#1
Posted 04 March 2012 - 07:38 AM
#2
Posted 04 March 2012 - 02:23 PM
I think you were on the right track with the averaging.
I see that your main loop is reading the sensors approximately every 10ms, so the average is only over 50ms (20Hz).
My guess is that 50ms is not long enough to average out any shake in your hand. I just did a quick test seeing how many times I can hita key on the keyboard in 5 seconds, I managed 41 - so that's about 8Hz.
What happens if you keep the same period in the main loop (10ms), but up the averages to 20 to give 200ms (5Hz)?
Paul
#3
Posted 04 March 2012 - 06:15 PM
I've tried looking this up in other place on the web and I really have not found anything yet. I'm sure there is a solution I'm just wondering if I'm going about it completely wrong. Also if I use anything other then 10 ms to read the accelerometer I get a lot more spikes. The numbers jump all over +-50. 10 ms seems to keep it steady.
#4
Posted 04 March 2012 - 06:36 PM
You have not said anything about the construction of your circuit.
Is there anything else connected to the Netduino? (other shields, etc.)
If so, try without them in-case they are causing a problem.
Do you have any capacitors fitted to the power supply lines close to the sensor?
These would help get rid of any noise on the supply lines that could cause noise on the analogue outputs. The data sheet for the sensor will probably specify some combination of decoupling capacitors.
Are you powering the servos and the sensors from the same supply?
It may be that as the servo motors turn, the voltage is dropping slightly and the Netduino is measuring a slight dip on the analogue inputs because of this. Depending on the dynamics of the system, you can end up with an oscillator!
If you can, try powering the servos from their own battery supply. That way the motors will not add noise to the Netduino and sensor power supply.
Another thing to try is to use some potentiometers as analogue inputs instead of your sensor. Check if you still get shaky servos then. If you do, it is not a problem with the sensor.
Keep trying - Paul
#5
Posted 04 March 2012 - 06:43 PM
#6
Posted 04 March 2012 - 06:44 PM
I have not measured it, but IMHO you can speed up the code a little bit by replacing Parse() with cast:Still shaky but now extremely slow.
avg += (int)stackX[i];Also, you might consider changing avg type to long to avoid overflow and Queue instead of Stack.
What accelerometer do you use?
#7
Posted 05 March 2012 - 05:10 AM
I like your idea of separate power supply. You may have a point there. I'll try it. Basically I'mm just powering 2 micro servos via board power so there could be a surge. I'm a software guy not a hardware guy so I'll have to look up how to plug in some capacitors. Any ideas?
CW2,
Its an ADL335. The stack object is actually an Arraylist. Long won't matter due to a array capacity count of 10 an avg val * max val 0f 600 = 6000. I'll try your casting instead of parsing to make it faster.
Thanks for the ideas!
#8
Posted 05 March 2012 - 06:38 AM
-- H.L. Mencken, "What I Believe"
#10
Posted 05 March 2012 - 04:12 PM
Here is the sensor link...
http://www.adafruit.com/products/163
It takes me to a data sheet with the following image...

I'm not very intuitive in reading electronic symbol diagrams, but those resistors look built in to me. Looks like 4 capacitors needed? will ceramic 0.1uf do the trick?
#11
Posted 05 March 2012 - 07:39 PM
Yes you are correct - the resistors are actually part of the chip.
Are you using the breakout board shown at the link?

I am guessing that you are as that device would be a bugger to solder on its own!
If not then congratulations on the soldering skills, and yes you will have to add the four capacitors. The diagram does not show polarised capacitors (no + symbol) - so ceramic should be OK. They should be fitted near the device.
The breakout board has all the capacitors fitted already, so assuming that is what you are using, you don't need to add anything else. It also has a voltage regulator.
3Vo is the output from the on-board regulator, you could use it to drive the Aref input on the Netduino. Once the jitters are fixed, using the 3Vo to drive Aref would give a better range on the ADCs. (To use the Aref signal for the ADCs instead of the on board 3.3V, there is a setting to make in the Netduino - I can't remember what it is off hand.)
EDIT: sorry the regulator is actually 3.3V so it will not give an improvement in range. I read 3Vo as three volts not 3.3 Volts
A few questions that might help spot a problem with your setup:
What have you done with the test pin? The data sheet says to either leave it unconnected or to tie it to ground.
What voltage have you connected to Vin (3.3V or 5V)? I think 5V would be better, I am not sure that 3.3V will give enough voltage for the regulator to work correctly.
How long are the wires from the board back to the Netduino? If they are long, they will be susceptible to noise, and the chip may not be able to drive enough current into them.
Remember to enjoy yourself - it is a hobby after all
Regards - Paul
#12
Posted 05 March 2012 - 07:47 PM
I do nothing with the Test lead and the sensor is on top of a proto shield with 3 inch test leads using onboard 3.3v. You sure I won't damage the board with 5v?
And you are right... it is a hobby, one that is not supposed to pull my hair out. As a 40+ hour .Net developer, you'd think I would have chosen tennis. Hahaha
#13
Posted 05 March 2012 - 08:38 PM
Yep - the board already has the capacitors so you don't need to add any more.
3 inches is fine. (I was a little worried that you might have long leads of several feet so that the Netduino could be on the desk and the accelerometer in your hand.)
Yes, I'm sure 5V is OK, the web page says: "The VCC takes up to 5V in and regulates it to 3.3V with an output pin."
Sounds like the sensor end is almost perfect.
Do have a go at using separate supplies for the servos. My buggy project (that I get to spend about an hour a month on) rebooted every time the motors spun up until I used a separate supply for them!
Paul
#14
Posted 05 March 2012 - 08:46 PM
There's other ways to make it faster (don't push/pop from a list, instead use a plain array and cycle the index that you are using). However, your main problem is that you only have an accelerometer to measure the orientation of your setup, and accelerometers are jittery in itself - also, for an accelerometer gravity is indistinguishable from you accelerating your hand, so it's expected that your readings are off when you move your hand. What you'd need to do would be to couple the accelerometer with a gyro, and then combine the measurements e.g. complementary filtering - see this Presentation for example.
Stefan,
I'm sorry I did not see this post. I just ordered a sensor with Nine axis modules (three-axis gyro + three axis acceleration + tri-axial magnetic field)
I'll give it a go with that one. Thank you.
And Paul, thanks again for your insight as well.
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users











