0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« on: January 21, 2011, 01:11:04 am » |
Hello everyone, I'm hoping to get some programming help here for my little project. I'm trying to gain experience with the code and the arduino, so please bear with me. What I'm trying to accomplish is to have my accelerometer detect movement and then have my stepper motor move accordingly (the bigger the acceleration, the bigger the stepper motor movement). Also, if the accelerometer is experiencing a constant G, then the stepper steps the appropriate number of steps, and holds that position. When there is no acceleration, the stepper motor returns to the original position it started. Hopefully this is clear  The problem that I am experiencing is erattic motor behaviour. It seems like the motor doesn't reliably return to the starting position. Any suggestions would be great! Thanks! Without further adieu, here is the code I have so far: //Easydriver pins int dirPin = 3; int stepperPin = 12; //Accelerometer pins (analog) const int pinx = 1 ; const int piny = 2 ; const int pinz = 3 ; const int SLP = 9; //variables to store accelerometer output and keep track of stepper position int valx = 0; int valy = 0; int valz = 0; int last = 0; int current = 0; int difference = 0; //setup void setup() { Serial.begin(9600); pinMode(SLP, OUTPUT); pinMode(dirPin, OUTPUT); pinMode(stepperPin, OUTPUT); } //Function for instructing the Easydriver void step(boolean dir,int steps){ digitalWrite(dirPin,dir); //give Easydriver direction for stepper to move delay(50); for(int i=0;i<steps;i++){ //loop through the number of steps that the stepper motor must complete digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1000); } } //Main code body void loop(){ digitalWrite(SLP, HIGH); //Make sure the accelerometer is "awake" //Read the values from the accelerometer and assign them to the variables. For this simple program, only the y value will be used for now. valx = analogRead(pinx); valy = analogRead(piny); valz = analogRead(pinz); if (last == 0) { //For the first time through the loop, set the "last" value to y input from the accelerometer (multiplied by 5 so stepper motor moves more) last = valy*5; } current = valy*5; //Set the "current" value to the y value (multiplied by 5 so stepper motor moves more) difference = last - current; //Calculate the difference between the last known acceleration and the current acceleration if (difference > 0) { //If the difference is positive, then it will tell the Easydrive to step the motor counter-clockwise step(false, difference); } if (difference < 0) { //If the difference is a negative number, then it will tell the Easydriver to step the motor clockwise difference = abs(difference); step(true, difference); } last = current; //Set the last known to acceleration to the current one so it can be compared to the next reading delay(50); }
|
|
|
|
« Last Edit: January 21, 2011, 01:12:28 am by doublec4 »
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35478
Seattle, WA USA
|
 |
« Reply #1 on: January 21, 2011, 08:49:28 am » |
Also, if the accelerometer is experiencing a constant G, then the stepper steps the appropriate number of steps, and holds that position. When there is no acceleration, the stepper motor returns to the original position it started. Hopefully this is clear I suspect you have a fundamental misunderstanding of accelerometers. You seem to be mistaking motion and acceleration. Acceleration is the rate of change of velocity, while velocity is a vector that combines position and direction, and changes when either the position changes or the direction changes. The problem that I am experiencing is erattic motor behaviour. It seems like the motor doesn't reliably return to the starting position. How can it, with all those delays? You are missing loads of data from the accelerometer, which you are not properly integrating, anyway.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #2 on: January 21, 2011, 02:02:58 pm » |
Hi Paul,
thank you for your response. I do know the difference between acceleration and velocity (acceleration being the derivative of velocity with respect to time). When I said "motion" I was referring to acceleration or tilt (accelerometer should detect gravity in whatever axis is experiencing it?).
So technically, if I were to quickly strike the accelerometer, the change in velocity (acceleration) should produce a stepping sequence of lets say, 200 steps for example. I understand that the arduino is busy stepping the motor and will not read any info from the accelerometer during this process. Once the stepping process is done, the next accelerometer reading should be the "baseline" again because there is no acceleration. Therefore, it should step backwards 200 steps to the starting position?
The next condition would be tilting the accelerometer. By tilting it, the y axis should feel gravity, should it not? Then, it should move a prescribed amount. If it is still tilted the same amount when the stepping sequence is done, it should remain in that position. Once it is set back down on the table, and the y axis does not feel gravity, it should go back to the home position?
I hope this is more clear? I would really like to get this working.
Thank you again.
Chris
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35478
Seattle, WA USA
|
 |
