Go Down

Topic: adxl335 to control servo help with map (Read 7820 times) previous topic - next topic

nwgtr

Jul 22, 2010, 05:18 am Last Edit: Jul 22, 2010, 05:22 am by nwgtr Reason: 1
maybe someone could clearify this for me,  I'm trying to control servo with adxl335,  I read the datasheet but what is the range that I'm supposed to map?

there is a number in the datasheet showing ratiometric 270 to 330
I tried mapping it to 0-179 of the servo but it doesn't do anything
the sweeping sketch works,  I also tried hooking up the acclerometer and getting values with the adxl3XX sketch,  for x-axis it reads 414 to 630.  I tried mapping that and still doesn't work.

Do I have to do some sort of conversion or am I just doing something wrong cus right now I just want to be able to map the x-axis to the servo so I could tilt the accelerometer from one extreme to the other and the servo will rotate the range of 0-180.

I was using the code
val = map(val, 0, 1023, 0, 179);

but of course I change the value of the 0, and 1023 to the other values I posted above

PaulS

What you need to do is determine the range of values that you get from the accelerometer. Use the lower and upper limits as the from range (the 2nd and 3rd arguments) in the call to map. The to range (the 4th and 5th arguments) is the range of values that the servo can move to.

Quote
I also tried hooking up the acclerometer and getting values with the adxl3XX sketch,  for x-axis it reads 414 to 630.  I tried mapping that and still doesn't work.


Dang, I hate when that happens.

"still doesn't work" doesn't tell us anything, except that the code did not produce the results you wanted. It does NOT tell us what the results were that you wanted, or what the results were that you got.

You'll get more help if you provide those details.

You'll also get more help if you post all of your code, not just some snippet that you say you modified anyway.
The art of getting good answers lies in asking good questions.

GrooveFlotilla

#2
Jul 22, 2010, 12:26 pm Last Edit: Jul 22, 2010, 12:27 pm by GrooveFlotilla Reason: 1
Quote
there is a number in the datasheet showing ratiometric 270 to 330

...in millivolts per g
How are you powering the accelerometer?
What is your test method?
Mine would be to power it from 3.3V, so zero g would then give a reading of around 1650mV.
Work out your A/D scaling of about 5mV per count, so you should have a reading of about 338 for the x-axis on a horizontal surface.
Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.

nwgtr

I'm powering the adxl335 chip from the arduino 3.3v pin

First I used this code so that the adxl335 would output the values on the screen.
I rotated the x-axis shows 519 when I lay it flat on the table.  I rotate it 90 degrees to both extremes and got 414  and 630

The circuit:
analog 0: accelerometer self test
analog 1: z-axis
analog 2: y-axis
analog 3: x-axis
analog 4: ground
analog 5: vcc


*/

// these constants describe the pins. They won't change:
const int groundpin = 18;             // analog input pin 4 -- ground
const int powerpin = 19;              // analog input pin 5 -- voltage
const int xpin = 3;                   // x-axis of the accelerometer
const int ypin = 2;                   // y-axis
const int zpin = 1;                   // z-axis (only on 3-axis models)

void setup()
{
 // initialize the serial communications:
 Serial.begin(9600);
 
 // Provide ground and power by using the analog inputs as normal
 // digital pins.  This makes it possible to directly connect the
 // breakout board to the Arduino.  If you use the normal 5V and
 // GND pins on the Arduino, you can remove these lines.
 pinMode(groundpin, OUTPUT);
 pinMode(powerpin, OUTPUT);
 digitalWrite(groundpin, LOW);
 digitalWrite(powerpin, HIGH);
}

