Go Down

Topic: Ping-Pong with a DC motor & a pot (Read 2307 times) previous topic - next topic

BazzaCAD

So yes, I'm a noob.

I have a DC motor connected to a L298N driver. The motor is spinning what I call a large plate. In the center of this plate I have a pot.
I'm trying to get the plate to rotate in one direction until the pot reads 750, then reverse it's direction until the pot reads 300, then reverse again. Basically turning back & forth or Ping-Pong, but I'm having a hard time getting my head around the code.
Can anyone give me some suggestions?

I've tried stuff like this, but of course it's not working....:
Code: [Select]

#define  POT_PIN   A8
#define  MAX_LEFT  750
#define  MAX_RIGHT 300

//Motor A
int dir1PinA = 32;
int dir2PinA = 34;
int speedPinA = 36;
int motor_speed;
int dir = 0;

void setup() {
  pinMode (dir1PinA, OUTPUT);
  pinMode (dir2PinA, OUTPUT);
  pinMode (speedPinA, OUTPUT);
  motor_speed = 250;
}


void loop() {
  int headRot = analogRead(POT_PIN);
  analogWrite (speedPinA, motor_speed); //Turn motor on

  if (headRot < MAX_LEFT && dir == 0) // 750
  {
    flipMotorDirection(1);
    dir = 1;
    Serial.println("dir = 1");
  }
 
  if (headRot > MAX_RIGHT && dir == 1) // 300
  {
    flipMotorDirection(0);
    dir = 0;
    Serial.println("dir = 0");
  }
}


void flipMotorDirection(int dir)
{
  if (1 == dir)
  {
    digitalWrite (dir1PinA , LOW);
    digitalWrite (dir2PinA, HIGH);
  }
  else
  {
    digitalWrite (dir1PinA, HIGH);
    digitalWrite (dir2PinA, LOW);
  }
}


PaulS

Quote
but I'm having a hard time getting my head around the code.
Can anyone give me some suggestions?

The code does something. You want it to do something.

What you want it to do is clear. What it actually does is not.

We can't really help you until we know what the problem is.


PeterH

That code looks as if it is trying to power the motor in the target direction until it reaches the target, then reverses the motor direction and waits until the motor slows down, stops, accelerates in the reverse direction and reaches the other limit.

You don't say what it actually does, but this design is a recipe for a massively overshooting system which would be liable to be unstable and just overshoot further and further until it hits a mechanical limit somewhere.

I would have thought that a system with significant inertia as you're describing would benefit from using a PID algorithm to control the motor direction and speed. That way you could easily get it to move to the required position and stop.
I only provide help via the forum - please do not contact me for private consultancy.

BazzaCAD

Thanks for the replays.
Currently, when it's between 300 & 750 it alternates between 0 & 1 on every loop.
Code: [Select]

dir = 1
dir = 0
dir = 1
dir = 0
dir = 1
dir = 0
dir = 1
dir = 0


e.g. Runs the motor at 1/2 speed.
When the pot goes over 750, it runs at full speed, but doesn't reverse direction.
When the pot goes under 300, it runs at full speed, and reverses direction.

I'm not sure what a PID algorithm is or how to use it....?


PeterH

Ignoring everything but the motor, are you able to control it so that it moves in the direction you want at the speed you want?
I only provide help via the forum - please do not contact me for private consultancy.

BazzaCAD

#5
Oct 08, 2012, 04:52 am Last Edit: Oct 08, 2012, 04:58 am by BazzaCAD Reason: 1
Yes, if I run the code below, the motor runs as expected.
In one direct for 4 sec. then in the other for 4 sec.....

Code: [Select]

//Motor A
int dir1PinA = 2;
int dir2PinA = 3;
int speedPinA = 5;

unsigned long time;
int speed;
int dir;

void setup ()
{
 pinMode (dir1PinA, OUTPUT);
 pinMode (dir2PinA, OUTPUT);
 pinMode (speedPinA, OUTPUT);
 time = millis ();
 speed = 200;
 dir = 1;
}

void loop ()
{
 analogWrite (speedPinA, speed);
 
 // set direction
 if (1 == dir)
 {
   digitalWrite (dir1PinA , LOW);
   digitalWrite (dir2PinA, HIGH);
 }
 else
 {
   digitalWrite (dir1PinA, HIGH);
   digitalWrite (dir2PinA, LOW);
 }
 
 delay(4000);
   if (1 == dir)
     {dir = 0;}
   else
     {dir = 1;}
}


