Go Down

Topic: motor speed control (Read 145 times) previous topic - next topic

kevin1951

HI.
i'm new to Arduino, and at 69 years old am struggling to understand it.
i'm making"trying"to make  a robotic lawnmower, so far iv'e got most of it working, but i can't get to grips with slowing down the motors, i have two kids ride on car motors running at the moment.
this is the code iv'e downloaded.
#include <Servo.h>
 
// Pins
#define TRIG_PIN A0
#define ECHO_PIN A1
 
//Define all the connections maps to the L298N
#define enA 13
#define in1 12
#define in2 11
#define in3 7
#define in4 6
#define enB 5
#define servoPin 3
 
class Motor{
 
int enablePin;
int directionPin1;
int directionPin2;
 
public:
 
//Method to define the motor pins
Motor(int ENPin,int dPin1,int dPin2){
enablePin = ENPin;
directionPin1 = dPin1;
directionPin2 = dPin2;
};
 
//Method to drive the motor 0~255 driving forward. -1~-255 driving backward
void Drive(int speed){
if(speed>=0){
digitalWrite(directionPin1, LOW);
digitalWrite(directionPin2, HIGH);
}
else{
digitalWrite(directionPin1, HIGH);
digitalWrite(directionPin2, LOW);
speed = - speed;
}
analogWrite(enablePin, speed);
}
};
 
Motor leftMotor = Motor(enA, in1, in2);
Motor rightMotor = Motor(enB, in3, in4);
Servo myservo; // create servo object to control a servo
 
void motorInitiation(){
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
// Set initial direction and speed
digitalWrite(enA, LOW);
digitalWrite(enB, LOW);
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
}
 
//Variables--------------------------------------------------------------------------
// Anything over 400 cm (23200 us pulse) is "out of range"
const unsigned int MAX_DIST = 23200;
bool ObsticalAhead = false;
int servoPos = 90;
 
enum Directions { Forward, TurnLeft, TurnRight, TurnAround,Brake};
 
Directions nextStep = Forward;
 
unsigned long t1;
unsigned long t2;
unsigned long pulse_width;
float cm;
float inches;
 
//SETUP--------------------------------------------------------------------------
void setup() {
 
// The Trigger pin will tell the sensor to range find
pinMode(TRIG_PIN, OUTPUT);
digitalWrite(TRIG_PIN, LOW);
 
// We'll use the serial monitor to view the sensor output
Serial.begin(9600);
myservo.attach(servoPin);
motorInitiation();
Directions nextStep = Forward;
}
 
void loop() {
 
checkDistance();
checkDirection();
drive();
}
 
void checkDistance(){
 
// Hold the trigger pin high for at least 10 us
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
 
// Wait for pulse on echo pin
while ( digitalRead(ECHO_PIN) == 0 );
 
// Measure how long the echo pin was held high (pulse width)
// Note: the micros() counter will overflow after ~70 min
t1 = micros();
while ( digitalRead(ECHO_PIN) == 1);
t2 = micros();
pulse_width = t2 - t1;
 
// Calculate distance in centimeters and inches. The constants
// are found in the datasheet, and calculated from the assumed speed
//of sound in air at sea level (~340 m/s).
cm = pulse_width / 58.0;
inches = pulse_width / 148.0;
 
// Print out results
if ( pulse_width > MAX_DIST ) {
//Serial.println("Out of range");
} else {
//Serial.print(cm);
//Serial.print(" cm \t");
//Serial.print(inches);
//Serial.println(" in");
}
 
// Wait at least 60ms before next measurement
delay(60);
 
if(cm<= 20){
ObsticalAhead = true;
Serial.println("Problem Ahead");
 
}
else{ ObsticalAhead = false;}
 
}
void checkDirection(){
Serial.println("checking direction");
if(ObsticalAhead ==true){
nextStep = Brake;
drive();
myservo.write(180); // tell servo to go to position in variable 'pos'
delay(400); // waits 15ms for the servo to reach the position
checkDistance();
if(ObsticalAhead ==false){//if left side is open
nextStep = TurnLeft;
Serial.println("Next step is TurnLeft");
myservo.write(90);//reset servo position
delay(400);
}
else{// left is blocked, now need to look at right
myservo.write(0); // tell servo to go to position in variable 'pos'
delay(800); // waits 15ms for the servo to reach the position
checkDistance();
if(ObsticalAhead ==false){//if right side is open
nextStep = TurnRight;
Serial.println("Next step is TurnRight");
myservo.write(90);//reset servo position
delay(400);
}
else{//right is blocked as well, need to turn around
nextStep = TurnAround;
myservo.write(90);//reset servo position
delay(300);
Serial.println("Next step is TurnAround");
}
}
 
}
else{nextStep = Forward;}//No obstical ahead
}
 
void drive(){
switch (nextStep){
case Forward:
leftMotor.Drive(255);
rightMotor.Drive(255);
Serial.println("Forward");
 
break;
case TurnLeft:
leftMotor.Drive(-255);
rightMotor.Drive(255);
Serial.println(" TurnLeft");
delay(400);
 
break;
case TurnRight:
leftMotor.Drive(255);
rightMotor.Drive(-255);
Serial.println(" TurnRight");
delay(400);
break;
case TurnAround:
leftMotor.Drive(255);
rightMotor.Drive(-255);
Serial.println(" TurnAround");
delay(600);
break;
 
case Brake:
leftMotor.Drive(0);
rightMotor.Drive(0);
Serial.println(" stopped");
}
 
}

I realise that i am totally out of my depth, but nevertheless i would still appreciate some assistance.

wildbill

How do you plan to specify the speed?

Is it supposed to run at different speeds or do just want it running at a speed slower than it does now?

johnwasser

Code: [Select]
// Wait for pulse on echo pin
while ( digitalRead(ECHO_PIN) == 0 );
 
// Measure how long the echo pin was held high (pulse width)
// Note: the micros() counter will overflow after ~70 min
t1 = micros();
while ( digitalRead(ECHO_PIN) == 1);
t2 = micros();
pulse_width = t2 - t1;


All of this can be replaced with:
Code: [Select]
pulse_width = puleIn(ECHO_PIN, HIGH, MAX_DIST);

And the NewPing library can handle all of the low-level stuff for you and deliver distances in cm.

One problem with the code as written.  If no echo is seen the Echo pin will never go HIGH and your first while() loop will hang forever.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp
See who has no social life: https://forum.arduino.cc/index.php?action=stats :)

slipstick

You forgot to say which Arduino you are using. Pin13 isn't a PWM pin on many of them so analogWrite won't do what you expect.

What exactly are the motors you are using because an L298N will only run small motors (and not very well). "Kids ride on car motors" sound like they will be way too big.

Steve

kevin1951

Thanks for the replies, I'm using an Arduino Uno, I just need to lower the speed in both directions, also using two 12000 rpm 12v motors.

slipstick

O.k. you need to move enA to a different pin. Valid PWM pins for speed control are 3, 5, 6, 9, 10, 11.

12000rpm 12V isn't really a motor specification. Do you have a link to the motors you're using?

Steve

JCA34F

What are the full load and stall current of those motors?

wildbill

Thanks for the replies, I'm using an Arduino Uno, I just need to lower the speed in both directions, also using two 12000 rpm 12v motors.
Change the number you pass to analogWrite (after you've redone the wiring as suggested). Try 128 to start with and experiment with it until you get the speed you need. Be aware that at some point, the number will be too low to move the motors at all.

slipstick

Sorry, just noticed you're using Servo.h so that means you can't use PWM on pins 9 and 10 either. So enA needs to be on one of 3,5,6 or 11.

Steve

Go Up