void loop()
{
 // print the sensor values:
 Serial.print(analogRead(xpin));
 // print a tab between values:
 Serial.print("\t");
 Serial.print(analogRead(ypin));
 // print a tab between values:
 Serial.print("\t");
 Serial.print(analogRead(zpin));
 Serial.println();
 // delay before next reading:
 delay(100);

nwgtr

#4
Jul 23, 2010, 02:53 am Last Edit: Jul 23, 2010, 02:57 am by nwgtr Reason: 1
I then modified this code to try and map the values to the servo

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer (i used adxl335)
int val;    // variable to read the value from the analog pin

void setup()
{
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop()
{
 val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)

// here is where i put my values to map to the servo

val = map(val, 414, 519, 0, 179);     // scale it to use it with the servo
(value between 0 and 180)
 myservo.write(val);                  // sets the servo position according to the scaled value
 delay(15);                           // waits for the servo to get there
}


I tired different values and nothing works,  I tried using the ratiometric values given in the datasheet.

I'm just not sure what are those values that was outputted when I ran the first program.  I thought I could just plug those in and map it.

I checked the datasheet and it didn't show any calculations or any range that the x, y, z axis's output.  except that ratiometric value which I tried mapping.


I mapped val = map(val, 414, 519, 0, 179);  

I rotated the adxl335 on the x-axis which is the only axis I'm testing to keep things simple. The servo doesn't rotate.

That is the problem I'm having,  I just need to be able to figure out how to map the values so that when I rotate the adxl chip, it would cause the servo to move.

PaulS

You said that the range of values you got was from 414 to 630, and that you got 519 when the accelerometer was laying flat on a table.

So, why are you mapping from 414 to only 519? Your map from range should be from 414 to 630.

You can use Serial.begin() in setup, and Serial.print() and/or Serial.println() in loop() to see what value was read from the accelerometer and what value is returned by the map function.

I notice though, that the code that prints the values has a lot more pins defined and has more pinMode statements.

Why would you switch pins between scripts? What happened to powering and ground the accelerometer?
The art of getting good answers lies in asking good questions.

nwgtr

#6
Jul 23, 2010, 05:31 am Last Edit: Jul 23, 2010, 05:38 am by nwgtr Reason: 1
Quote
You said that the range of values you got was from 414 to 630, and that you got 519 when the accelerometer was laying flat on a table.

So, why are you mapping from 414 to only 519? Your map from range should be from 414 to 630.

You can use Serial.begin() in setup, and Serial.print() and/or Serial.println() in loop() to see what value was read from the accelerometer and what value is returned by the map function.

I notice though, that the code that prints the values has a lot more pins defined and has more pinMode statements.

Why would you switch pins between scripts? What happened to powering and ground the accelerometer?  


sorry it was a typo. I mapped it between the min and max that I got which was 414 to 630 but even if it was only mapped between 414 to 519 I should still have gotten movement from the servo when I tilted the accelerometer.

Also I'm just using that code to test my servo and the adxl335 why does it matter what other useless code is on there?  as long as I don't use it or plug anything to those pins it won't affect anything.

instead of retyping what I tried do you actually know what the problem is or have a solution?   Or did you reply just to have more posts under your belt?   Maybe I misunderstood your intentions

I'll go test it some more and see,  I'm thinking my problem is due to the values that I map,  whatever the serial print shows is not the actual values that I have to map.

If I find a solution I'll post it here so it could help other people with this problem.

thanks anyways for contributing.

GrooveFlotilla

#7
Jul 23, 2010, 08:41 am Last Edit: Jul 23, 2010, 04:08 pm by GrooveFlotilla Reason: 1
Quote
The circuit:
analog 0: accelerometer self test


You realise that the self-test is an input to the accelerometer?
Have you set the pinMode correctly for pin 14 (analogue pin 0)?

I'm puzzled as to why you're getting a reading of 519 for a motionless, horizontal accelerometer.
Is your Arduino running off 3.3V too, or have you set the analogue reference to 3.3V also? (when posting, it is usually best to tell the world what sort of board you're running on and the conditions of your tests, otherwise we just have to guess stuff, which wastes time)

Quote
I checked the datasheet and it didn't show any calculations or any range that the x, y, z axis's output

http://www.analog.com/static/imported-files/data_sheets/ADXL335.pdf
Page 3/16, "Specifications", "Sensitivity at XOUT, YOUT, ZOUT 270 (min) 300 (typ) 330 (max) mV/g

Also, when posting code, can you please use the # button on the editor's toolbar to enclose your sketch.
Thanks.

Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.

PaulS

After looking at your last response, I see that one code is for reading and echoing the data obtained from the accelerometer, and that the other code is trying to move the servo using a potentiometer.

Fair enough that the pins and pin mode stuff will be different.

However, the map command does not constrain the values to be in the from range. So, if you are reading (and not printing, so you don't know) a value like 312 from the potentiometer, and mapping values in the range 414 to 519 to 0 to 179, then the 312 value will cause map to return a negative number.

Since the servo can't move to a negative value, it simply sits still.

You may not be thrilled with all the questions about what you are doing, but we are not there with you. We can't see what you are doing. Without you showing the code and circuit you are using, we can only guess at what is causing the problem. So, we ask questions to try to get you to provide more information, or to think.

If you'd prefer not to do that, that's fine.
The art of getting good answers lies in asking good questions.

nwgtr

#9
Jul 24, 2010, 05:29 am Last Edit: Jul 24, 2010, 05:35 am by nwgtr Reason: 1
PaulS,  I know at first it seems like you were just telling me to do what I've already done that's all but your last post was useful,  cus it explains what might be the cause.

I'm using Duemilanove and the accelerometer is ADXL335, servo is HS-485HB.

Quote
I'm puzzled as to why you're getting a reading of 519 for a motionless, horizontal accelerometer.
Is your Arduino running off 3.3V too, or have you set the analogue reference to 3.3V also?


I'm powering the adxl335 with the 3.3 volts from the arduino and the servo off the 5v, I also have a adafruit motor shield which doesn't really change anything since the servo's don't really need the motor shield to work.

I also donno why I'm getting 519 when it's horizontal,  maybe cus the analog reading is 0-1023  and 519 is near the middle?

Quote
You realise that the self-test is an input to the accelerometer?


But I don't really need to use the selftest if I'm controlling the servo with the accelerometer values.  
selftest is just used to test if the device is working properly and I already checked that in the first adxl## sample code which outputs the results serially.

Quote
However, the map command does not constrain the values to be in the from range. So, if you are reading (and not printing, so you don't know) a value like 312 from the potentiometer, and mapping values in the range 414 to 519 to 0 to 179, then the 312 value will cause map to return a negative number.

Since the servo can't move to a negative value, it simply sits still.


What do you mean by that Paul, I thought when I used the first code to get the range that I will be using from the accelerometer  which was between 414 to 630  I just map that range to the 0-179.

Are you saying that the range 414-630 that the first code outputted is not correct? I also tried mapping from 0-1023 which covers the whole range of analog output and the servo still didn't budge.

nwgtr

#10
Jul 24, 2010, 07:08 am Last Edit: Jul 24, 2010, 07:09 am by nwgtr Reason: 1
I got it working with this code:
Code: [Select]


#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = 3;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin
int val2;
int val3;

void setup()
{
Serial.begin(9600);
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop()
{
 val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)

Serial.println(val);
Serial.print("\t");
val = map(val, 269, 409, 0, 179);     // scale it to use it with the servo (value between 0 and 180)
Serial.println(val);
myservo.write(val);
delay(100);
}




I had to use the serial. print command to make sure I'm getting the correct values.

I double checked again before mapping and after mapping.  the values range is about 269 to 409.

Now i just have to add a few more lines of code to get the avg value so it's more stable

AWOL

#11
Jul 24, 2010, 10:33 am Last Edit: Jul 24, 2010, 10:55 am by AWOL Reason: 1
Quote
I also donno why I'm getting 519 when it's horizontal,  maybe cus the analog reading is 0-1023  and 519 is near the middle


Yes, 519 is very near the middle of the range, but the 0..1023 range represents a range of 0 to 5V, so mid-range is 2.5V, which is not what the 0g point of your accelerometer should be at if you're powering it from 3.3V (the maximum supply voltage for the device you're using).
It should be more like 338, as noted earlier.
However, if you were powering the accelerometer from 5V (and thereby potentially damaging it), then perhaps the 0g point would be at 2.5V

Have you checked your wiring?

PaulS

Quote
I got it working with this code:

I must say that I'm surprised, or that you have a different definition of working than I do.

This code is reading the value of a potentiometer, not an accelerometer. If the potentiometer is wired correctly, this code should result in analogRead returning values in the range 0 to 1023.

You then map these values using
Code: [Select]
val = map(val, 269, 409, 0, 179);
For values from 0 to 269, this will result in val containing a negative value. For values from 410 to 1023, val will contain values of 180 or more.

So, for a broad range of potentiometer movement, the map function will output a value that the servo can not move to. Unless it's not a normal 180 degree servo.

Quote
Now i just have to add a few more lines of code to get the avg value so it's more stable

I think you have more to do...
The art of getting good answers lies in asking good questions.

nwgtr

Quote
I must say that I'm surprised, or that you have a different definition of working than I do.

This code is reading the value of a potentiometer, not an accelerometer. If the potentiometer is wired correctly, this code should result in analogRead returning values in the range 0 to 1023.


I don't think you completely get what I'm doing still.  This sketch is from the arduino programmer as a demo,  potentiometer or accelerometer it's still analog,  I just didn't bother to rename the code till I finish my initial testing.  All I have to do is connect the x-axis of the accelerometer to that same pin and it will read the values.

I also used that adxl335 code to get the values with serial print which allows me to see what value range I'm using.  At steady state ( leaving the accelerometer flat on the table) I get 336,  tilt it on one side on an angle and right side on the same angle I get around 269 to 409  which is the range I'm planning to use.   I map that to 0-179 which is mainly the range of my servo.  Now if I power it up not touching the accelerometer  the servo is roughly at 90 degrees.

I tilt it one way, it will rotate the servo towards min or high depending on which way I tilt the accelerometer.

Well it's working to my standards because I know exactly what I'm trying to do and it did what I wanted to.

I have 2 servo's x and y axis being controlled by the accelerometer now, just working on smoothing the movement by taking averages.


Quote
For values from 0 to 269, this will result in val containing a negative value. For values from 410 to 1023, val will contain values of 180 or more.

So, for a broad range of potentiometer movement, the map function will output a value that the servo can not move to. Unless it's not a normal 180 degree servo.


Why would the pot or aka (accelerometer) output values higher than 409?  I mapped the min to high values between 269 and 409.   Which is the values that I tested and will never go past.


AWOL

Quote
I don't think you completely get what I'm doing still.

Probably true - we're not psychic.

Quote
I just didn't bother to rename the code

Well, if that just doesn't make me feel so special.

Quote
At steady state ( leaving the accelerometer flat on the table) I get 336

What caused the sudden shift from 519?
Do you have eccentric gravity?
Perhaps you were testing in an elevator.

Quote
Why would the pot or aka (accelerometer) output values higher than 409?

Well, you might tap it, drop it onto a hard surface, or swipe it.
Quote
Which is the values that I tested and will never go past.

Good luck.
Keep an eye on that capricious gravity though.

Go Up