It's just the logic with the pot code that I can't figure out.

Nick Gammon


The code does something. You want it to do something.


That's what happens with my code!

I want it to do something. It does something. But usually that is "something else". ;)
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

PeterH


It's just the logic with the pot code that I can't figure out.


Initially I assumed that MAX_LEFT was less than MAX_RIGHT, and with that assumption your code seemed to make sense. But in fact MAX_LEFT is greater than MAX_RIGHT. That means that the comparisons you're applying to your pot values are back to front.
I only provide help via the forum - please do not contact me for private consultancy.

BazzaCAD

OK I "think" I got it now. How does this look?
Will this have the over shooting issue & hit a mechanical limit & break?

Code: [Select]

#define  POT_PIN   A8
#define  MAX_LEFT  750
#define  MAX_RIGHT 300

int dir = 0; // 0 = Left, 1 = Right

void setup() {
  Serial.begin(9600);
}

void loop() {
  int headRot = analogRead(POT_PIN);
// Serial.println(headRot); // read-print pot
 
  if (headRot < MAX_LEFT)
  {
    if (headRot > MAX_RIGHT)
    {
     // Serial.println("Center");
    } else {
    //  Serial.println("Max Right");
      dir = 0;
    }
  } else {
   // Serial.println("Max Left");
    dir = 1;
  }
 
  if (dir == 0)
  {
    Serial.println("Turning Left");
  } else {
    Serial.println("Turning Right"); 
  }
}

PaulS

You never actually do anything with dir or motors...

If the potentiometer values represent limits, names like MIN_something and MAX_something make more sense than two MAX_somethings.

BazzaCAD


You never actually do anything with dir or motors...

If the potentiometer values represent limits, names like MIN_something and MAX_something make more sense than two MAX_somethings.


Yes I was just testing to make sure I got the logic correct before connecting to the motor. Here it is with the motor code. Thanks for the tip on the MIN/MAX..

Code: [Select]

#define  POT_PIN   A8
#define  MAX_LEFT  750
#define  MIN_RIGHT 300

//Motor A
int dir1PinA = 32;
int dir2PinA = 34;
int speedPinA = 36;
int motor_speed = 250;
int dir = 0; // 0 = Left, 1 = Right

void setup() {
  Serial.begin(9600); 
}

void loop() {
 
  int headRot = analogRead(POT_PIN);
// Serial.println(headRot); // read-print pot
  analogWrite (speedPinA, motor_speed); //Turn motor on
 
  if (headRot < MAX_LEFT)
  {
    if (headRot > MIN_RIGHT)
    {
     // Serial.println("Center");
    } else {
    //  Serial.println("Min Right");
      dir = 0;
    }
  } else {
   // Serial.println("Max Left");
    dir = 1;
  }
 
  flipMotorDirection(dir); 
}


void flipMotorDirection(int dir)
{
  if (0 == dir)
  {
    digitalWrite (dir1PinA , LOW);
    digitalWrite (dir2PinA, HIGH);
  }
  else
  {
    digitalWrite (dir1PinA, HIGH);
    digitalWrite (dir2PinA, LOW);
  }
}

PaulS

Code: [Select]
  analogWrite (speedPinA, motor_speed); //Turn motor on
Varying the motor speed as you get closer to the limit would be a good thing. That's what the PID idea is all about. Sneak up on the limits to avoid overshooting.

You only need to flip the motor direction if it changes, not on every pass through loop.

Your commented out Serial.print() information does not reflect reality.


BazzaCAD


Varying the motor speed as you get closer to the limit would be a good thing. That's what the PID idea is all about. Sneak up on the limits to avoid overshooting.

You only need to flip the motor direction if it changes, not on every pass through loop.

Your commented out Serial.print() information does not reflect reality.


Thanks for the info. So I should slow down the motor as I get closer to the limit?

PaulS

Quote
So I should slow down the motor as I get closer to the limit?

Yes. Make the speed depend on the absolute value of the difference between the headRot value and the middle of the range. As the difference gets larger, slow down. As it gets smaller, speed up. The maximum speed, then, would be right in the center of the range.

BazzaCAD


Yes. Make the speed depend on the absolute value of the difference between the headRot value and the middle of the range. As the difference gets larger, slow down. As it gets smaller, speed up. The maximum speed, then, would be right in the center of the range.


Could you give me a hint on how to code that?

Go Up