I'm intending to use this code to control a linear actuator that controls the reverse buckets on a jet boat. The buckets are either raised (full forward power), or lowered (full reverse power), Neutral (equal parts forward and reverse thrust), or gradients between those positions.
One 0-5v hall sensor will be attached to the control lever in the helm to read the lever's position, and another hall sensor is attached to the lever on the transom of the boat that controls the bucket position. The linear actuator moves the transom lever to raise or lower the bucket.
The idea is that when the control lever is moved to a position in the helm, the pot gives a value, and then the actuator moves the bucket until the pot on the bucket matches the value of the control lever pot. I'm using the multimap function to be able to calibrate different neutral values for the control lever and the bucket since the physical neutral positions might not translate linearly between the two.
I'm using a separate MC circuit for each bucket on the boat (there are two), which are ruggeduinos with a MegamotoPlus on each one to control the actuators. The entire system will run through two 80a relays so as a backup I can switch to direct rocker switch control of the buckets in case the MCs freeze or fail.
The code I've pieced together so far works well in tinkercad, and I'm about to set up a bench test with one actuator this week. Does anyone have any suggestions or feedback to improve the code? Because the Megamoto can monitor load, I was thinking about adding code to watch for amperage spikes and force the actuator to rest for a short period if a serious spike occurs. Also, ignore all of the serial prints : ) Thanks in advance for any feedback!
const int reverseBucket = A0; //potentiometer from reverse bucket actuator
const int shiftLever = A1; //potentiometer from throttle
const int enable = 8;
const int PWMA = 11;
const int PWMB = 10;
int reverseMax = 1023;
int reverseMin = 0;//range of reverse bucket actuator pot
int shiftLeverMin = 0;
int shiftLeverMax = 1023; //range of shift lever pot
//these values are for the multimap fuction
int bucketNeutral = 511; //neutral position value for the bucket
int shiftLeverNeutral = 511; //neutral position value for the shift lever
int in[] = {shiftLeverMin,shiftLeverNeutral,shiftLeverMax};
int out[] = {reverseMin,bucketNeutral,reverseMax};
//end multimap fuction values
int speedMin = 100;
int speedMax = 225; //speed range of actuator when moving
int precision = 2;//how close to final value to get
int rawbucketPosition = 0;
int bucketPosition = 0;
int rawdestination = 0;
int destination = 0;
int difference = 0;//values for knowing location
void setup()
{
pinMode(reverseBucket, INPUT);//input from reverse bucket pot
pinMode(shiftLever, INPUT);//input from reverse shift lever pot
pinMode(enable, OUTPUT);
pinMode(PWMA, OUTPUT);//actuator motor outputs
pinMode(PWMB, OUTPUT);
digitalWrite(enable,HIGH);
Serial.begin(9600);
}
void loop()
{
destination = getDestination(); //See where shift lever is
bucketPosition = analogRead(reverseBucket);//check where reverse bucket is
Serial.print("Bucket Position ");
Serial.println(analogRead(reverseBucket));
Serial.print("Lever Position ");
Serial.println(analogRead(shiftLever));
difference = destination - bucketPosition;//find out how far you are from the destination
Serial.print("Difference ");
Serial.println(difference);
if (bucketPosition > destination) pullActuatorUntilStop(destination);// choose what action to take
else if (bucketPosition < destination) pushActuatorUntilStop(destination);
else if (difference < precision && difference > -precision) stopActuator();
}//end void loop
int getDestination()
{
int val = analogRead(shiftLever);//read the shift lever potentiometer to get the destination
destination = multiMap(val,in,out,3);//convert the shift lever values to match the bucket and calibrate neutral
return(destination);
}//end getDestination
void pushActuatorUntilStop(int destination)
{
destination = getDestination();
int rawbucketPosition = analogRead(reverseBucket);
difference = destination - rawbucketPosition;//check difference to see if continue moving, or stop
while (difference > precision)
{
destination = getDestination();
rawbucketPosition = analogRead(reverseBucket); //continue checking difference
difference = destination - rawbucketPosition;
int Speed = constrain(difference, speedMin, 255);
Serial.print("Bucket ");
Serial.println(rawbucketPosition);
Serial.print("Lever ");
Serial.println(destination);
pushActuator(Speed);
}//end while
delay(25);
stopActuator();
}//end pushActuatorUntilStop
void pullActuatorUntilStop(int destination)
{
destination = getDestination();
int rawbucketPosition = analogRead(reverseBucket); //check difference to see if continue moving, or stop
difference = destination - rawbucketPosition;
while (difference < -precision)
{
destination = getDestination();
rawbucketPosition = analogRead(reverseBucket); //continue checking difference
difference = destination - rawbucketPosition;
int Speed = constrain(-difference, speedMin, 255);
Serial.print("Bucket ");
Serial.println(rawbucketPosition);
Serial.print("Lever ");
Serial.println(destination);
pullActuator(Speed);
}//end while
delay(25);
stopActuator();
}//end pullActuatorUntilStop
void stopActuator()
{
analogWrite(PWMA,0);
analogWrite(PWMB,0);
}//end stopActuator
void pushActuator(int Speed)
{
analogWrite(PWMB, Speed);
analogWrite(PWMA,0);
}//end pushActuator
void pullActuator(int Speed)
{
analogWrite(PWMB,0);
analogWrite(PWMA, Speed);
}//end pullActuator
//MultiMap Functionality to set neutral position
int multiMap(int val, int* _in, int* _out, uint8_t size)
{
// take care the value is within range
// val = constrain(val, _in[0], _in[size-1]);
if (val <= _in[0]) return _out[0];
if (val >= _in[size-1]) return _out[size-1];
// search right interval
uint8_t pos = 1; // _in[0] allready tested
while(val > _in[pos]) pos++;
// this will handle all exact "points" in the _in array
if (val == _in[pos]) return _out[pos];
// interpolate in the right segment for the rest
return map(val, _in[pos-1], _in[pos], _out[pos-1], _out[pos]);
}