**Full sketch added to files.
Equipment:
MEGA 2560
SyRen50 Motor Controller
12V, 30A switching power supply for motor
12V, 3000mA wall wart for Arduino
12VDC motor
Incremental encoder
Generic LCD
What I want to do:
Control a maximum motor speed as determined by the difference in position. Current position is registered by an incremental encoder and desired position is varied by a simple pushbutton counter for the moment. Both positions read correct in the LCD and Serial.print when troubleshooting. I am trying to make the motor ramp up to the motor setpoint if its current speed is less and ramp down the setpoint if its current speed is more. If the positions are equal, I want the motor to stop. Essentially, I am looking for proportional control; the farther from the target position, the faster I want the motor to go towards it.
This is going to control a telescope dome so all the 360° math relates to the azimuth of the dome and a lot of the math shown is to keep everything scaled to a positive 360° no matter which direction the encoder is running.
I am setting the motor setpoint (mtrMax) in mtrSpeedMax () and instructing the motor to run at those speeds in the second half of mtrRun() after the auto manual condition has been checked (needs to see a 1). You'll see a manual motor operation section in first half of the later function (condition autoMan == 0) and that operates just fine ramping to and from a maximum value as determined in the first half of mtrSpeedMax()
What is happening:
The motor seems to ramp up ok but once it reaches the maximum of 80, it holds that value and will not ramp down. I do not understand why, clearly I am not satisfying some condition but the logic seems simple enough I can't find the error I've injected.
I had to delete the various sections of code and notes to get under 9000 characters so if you suspect something is missing that is causing the problem, I can post other sections in the comments.
My code is over 9000 characters so it won't let me post in its entirety. I've posted what I believe to be the pertinent sections (I am very aware that I could be wrong) so if something else needs to be looked at I can post more in the comments.
void differentialPosition() {
//////***math to sort smallest of angle differences***///////
if ((tgtPos - azi) > 0) {
angleDiff1 = abs(tgtPos - azi - 360);
}
else {
angleDiff1 = tgtPos - azi;
}
if (azi > tgtPos) {
angleDiff2 = azi - tgtPos;
}
else {
angleDiff2 = tgtPos - azi;
}
if (angleDiff2 > 180) {
smallestAngle = 360 - angleDiff2;
}
else {
smallestAngle = angleDiff2;
}
void mtrSpeedMax() {
if (autoMan == 0) { // If in manual mode
mtrMax = 100;
}
if (autoMan == 1) { // If in auto mode ***Add conditions for differential speed***
if (smallestAngle > 0 && smallestAngle < 5) {
mtrMax = 15;
}
if (smallestAngle >= 5 && smallestAngle < 20) {
mtrMax = 20;
}
if (smallestAngle >= 20 && smallestAngle < 90) {
mtrMax = 60;
}
if (smallestAngle >= 90 && smallestAngle < 180) {
mtrMax = 80;
}
if (azi % 360 == tgtPos % 360) {
mtrMax = 0;
}
}
}
void mtrRun () {
//Default lights to off
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
//Declare variables for encoder millis() math
static unsigned long lastAccelTime = 0;
static unsigned long lastDecelTime = 0;
unsigned long currentTime = millis();
if (autoMan == 0) { //Manual mode **works fine
//CCW Button ramp motor up if high ramp to max if nigh, ramp down to 0 if low, ramp to zero if both pressed
if (digitalRead(BUTTON1) == HIGH && digitalRead(BUTTON2) == LOW && power >= 0)
{
digitalWrite(LED1, HIGH);
if (currentTime - lastAccelTime > accel) {
lastAccelTime = currentTime;
if (power <= mtrMax) {
power ++;
SR.motor(power);
}
}
}
if (power > 0 && digitalRead(BUTTON1) == LOW || power > 0 && digitalRead(BUTTON1) == HIGH && digitalRead(BUTTON2) == HIGH || power > 0 && digitalRead(BUTTON1) == LOW && digitalRead(BUTTON2) == HIGH )
{
if (currentTime - lastDecelTime > decel) {
lastDecelTime = currentTime;
power = power / 1.01;
SR.motor(power);
}
}
// CW Button ramp motor down to max negative if high, ramp up to 0 if low, ramp to 0 if both pressed
if (digitalRead(BUTTON2) == HIGH && digitalRead(BUTTON1) == LOW && power <= 0) //ramp up in positive direction with B1 pressed
{ //but return speed to zero if conflicting inputs
digitalWrite(LED2, HIGH);
if (currentTime - lastAccelTime > accel) {
lastAccelTime = currentTime;
if (power >= -mtrMax) {
power --;
SR.motor(power);
}
}
}
if (power < 0 && digitalRead(BUTTON2) == LOW || power < 0 && digitalRead(BUTTON1) == HIGH && digitalRead(BUTTON2) == HIGH || power < 0 && digitalRead(BUTTON2) == LOW && digitalRead(BUTTON2) == HIGH)
{
if (currentTime - lastDecelTime > decel) {
lastDecelTime = currentTime;
power = power / 1.01;
SR.motor(power);
}
}
}
if (autoMan == 1) { //automatic mode **does not work
if (mtrdirection == -1) {
if (currentTime - lastAccelTime > accel) {
lastAccelTime = currentTime;
if (power < mtrMax && power >= 0) {
power ++;
SR.motor(power);
}
}
if (currentTime - lastAccelTime > accel) {
lastAccelTime = currentTime;
if (power > mtrMax && power > 0) {
power = power / 1.01;
SR.motor(power);
}
}
}
if (mtrdirection == 1) {
if (currentTime - lastAccelTime > accel) {
lastAccelTime = currentTime;
if (power > -mtrMax && power <= 0) {
power --;
SR.motor(power);
}
}
if (currentTime - lastAccelTime > accel) {
lastAccelTime = currentTime;
if (power < -mtrMax && power < 0) {
power = power / 1.01;
SR.motor(power);
}
}
}
}
}
SabertoothArduinoLibraries.zip (382 KB)