« Reply #3 on: January 21, 2011, 05:16:37 pm » |
Forget, for the moment about actually moving the stepper motor. Just print to the serial port the value read from the accelerometer (valy), the value that reading is mapped to (valy*5), along with current, last and difference.
With the accelerometer sitting still, does difference show a nice steady 0? When you move it, does difference return quickly to 0?
Or, are the readings all over the place? Do they tend to return quickly to 0, or do they oscillate all over the place?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #4 on: January 21, 2011, 05:53:46 pm » |
Hi Paul,
The values oscillate while the accelerometer is sitting still. I realize this will cause a certain percent error when trying to get the stepper motor to return back to the original position after it is done accelerating. However, I am experiencing the difference of more than a few steps (even by the multiple of 5). Sometimes it appears to have a mind of its own, and not even travel in the right direction.
I took a step back and revisited some simple stepper motor program, and without the accelerometer, the results are similar. This program that I will add next, should only have the stepper motor moving in one direction. However, it sometimes travels in reverse? I'm somewhat frustrated and not sure what is going on. (I also repinned the board, so the pins are not the same as the first program I posted).
int dirPin = 3; int stepperPin = 2; int SLEEP = 8; int MS1 = 7; int MS2 = 9;
void setup() { pinMode(dirPin, OUTPUT); pinMode(stepperPin, OUTPUT); pinMode(MS1, OUTPUT); pinMode(MS2, OUTPUT); pinMode(SLEEP, OUTPUT); }
void step(boolean dir,int steps){
digitalWrite(SLEEP, HIGH); digitalWrite(MS1, LOW); digitalWrite(MS2, LOW);
digitalWrite(dirPin,dir); delay(50);
for(int i=0;i<steps;i++){ digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1000); } }
void loop(){ step(true,1600); delay(1000);
}
Technically, the motor should just keep going around in circles in one direction smoothly. However, it is jerky, sometimes travels in reverse, or changes directions in the middle of a stepping sequence. Not sure what could be wrong?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35478
Seattle, WA USA
|
 |
« Reply #5 on: January 21, 2011, 06:50:39 pm » |
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #6 on: January 21, 2011, 07:03:00 pm » |
I took a look through the stepper library, however isn't that for using the PWM option for Arduino?
I'm using the Easydriver 4.2/4.3 so that I wouldn't have to use the Arduino PWM to control the stepper. I should just have to pass it the direction, and number of steps with the proper sequencing.
I'm noticing that the stepper motor doesn't like it if I try to change the speed. The 1000 microsecond delay is pretty much all it will work with.
Do you happen to know how to properly adjust the current setting on the Easydriver? I have moved it around a little, but don't really notice a difference in my stepper performance or smoothness.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35478
Seattle, WA USA
|
 |
« Reply #7 on: January 21, 2011, 08:06:58 pm » |
I took a look through the stepper library, however isn't that for using the PWM option for Arduino? No. It's for driving stepper motors. I'm noticing that the stepper motor doesn't like it if I try to change the speed. The 1000 microsecond delay is pretty much all it will work with. Speed is most definitely a function of current, and, to a lesser extent, voltage. Given adequate current, the motors will step faster. Do you happen to know how to properly adjust the current setting on the Easydriver? There is a potentiometer that adjusts the amount of current drawn. Of course, this presupposes that there is adequate current available to be drawn. In your situation, this appears to not necessarily be the case. How are you powering the stepper motors?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #8 on: January 21, 2011, 09:44:26 pm » |
Well I figured out part of my problem. I had the stepper motor wired improperly. It is a cheap stepper from an electronics store to which I could not find the data sheet anywhere online. I did find a picture of one wired, so I wired mine the same. The assumption that someone else wired it properly was a poor decision on my part. I decided to ohm out the motor tonight and I now have it wired correctly, which fixed the erratic behaviour. My basic programs run properly, and the stepper has much more torque and holding torque now. I'm powering the stepper and the easy driver with a 12V DC supply which has a 5.8A rating. It is plenty for this application. Now that the stepper is wired correctly, I adjusted the potentiometer so that the motor runs smoothly. This may be a silly question, but how can I go about measuring the actual current when I adjust it? Should I just use my multimeter and put it inline with one of the wires for the stepper motor? Would that be the correct process? Tomorrow I will play around more with the program and see where I can make improvements such that it is more reliable. Thank you for all of your help so far. I truly appreciate it. I will post the new code tomorrow 
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35478
Seattle, WA USA
|
 |
