Wanting to add an accel and decel function to a Motor Controller

:smiley: Hi Everybody,

I'm building a handheld DC motor controller with (power monitoring, etc) that's used for testing motors already installed on equipment. This is a project that 10th through 12th grade students are putting together and I'm try to lead them through it from nothing. Its teaching them a little about electronic hardware, wiring, programming, and 3D CAD/CAM. The problem is I have a mechanical background and have very little knowledge about programming. Like the subject is trying to convey, I'm stuck at a "feature" I want to include in the program.

The way I currently have this in prototype form there is a pot that sets a speed and a button that enables that speed. The program takes these values and maps it to the values needed for my pwm being sent to the speed controller. this is extremely simple and straight forward in my program and it was relatively easy to throw together with my very limited knowledge.

The reason I want to implement this feature is that if you set the speed before pressing the enable button, the motor and attached drive train, etc gets a violent shock. The same thing happens if you let go of the trigger before returning the speed pot to neutral. So... I want to have a "soft start feature" that is capable of dealing with a constantly moving set point(ie. somebody adjusts the speed up or down while holding down the enabled button.

The one way to maybe accomplish this in my mind is to implement a PID library. The hangup here(is it a hangup, i don't know??) is that i'm not implementing any feedback for speed. BUT, i thought maybe it would be possible to take a sample of the "current pot value" every 50millis(maybe+-) and compare that to the "old pot value"... In other words, if i understand a PID loop correctly, the inputs are set-point and current speed and it outputs a "correction increment".. So.... (deep breath lol) the "current pot value" would be the set-point for the PID loop, the "old pot value" would act as the speed feedback for the PID loop and it would pop out a "correction increment" that i could feedback into a loop that updates the speed controller pwm output...

I hope everybody can follow that.. sorry if it sounds like a ramble but I'm still very unsure about the possibility of it working and how to implement it. I'm sure that there is some very simple, clever, "why in the heck didn't i think of that" way of doing this but that is exactly what i want to hear. Give me all your thoughts but please take it easy on me. I never touch arduino or any programming language for my own project until about a month ago and I don't want to have to fill out a hurt feelings report with this website :slightly_smiling_face: ... oh how i hate paperwork LOL :grinning:

Thanks ahead of time!!

-Jones

You have some code you want us to look at?

To accelerate, you, obviously, start with a speed of 0 and gradually increase the speed until you are going full speed. How gradually? Well, you didn't tell us if you want to take 3.65432 seconds or 3000 years.

To decelerate, you do the same, except you step the speed down instead of up.

Rather than use the value from the potentiometer directly, use it as a max or min setting and use another variable to control the speed of the motor.

Then at whatever intervals seem reasonable (maybe every 100 millisecs) adjust the motor speed variable up or down in steps until it matches the value from the potentiometer. Something like this

byte adjPWM = 5; // just a guess for illustration
unsigned long changeIntervalMillis = 100;
if (millis() - prevChangeMillis >= changeIntervalMillis) {
   prevChangeMillis += changeIntervalMillis;
   if (motorPWM > potPWM) {
      motorPWM -= adjPWM;
   }
   else if (motorPWM < potPWM) {
      motorPWM += adjPWM;
   }
   analogWrite(motorPin, motorPWM;
}

...R

Robin2:
Rather than use the value ...

Thank you! This is getting my wheels turning in the right direction i think. I'm the captain of over thinking and over complicating what should be a simple solution. One question that comes to mind right away about you code. Wouldn't i have to increment in steps of 1 always since if i increment in steps 5 and my target is not an interval of five it will over shoot and oscillate the speed, never getting to target?? I'm sorry if I miss understand. I'll be implementing this into my code this afternoon when i'm home for the day. Thanks again!

PaulS:
You have some code ...

Yes, but didn't include it because it wasn't what i was trying to accomplish. Here is the snip that applies to what we are doing. I'm walking out the door so I'm sorry if it leaves something out(like int variables). My program is lengthy and 80% doesn't apply to what I'm talking about here. Thanks!

void read_pot() {
  potvalue = analogRead(pot_pin);                   // read the input on analog pin 0 and write to var potvalue:
}

void map_pot() {
 if(trigger == 0) {
 mappedpotvalue = map(potvalue, 0, 1023, 1000, 2000);       //1000:full rev  1500:neutral  2000:full forward
  bargraphvalue = mappedpotvalue - 1000;                    //Display speed on lcd in graph form
  }
  else() {
  mappedpotvalue = 1500
  }
}

void drive_pwm() {
talon.writeMicroseconds(mappedpotvalue);
}

MrJones:
One question that comes to mind right away about you code. Wouldn't i have to increment in steps of 1 always since if i increment in steps 5 and my target is not an interval of five it will over shoot and oscillate the speed, never getting to target??

That's possible,. I just used 5 for illustration.

I felt I needed to leave something for you to get your teeth into :slight_smile:

...R

Wouldn't i have to increment in steps of 1 always since if i increment in steps 5 and my target is not an interval of five it will over shoot and oscillate the speed, never getting to target??

You could increment in steps of 27, when the starting value is 13 and the target is 84, if you are smart. There is nothing that says that every increment must be exactly the same size. If the final increment would produce a value that is over the target, there is no reason that you HAVE to go over the target.

Robin2:
Rather than use the value from the potentiometer directly, use it as a max or min setting and use another variable to control the speed of the motor.

Then at whatever intervals seem reasonable (maybe every 100 millisecs) adjust the motor speed variable up or down in steps until it matches the value from the potentiometer. Something like this

byte adjPWM = 5; // just a guess for illustration

unsigned long changeIntervalMillis = 100;
if (millis() - prevChangeMillis >= changeIntervalMillis) {
  prevChangeMillis += changeIntervalMillis;
  if (motorPWM > potPWM) {
     motorPWM -= adjPWM;
  }
  else if (motorPWM < potPWM) {
     motorPWM += adjPWM;
  }
  analogWrite(motorPin, motorPWM;
}




...R

Woohoo! :slight_smile:

This worked flawlessly! Thank You!! I knew I had to be over thinking it. Other than making adjustments for variable names and moving some stuff around it was just what i needed and now i understand the millis function much better. Thank you for posting this. This community is priceless!