I did some more testing.. The code with the protective access does cause the "runnaway" head upwards. Sometimes it may take 8-10 moves before it does it, and others times it occurs about 1 out of three times. I had some serial prints from the tests, but I apparently lost many of them, but here is one...
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -241
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -241
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -163
I uploaded the seemingly working code (I'll paste below), and made 15-20 moves and it did perfect. I decided to fire up the engine and give it a whirl) I cut up about 7-8 boards off of a log that was loaded, and it worked pretty much perfectly. Even the throttle control (servo motor) seemed to work right. I LOVE THIS FEATURE! I have never been able to control the throttle without physically turning the lever. So, the engine runs at WOT most of the time while I am cutting. This is no good for anything. Now with the turn of the pot, I can throttle down to idle for over 50 percent of the time (head moving up after cut, head moving back, head moving back down before next cut).
I have no idea why the protected access would be causing issues, but I sure hope that's what it is. I am including the serial prints below of the actual cutting that I did with the engine running and sawing lumber. It looks pretty good.... As, you will notice, after I finished cutting the log, I moved the head up and did a "fake" autoSlab run. It appeared correct until it was time for autoReverse() to be called, and it never got called. I couldn't remember what the issue was with this code for autoSlab, but I guess I will have a look later. I am going to try and load another log and see I continue to get good results.
start...
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -241
Trigger Up
softStartUp
PWM used after being increased by 20 percent = 145
Finish Upcount before motor Reversal = 240
The count after any over run = 240
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -242
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -242
Trigger Up
softStartUp
PWM used after being increased by 20 percent = 136
Finish Upcount before motor Reversal = 240
The count after any over run = 240
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -241
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -242
Trigger Up
softStartUp
PWM used after being increased by 20 percent = 140
Finish Upcount before motor Reversal = 241
The count after any over run = 241
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -240
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -242
Trigger Up
softStartUp
PWM used after being increased by 20 percent = 142
Finish Upcount before motor Reversal = 240
The count after any over run = 240
Trigger Up
softStartUp
PWM used after being increased by 20 percent = 153
Finish Upcount before motor Reversal = 240
The count after any over run = 240
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -240
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -242
Trigger Down
softStartDown
hardFinishcount before motor Reversal = -240
The count after any over run = -239
Trigger Up
softStartUp
PWM used after being increased by 20 percent = 130
Finish Upcount before motor Reversal = 240
The count after any over run = 240
AutoSlab Mode has started
throttle increasing to WOT
head moving forward
throttle decreasing to IDLE
The number of teeth counted is 55
softStartUp
PWM used after being increased by 20 percent = 139
Finish Upcount before motor Reversal = 240
The count after any over run = 240
//This has bitRead commented out and uses digitalRead. This allows me to use uno or mega. bitRead location in this sketch is for uno
//This has bitRead commented out and uses digitalRead. This allows me to use uno or mega. bitRead location in this sketch is for uno
#include <Servo.h>
Servo myServo; // create a servo object
const byte gearSensor = 2; // external interrupt pin
const byte encoderA = 3;//INT5 external interrupt pin
const byte encoderB = 4;
const byte beginAutoSlab = 5;
const byte headUp = 6;//if this pin goes high winch will engage clockwise through transistor board
const byte headDown = 7;//if this pin goes high winch will engage counterclockwise through transistor board
const byte buttonUpQuarter = 8;
const byte pwm = 9; //can I connect this pin to both motor drivers since they should never be engaged at the same time?
const byte buttonUpManual = 10;
const byte pwm2 = 11;
const byte headForward = 12;
const byte headBackward = 13;
const byte buttonDownManual = A0;
const byte pot = A15;
const byte buttonDownQuarter = A2;
const byte throttlePot = A1;
char directionSignal;
const int countUpQuarter = 240;
const int countDownQuarter = -240;
const int countUp1inch = 320;
const int countDown1inch = -320;
const int upMaxSpeed = 255;
const int downMaxSpeed = 75;
const int upSlowSpeed = 240;
const int downSlowSpeed = 38;
const int forwardMax = 158;// Maximum Speed of head moving forward during AUTO SLAB
const int forwardSlow = 148;
const int backwardMax = 255; // Maximum Speed of head moving backward during Auto Slab
const int backwardSlow = 130;
const int headGearSensor = 298;// Gear Tooth sensor that reads the teeth as the head moves forward/backwards
const int braking = (headGearSensor);
volatile int count = 0;
volatile int countGear = 0;
volatile int targetCount = 0;
volatile boolean runFinished = false;
volatile boolean autoHeadStarted = false;
volatile boolean loopFinished = false;
volatile boolean quarterMove = false;
volatile boolean checkCount = true;
int val;
int throttleVal;
int countBeforeCorrection;
int throttleAngle;
int prevCountGear;
unsigned long prevMillis = millis();
int prevCount = count;
byte pwmValue = 0;
void setup()
{
Serial.begin(115200);
Serial.println("start...");
myServo.attach(44);
pinMode(encoderA, INPUT_PULLUP); //external circuit pullup
pinMode(encoderB, INPUT_PULLUP); //external circuit pullup
pinMode(buttonUpQuarter, INPUT_PULLUP);
pinMode(buttonDownQuarter, INPUT_PULLUP);
pinMode(buttonUpManual, INPUT_PULLUP);
pinMode(buttonDownManual, INPUT_PULLUP);
pinMode(gearSensor, INPUT_PULLUP);//external circuit pullup 1K resistor
pinMode(beginAutoSlab, INPUT_PULLUP);
pinMode(headUp, OUTPUT); //connected to forward reverse switch of head motor driver
pinMode(headDown, OUTPUT);//connected to forward reverse switch of head motor driver
pinMode(pwm, OUTPUT);
pinMode(headForward, OUTPUT); // connected to forward reverse switch of motor driver through TIP120 Transistor board 2.2K resistor
pinMode(headBackward, OUTPUT); // connected to forward reverse switch of motor driver through TIP120 Transistor board
pinMode(pwm2, OUTPUT); // uncomment if there is a way to control headForward/headBackward with both pot and arduino if not pot will control speed during autoSlab and uncomment below
pinMode(throttlePot, INPUT);
attachInterrupt(digitalPinToInterrupt(gearSensor), isrMove, FALLING);
countGear = 0;
attachInterrupt(digitalPinToInterrupt(encoderA), isrCount, CHANGE);
EIMSK &= ~(1 << INT5);//disable interrupts until motor moves
EIFR |= (1 << INTF5);//clear any preesisting flags
count = 0;//clear counts
}
void loop()
{
{
val = analogRead(pot);
val = map(val, 0, 1023, 0, 255);
}
if (val >= 10) {
analogWrite(pwm2, val);
}
else {
analogWrite(pwm2, 0);
}
throttleVal = analogRead(throttlePot);
throttleVal = map(throttleVal, 0, 1023, 8, 75);//I think I need to adjust 255 to the angle needed for WOT
throttleAngle = throttleVal;
myServo.write(throttleAngle);
if (digitalRead(beginAutoSlab) == LOW)
{
Serial.println("AutoSlab Mode has started");
delay(1000);
autoSlab();
}
if (digitalRead(buttonUpQuarter) == LOW)
{
Serial.println("Trigger Up");
delay(1000);//need to rework for state change of button
motorUpQuarter();
}
if (digitalRead(buttonDownQuarter) == LOW)
{
Serial.println("Trigger Down");
delay(1000);//need to rework for state change of button
motorDownQuarter();
}
if (digitalRead(buttonUpManual) == LOW)
{
motorUpUntil();
}
if (digitalRead(buttonDownManual) == LOW)
{
motorDownUntil();
}
if (quarterMove == true and runFinished == true)// quarterMove set true when quarterUpQuarter or QuarterDownQuarter button is pressed
//runFinished set true in the isr once the targetCount has been reached.
{
if (directionSignal == '-')
{
Serial.print("hardFinish");
Serial.print("count before motor Reversal = ");
Serial.println (countBeforeCorrection);
delay(150); // adjust the amount of time the reversal of motor is on
EIMSK &= ~(1 << INT5);//stop interrupts
EIFR |= (1 << INTF5);//clear any preesisting flags
digitalWrite(headUp, LOW);
digitalWrite(headDown, LOW);
delay(1000); // wait and see how much over run I get
Serial.print("The count after any over run = ");
Serial.println(count);
runFinished = false;
}
if (directionSignal == '+'){
Serial.print("Finish Up");
Serial.print("count before motor Reversal = ");
Serial.println (countBeforeCorrection);
EIMSK &= ~(1 << INT5);//stop interrupts
EIFR |= (1 << INTF5);//clear any preesisting flags
digitalWrite(headUp, LOW);
digitalWrite(headDown, LOW);
delay(1000); // wait and see how much over run I get
Serial.print("The count after any over run = ");
Serial.println(count);
runFinished = false;
}
}
if (autoHeadStarted == true and runFinished == true)//autoHeadStarted was set True in the AutoHeadUp function and runFinished was set true once the targetCount was reached and head stopped moving
{
if (directionSignal == '-')
{
Serial.print("hardFinish");
Serial.print("count before motor Reversal = ");
Serial.println (countBeforeCorrection);
delay(150); // adjust the amount of time the reversal of motor is on
EIMSK &= ~(1 << INT5);//stop interrupts
EIFR |= (1 << INTF5);//clear any preesisting flags
digitalWrite(headUp, LOW);
digitalWrite(headDown, LOW);
delay(1000); // wait and see how much over run I get
Serial.print("The count after any over run = ");
Serial.println(count);
runFinished = false;
}
if (directionSignal == '+'){
Serial.print("Finish Up");
Serial.print("count before motor Reversal = ");
Serial.println (countBeforeCorrection);
EIMSK &= ~(1 << INT5);//stop interrupts
EIFR |= (1 << INTF5);//clear any preesisting flags
digitalWrite(headUp, LOW);
digitalWrite(headDown, LOW);
delay(1000); // wait and see how much over run I get
Serial.print("The count after any over run = ");
Serial.println(count);
runFinished = false;
}
autoReverse();
}
if (loopFinished == true and runFinished == true)
{
digitalWrite(headUp, LOW);//This should stop winch lift motor
digitalWrite(headDown, LOW);//This should stop winch lift motor
EIMSK &= ~(1 << INT5);//stop interrupts DO I need this when autoSlabbing?
EIFR |= (1 << INTF5);//clear any preesisting flags DO I need this when autoSlabbing?
delay(2000);
autoSlab();
}
}
void isrMove()
{
countGear ++;
}
void isrCount()//interrupt routine for encoder
{
byte AState = digitalRead(encoderA);
byte BState = digitalRead(encoderB);
if (AState == BState)
count++;
else
count--;
if (directionSignal == '-' and count <= targetCount)
{
//set motor to up with a value which locks the motor
countBeforeCorrection = count;
digitalWrite(headUp, HIGH);
digitalWrite(headDown, LOW);
analogWrite(pwm, 200);
runFinished = true;
}
if (directionSignal == '+' and count >= targetCount)
{
countBeforeCorrection = count;
//digitalWrite(headDown, HIGH); //try using these if over run up is a problem
//digitalWrite(headUp, LOW);
//analogWrite(pwm, 40);//This adjust how much to pwm wanted to reverse the motor and prevent overrun
digitalWrite(headUp, LOW);
digitalWrite(headDown, LOW);
runFinished = true;
}
}
void motorUpQuarter()
{
runFinished = false;
digitalWrite(headUp, HIGH);
targetCount = countUpQuarter;
directionSignal = '+';
count = 0;
EIFR |= (1 << INTF5);//clear any preesisting flags
EIMSK = (1 << INT5); //enable interrupt counting
softStart();
quarterMove = true;
}
void motorDownQuarter()
{
runFinished = false;
digitalWrite(headDown, HIGH);
targetCount = countDownQuarter;
directionSignal = '-';
count = 0;
EIFR |= (1 << INTF5);//clear any preesisting flags
EIMSK = (1 << INT5); //enable interrupt counting
softStart();
quarterMove = true;
}
void motorUpUntil ()
{
digitalWrite(headUp, HIGH);
//soft start
for (int i = 0; i <= 255; i = i + 10)
analogWrite(pwm, i);
while (digitalRead(buttonUpManual) == LOW) {} //Release of Button
analogWrite(pwm, 0);
digitalWrite(headUp, LOW);
}
void motorDownUntil ()
{
digitalWrite(headDown, HIGH);
//soft start
for (int i = 0; i <= 255; i = i + 10)
analogWrite(pwm, i);
while (digitalRead(buttonDownManual) == LOW) {} //Release of Button
analogWrite(pwm, 0);
digitalWrite(headDown, LOW);
}
void softStart() //count should always be starting at 0
{
if (directionSignal == '+') //was set for an up move
{
Serial.println("softStartUp");
for (int i = 0; i <= 255; i = i + 1)//head should move up before 255
{
analogWrite(pwm, i);
delay(10);
if (count >= 5) //give some leeway here incase of vibration noise
{
i = i * 1.2;// //add 20 percent to the pwm that begins the head moving
analogWrite(pwm, i);
Serial.print("PWM used after being increased by 20 percent = ");
Serial.println(i);
break; //exit for() loop
}
}
}
if (directionSignal == '-') //was set for a down move
{
Serial.println("softStartDown");
for (int i = 0; i <= 28; i = i + 1) //head should move up before 150
{
analogWrite(pwm, i);
delay(10);
if (count <= -5) //give some leeway here incase of vibration noise
{
// i = i ;// //add 15 percent to the pwm that begins the head moving
// analogWrite(pwm, i);
Serial.print("PWM used = ");
Serial.println(i);
break; //exit for() loop
}
}
}
}
void autoSlab() //Called on from button press and completion of autoHeadDown()
{
Serial.println("throttle increasing to WOT");
myServo.write(65);//adjust number to be WOT Need to disable POT some how...
delay(3000);
Serial.println("head moving forward");
countGear = 0;
EIMSK |= (1 << INT4);
digitalWrite(headForward, HIGH);
while (countGear <= 250) // Start Slowing Down and prevent issue of 255/256 changeOver
{
if (millis() - prevMillis > 250) // check periodically need adjust based on how fast desired tooth to pass sensor per check
{
if (prevCountGear == countGear)
{
if (pwmValue < 80)
pwmValue = pwmValue + 10; // more power to get moving at start quicker
if (80 < pwmValue < 255)
pwmValue++; // more power applied slower to make sure head continue to move
}
else
{
noInterrupts();
prevCountGear = countGear;
interrupts();
}
prevMillis = millis(); // reset time for next check.
analogWrite(pwm2, pwmValue);
}
}
noInterrupts();
countGear = 0;
interrupts();
while (countGear <= headGearSensor - 250); // prevent issue of 255/256 change Over
{
if (millis() - prevMillis > 250) // check periodically need adjust based on how fast desired tooth to pass sensor per check
{
if (prevCountGear == countGear)
{
if (pwmValue < 255)
pwmValue++; // more power applied slower to make sure head continue to move
}
else
{
noInterrupts();
prevCountGear = countGear;
interrupts();
}
prevMillis = millis(); // reset time for next check.
analogWrite(pwm2, pwmValue);
}
}
analogWrite(pwm2, 0);
digitalWrite(headForward, LOW);
loopFinished = false;
delay (1000);
Serial.println("throttle decreasing to IDLE");
myServo.write(8);//adjust number to be WOT Need to disable POT some how...
delay(3000);
autoHeadUp();
}
void autoHeadUp() // Called on from autoSlab
{
Serial.print("The number of teeth counted is ");
Serial.println(countGear);
runFinished = false;
digitalWrite(headUp, HIGH);
targetCount = countUpQuarter;
directionSignal = '+';
count = 0;
EIFR |= (1 << INTF5);//clear any preesisting flags
EIMSK = (1 << INT5); //enable interrupt counting
autoHeadStarted = true;
softStart();
}
void autoReverse() //Called with if statement in void loop() when runFinished = true and autoHeadStarted = true
{
Serial.println("head moving backwards");
countGear = 0;
EIMSK |= (1 << INT4);//enable interrupt
digitalWrite(headBackward, HIGH);//sets the forward reverse switch on the hacked motor driver for head forward
for (int i = 0; i <= backwardMax; i = i + 10)
{
analogWrite(pwm2, i);
delay (10);
}
while (countGear <= braking) //90 % there slow down
{}
noInterrupts();
countGear = 0;
interrupts();
for (int i = backwardMax; i >= backwardSlow; i = i - 10)
{
analogWrite(pwm2, i);
delay(10);
}
while (countGear <= headGearSensor - braking);
{}
analogWrite(pwm2, 0);
digitalWrite(headBackward, LOW);
delay(2000);
autoHeadDown();
}
void autoHeadDown() // called on from autoReverse()
{
Serial.print("The number of teeth counted is ");
Serial.println(countGear);
runFinished = false;
autoHeadStarted = false;
digitalWrite(headDown, HIGH);
targetCount = countDownQuarter * 2; //I want it to go down twice the targetCount because it should be above the log the thickness of the board that was just cut
directionSignal = '-';
count = 0;
EIFR |= (1 << INTF5);//clear any preesisting flags
EIMSK = (1 << INT5); //enable interrupt counting
loopFinished = true;
softStart();
}
Thanks!