« Reply #9 on: January 21, 2011, 09:57:12 pm » |
I had the stepper motor wired improperly. Hard to get the software working until the hardware does. Glad you got the hardware sorted out.
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #10 on: January 22, 2011, 01:50:29 pm » |
suggest you change the stepper code to include a small delay for(int i=0;i<steps;i++){ //loop through the number of steps that the stepper motor must complete digitalWrite(stepperPin, LOW); [glow]delayMicroseconds(500);[/glow] digitalWrite(stepperPin, HIGH); delayMicroseconds(1000); } and rather than sleep (to disable the stepper) why not use the Enable input instead?
|
|
|
|
« Last Edit: January 22, 2011, 01:51:10 pm by mmcp42 »
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #11 on: January 22, 2011, 03:36:44 pm » |
I haven't tried adding that delay in there yet with it being wired properly. When it was wired improperly, it didn't like the delay, however that doesn't mean much considering the way it was wired. I can give that a try.
As for the "enable," I see the pin for it, however, what does it do? If I don't send voltage to it, the board already accepts input. If I send it a voltage, is it just for redundancy?
Thanks!
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #12 on: January 22, 2011, 11:11:43 pm » |
I finally got it to do what I had originally intended. The delays could use some work to speed up the process, and I could filter out some noise a little better, but here is the code I have:
//Arduino Uno, Easydriver, Stepper Motor, Accelerometer Control //doublec4 2011 //Easydriver pins
int dirPin = 3; int stepperPin = 2; int SLEEP = 8; int MS1 = 7; int MS2 = 9;
//Accelerometer pins (analog)
const int pinx = 1 ; const int piny = 2 ; const int pinz = 3 ; const int SLP = 10;
//variables to store accelerometer output and keep track of stepper position int valx = 0; int valy = 0; int valz = 0;
int calib = 0; int position = 0;
int count = 0;
//setup
void setup() { Serial.begin(9600);
pinMode(SLP, OUTPUT); pinMode(dirPin, OUTPUT); pinMode(stepperPin, OUTPUT); pinMode(MS1, OUTPUT); pinMode(MS2, OUTPUT); pinMode(SLEEP, OUTPUT); } void loop(){ digitalWrite(SLP, HIGH); //Make sure the accelerometer is "awake" digitalWrite(SLEEP, HIGH); digitalWrite(MS1, LOW); digitalWrite(MS2, LOW); valy = analogRead(piny); if (count > 2) {
if (calib == 0) { //For the first time through the loop, set the "calibration" value to y input from the accelerometer calib = 300; position = calib; } //while(valy > (position + 5) || valy < (position - 5)) { //digitalWrite(dirPin,HIGH);
//digitalWrite(stepperPin, LOW); //digitalWrite(stepperPin, HIGH); //delayMicroseconds(1500); //} Serial.print("Calibration: "); Serial.print(calib); Serial.print(" Position: "); Serial.print(position); Serial.print(" Valy: "); Serial.println(valy); if ((valy > (calib + 10)) || (valy < (calib - 10))) { if ((valy - position) > 0) { //If the G reading (positive direction) is greater than the current position, move up towards that position digitalWrite(dirPin,HIGH);
digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1200); position++; } if (((calib - valy + calib) - position) > 0) { //If the G reading (negative direction) is greater than the current position, move up towards that position digitalWrite(dirPin,HIGH);
digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1200); position++; } if (((valy - position) < 0) && (position > calib) && (valy > calib)) { //If the G reading (positive direction) is less than the current position, move down towards that position digitalWrite(dirPin,LOW);
digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1200); position--; } if ((((calib - valy + calib) - position) < 0) && (position > calib) && (valy < calib)) { //If the G reading (negative direction) is less than the current position, move down towards that position digitalWrite(dirPin,LOW);
digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1200); position--; } } if ((valy < (calib + 10)) && (valy > (calib - 10))) { if (position > calib){ digitalWrite(dirPin,LOW);
digitalWrite(stepperPin, LOW); digitalWrite(stepperPin, HIGH); delayMicroseconds(1200); position--; } } } count++; }
Basically, the stepper motor travels in one direction to a position related to a G force. The higher the G, the greater the position away. Right now only using the y axis. When no G is detected, the stepper returns to the original position.
Comments and critiques welcome. Not sure if I could have done this in a more elegant and robust way? I'd love to know! Thanks!
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #13 on: January 23, 2011, 01:07:28 pm » |
the difference between sleep and enable:
sleep sends the whole board to sleep - it takes a finite time to wake up enable (or rather NOT enable) is a signal that switches off the output stage
quick look at the data sheet will tell all
as it is a NOT input, by default it is enabled, you can disable by setting it HIGH
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« Reply #14 on: January 23, 2011, 01:19:05 pm » |
Sounds good. So technically, if I have nothing connected to the sleep pin, or the enable pin, it will always be on, and ready for input. Eliminating that amount of time to enable the board?
|
|
|
|
|
Logged
|
|
|
|
|
|