Challenge: Actuator speed control easing

Been working with member Anshu_Raj on this for 6 months on a complex automated actuator movement. Happy to pay for help.

6-channel Continuum Robot like this: 3-segment Continuum Robot

13 feet, it sits vertically:

Components:
(6) Roboclaw 30A controllers
(6) CreativeWerks 8" actuators with position feedback
(1) Mega 2560

But right now we're just trying to get one of the six channels to work, and will duplicate the rest later.

Goal is to move one actuator:

  • To a random position.
  • At a random speed.
  • Circular easing applied.

Programming:

  • Movement is driven randomly from the Arduino.
  • It runs one loop with a random speed and distance, then it switches direction to do the same thing. Repeat.

Problems we have:

  • Glitches in analog position feedback.
  • Complex loop calculations.

How would you do it?

Latest sketch below.

#include <SoftwareSerial.h>
#include "RoboClaw.h"
//Keep a track of time to update speed
#include <elapsedMillis.h>
elapsedMillis timeElapsed;

SoftwareSerial serial1(10, 10);
SoftwareSerial serial2(11, 11);
SoftwareSerial serial3(12, 12);

RoboClaw sec1(&serial1, 10000);
RoboClaw sec2(&serial2, 10000);
RoboClaw sec3(&serial3, 10000);

#define address 0x80

//Can be set to const
//MODIFY THESE VALUES AS PER DATA FROM CALIBRATION SKETCH
const byte pot[][3] = {{0, 0, 0}, {0, A0, A1}, {0, A2, A3}, {0, A4, A5}}; //pot[Section][Axis]
boolean dirBool[][3] = {{0, 0, 0}, {0, 1, 1}, {0, 1, 0}, {0, 1, 0}}; //dirBool[Section][Axis]

//Change these values to see change in update speed
//Update speed is based on time elasped and not on position
//So, each acuator will have same speed at a given time
byte spdHD[] = {20,26,32,38,44,50,56,62,68,74,80,74,68,62,56,50,44,38,32,26,20}; //HARDCODED SPEED VALUES
const int spdHDlenght = 21; //Size of the above array
const int updateSpdEvery = 2000; //2000 milliseconds
byte spd = 20; //Initial speed (Changing this value dosen't matters)
boolean upSpeed = 1;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600); //Serial comm at 9600 bps
sec1.begin(38400);
sec2.begin(38400);
sec3.begin(38400);
}

void loop() {
// put your main code here, to run repeatedly:
Serial.println("GOING IN");
goIn(2,2,300);
delay(2000);
Serial.println("NOW GOING OUT");
goOut(2,2,700);
delay(2000);
Serial.println("Will continue the loop in 9 secs");
delay(9000);
}

void goIn(byte sec, byte axis, int goal) {
Serial.println("MAKE SURE THAT SPEED RANGE IS 20-80");
delay(1000);
timeElapsed = 0; //Reset time counter
upSpeed = 1;
while (analogRead(pot[sec][axis]) > goal) {
//keep moving
move_A(sec, axis, goal, 0); //Update speed
delay(200); //Check for updated values every 200ms
}
motorOut(sec, axis, 0); //STOP
}

void goOut(byte sec, byte axis, int goal) {
Serial.println("MAKE SURE THAT SPEED RANGE IS 20-80");
delay(1000);
timeElapsed = 0; //Reset time counter
upSpeed = 1;
while (analogRead(pot[sec][axis]) < goal) {
//keep moving
move_A(sec, axis, goal, 1); //Update speed
delay(200); //Check for updated values every 200ms
}
motorOut(sec, axis, 0); //STOP
}

//Movement methods:
void move_A(byte sec, byte axis, int goal, boolean dir) {
updateSpeed();
Serial.print(" Current speed is ");
Serial.println(spd);
delay(10);
//motorC(X,X,XX,1); <--To move OUT
//motorC(X,X,XX,0); <--To move IN
if (dirBool[sec][axis]) {
//Acuator moves out with ForwardM
if (dir) {
//Command received to move out
motorOut(sec, axis, spd);
} else {
//Command received to move IN
motorIn(sec, axis, spd);
}
} else {
//Acuator moves out with BackwardM
if (dir) {
//Command received to move out
motorIn(sec, axis, spd);
} else {
//Command received to move IN
motorOut(sec, axis, spd);
}
}
}

void updateSpeed(){
int index = timeElapsed/updateSpdEvery;
if(index >= spdHDlenght){
timeElapsed=0; //reset the time counter
index=0;
upSpeed = 0; //Stop speed update for this loop reached end of the index
}else if(upSpeed){
spd = spdHD[index];
}
}

void motorOut(byte section, byte axis, byte spd) {
//spd data only to stop a particular motor using spd data=0
switch (section) {
case 1:
if (axis == 1) {
sec1.ForwardM1(address, spd);
} else {
sec1.ForwardM2(address, spd);
}
break;
case 2:
if (axis == 1) {
sec2.ForwardM1(address, spd);
} else {
sec2.ForwardM2(address, spd);
}
break;
case 3:
if (axis == 1) {
sec3.ForwardM1(address, spd);
} else {
sec3.ForwardM2(address, spd);
}
break;
default:
break;
}
}
void motorIn(byte section, byte axis, byte spd) {
switch (section) {
case 1:
if (axis == 1) {
sec1.BackwardM1(address, spd);
} else {
sec1.BackwardM2(address, spd);
}
break;
case 2:
if (axis == 1) {
sec2.BackwardM1(address, spd);
} else {
sec2.BackwardM2(address, spd);
}
break;
case 3:
if (axis == 1) {
sec3.BackwardM1(address, spd);
} else {
sec3.BackwardM2(address, spd);
}
break;
default:
break;
}
}

speedEasing_Timev0.1.ino (4.41 KB)

To rephrase my question, How would you do write a loop that only takes an analog position read at the start and end?