I have a problem very similar to this thread:
http://arduino.cc/forum/index.php/topic,21215.0.html
My project is a simple "elevator" that goes up a specified distance if a button is pressed, or down a specified distance if another button is pressed. It knows when it's reached the top or bottom, based on what the PING))) sensor tells Arduino.
The PING))) sensor is continually read. Depending on the distance to an object it returns, a motor runs forward or backwards (or stops it, or keeps it stopped).
The problem is the output from the PING))) sensor. As the motor runs and moves the
car away from the sensor, the distance to the car that the sensor reports varies wildly. The
centimeters as measured by PING))) might look like this:
3, 3, 3, 1, 3, 3, 4, 4, 4, 0, 1, 4, 4, 4, 1, 4, 4, 4, 5, 5,5,5, 5, 1, 5, 5, 5, 1, 1, 1, 5 etc.
I am guessing that the introduction of the motor to the circuit is causing some interference with the PING. Without the motor, if I just move the "elevator car" up and down with my hands, the PING sensor always gives the right values, without the variations shown above.
I took the advice from the thread above about using a capacitor (I used 0.1uF) across the terminals of the motor, and it didn't solve the problem. The motor has a separate 5V power supply as shown in the Fritzing diagram.
This is the first real project I've tried with Arduino - I have very little experience with electronics, so I am at a loss for how to troubleshoot the issue. I did the tutorial booklets and studied the Arduino Cookbook, and am at a point where I can't continue.
Here is the Fritzing diagram (the .fzz is also attached if this doesn't show up well):
The H-bridge chip is L293 (SN754410NE).
The power supply in the top left is SparkFun's 5V breadboard power supply.
Code:
/*
This is a project that started with the H-Bridge sketch from Arduino Cookbook page 283 and
the PING sensor tutorial at http://www.arduino.cc/en/Tutorial/Ping. Also has some elements of the basic "getting input from a button" Arduino tutorial.
There is a PING sensor that constantly locates an "elevator car" on rails. When an "Up" button
is pressed, the motor runs, acting as a winch, to lift the car. When the "Down" button is pressed, the motor runs the other direction.
The program below defines three "floors", with the ground floor position at 3 cm, and each "floor" being 6 cm high.
Pressing an Up button will add 6cm to the destination distance amount, and the motor will run until it reaches that position, and stop. Pressing a down button, when the car is not at the "ground" level, will run the motor the other way to allow the car to move down.
The loop() function will get the distance from the sensor to the elevator car
and control the motor to move the car in the right direction to get to the
distance stored in the variable called destinationPosition.
*/
//up and down tact buttons
int btnDown = 2;
int btnUp = 3;
//H-Bridge pins
const int hBridgeInputPin2 = 4; //h-bridge input pin 2
const int hBridgeInputPin1 = 5; //h-bridge input pin 1
const int hBridgeEnablePin = 6; //h-bridge enable pin
//The pin number of the PING)) sensor's output.
const int pingPin = 7;
const int groundFloorPositionCm = 3; //bottom of first floor is 3 cm from sensor
const int topFloorPositionCm = 21; //bottom of the third floor is at 21 cm from sensor
const int floorHeightCm = 6; //a "floor" is 6 cm high. This allows 3 floors betw 3 and 21 cms.
//is the car going up? if so, this is set to true. If going down, it's set to false.
boolean goingUp = false;
//this is the current destination, in cms from the sensor
//the motor will run in the correct direction to reach this position, then it will stop.
int destinationPosition = -1;
void setup()
{
//set up serial communication to receive debugging information
Serial.begin(9600);
//set up pins for the h-bridge
pinMode(hBridgeInputPin1, OUTPUT);
pinMode(hBridgeInputPin2, OUTPUT);
digitalWrite(hBridgeInputPin1, LOW);
digitalWrite(hBridgeInputPin2, HIGH);
//up and down button pins are used for input
pinMode(btnUp, INPUT);
pinMode(btnDown, INPUT);
//set the initial destination to be the first floor by default. When the loop() function starts running,
//it will move the car to the initial position if it's not already there.
InitializeElevatorPosition();
}
void loop()
{
ReadButtons();
ControlMotor();
}
void ReadButtons()
{
int curDistance = GetCurrentCarPositionCms();
//was the Up button pressed? If the car is stopped, adjust the destination distance, and run the motor to go up.
if (digitalRead(btnUp) == LOW)
{
if (curDistance == destinationPosition && curDistance < topFloorPositionCm)
{
destinationPosition += floorHeightCm;
goingUp = true;
}
Serial.println("**** button up");
return;
}
//was the Down button pressed? If the car is stopped, reduce the destination distance and run the motor
if (digitalRead(btnDown) == LOW)
{
if (curDistance == destinationPosition && curDistance > groundFloorPositionCm)
{
destinationPosition -= floorHeightCm;
goingUp = false;
}
Serial.println("**** button down");
return;
}
}
//when the program starts, move it to the "ground" floor
void InitializeElevatorPosition()
{
destinationPosition = groundFloorPositionCm;
}
//using the PING))), get the number of centimeters from the sensor
//to the bottom of the elevator car.
int GetCurrentCarPositionCms()
{
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return MicrosecondsToCentimeters(duration);
}
// Runs motor, if necessary, in the right direction to reach the
// current destination. Stops motor (or keeps motor stopped) if at the destination position
void ControlMotor()
{
int cmsDistanceFromPing = GetCurrentCarPositionCms();
Serial.print(cmsDistanceFromPing);
Serial.println();
//we're in the position we want - stop the motor, or leave it stopped.
if (cmsDistanceFromPing == destinationPosition)
{
analogWrite(hBridgeEnablePin, 0);
return;
}
if (cmsDistanceFromPing > destinationPosition)
{
//destination is below the current position - run the motor clockwise to lower the car
digitalWrite(hBridgeInputPin1, HIGH);
digitalWrite(hBridgeInputPin2, LOW);
}
else
{
//run motor clockwise - lower the car
digitalWrite(hBridgeInputPin1, LOW);
digitalWrite(hBridgeInputPin2, HIGH);
}
//make sure the motor is running
//use the map() function to control the speed of the motor (between 0 and 255)
analogWrite(hBridgeEnablePin, 255);
}
long MicrosecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
//http://www.arduino.cc/en/Tutorial/Ping
return microseconds / 29 / 2;
}
Any ideas are welcome!
Thanks.
Don
Elevator (post for help).fzz (15.6 KB)