Linear actuator position issue

PROBLEM SOLVED

It appears that when the program recognizes

I can't believe that it does recognize that statement.

So, if it takes the arduino 3 seconds to finally reach this piece of "Write" code,

the programmer is doing something horribly wrong.

The thing is, being that this is the saved position, the rod really shouldn't move at all.

That's assuming that the stored position and the current position are the same. That is NOT an assumption I'm willing to make.

Here is my reset PB code and the initial setup code.

When you post ALL of your code, I will read it. Not until then.

http://snippets-r-us.com

Why we don't like snippets.

Weedpharma

Sorry for being new lol. Didn't think you'd actually like to run through my whole code.

Very well then!

Edit: Also, I store the position right before I restart it, mainly for testing purposes, so the rod is in the exact position when it's reloaded.

Hi, You servo motor is not completely matched to the controller, it uses PWM to give hi torque efficient operation.

Check with servocity to see what they recommend. The noise you are hearing is the PWM duty cycle changing as the actuator near it set position. It uses 1kHz frequency so you most certainly would hear it as a squeal.

Tom..... :)

Is an RC signal (servo signal) equivalent to PWM?

Yes, but servo pulse repetition frequency is usually quite low.

jremington: Yes, but servo pulse repetition frequency is usually quite low.

I'm using pin 13 on the arduino MEGA2560. This should send pulses at 980Hz, correct?

This should send pulses at 980Hz, correct?

That would mean that each pulse was less than a millisecond long. You need to do some research on how long a servo pulse typically lasts. It's more than an order of magnitude longer than that.

Hi, [u]Sorry I should say the linear actuator, problem, the squeal.[/u]

The motor is a DC motor and the controller for it has H-Bridge output and uses PWM control. The frequency of the PWM to the motor is set by the actuator controller. So it is different to the PWM from the arduino.

Tom...... :) Also what are your power supply arrangements?

I'm using a 5 wire linear actuator and a motor control board which allows me the control the linear actuator just like a servo using an RC input.

If three of the five wires go to a pot on the actuator, you should be able to read the pot value, map that to the actuator control value and position, so you will know the current actuator position.

TomGeorge: Hi, [u]Sorry I should say the linear actuator, problem, the squeal.[/u]

The motor is a DC motor and the controller for it has H-Bridge output and uses PWM control. The frequency of the PWM to the motor is set by the actuator controller. So it is different to the PWM from the arduino.

Tom...... :) Also what are your power supply arrangements?

But the motor control board is meant to run 1kHz frequency linear actuators so theoretically there shouldn't be a problem there.

I'm using a 0-30V 0-5A variable DC power supply for testing purposes at this point. I'm just running the actuator at 7V for testing as I do not need more and I believe it can be operated between 6-12V.

PaulS: That would mean that each pulse was less than a millisecond long. You need to do some research on how long a servo pulse typically lasts. It's more than an order of magnitude longer than that.

I will look into this.

zoomkat: If three of the five wires go to a pot on the actuator, you should be able to read the pot value, map that to the actuator control value and position, so you will know the current actuator position.

Hmm. Maybe I will try messing around with that. I'll try mapping the analog position to a value between 1000 to 2000 (since I can only write to my linear actuator in micro seconds) and see how that works.

So I tried ZoomKat’s suggestion and I really like the idea because it’s much simpler than the multiplication I was trying to do. Also, I don’t need to save the position by doing this. That being said, I’m having an issue because my AnalogRead is giving me really funky values. Between the actuators fully retracted and fully extended I’m getting values between 650 (fully retracted) to about 100-200 (fully extended).

The LAC control board supplies 3.3V to the potentiometer if that changes anything.

Can anybody check my code and help me out please?

Thanks.

#include <EEPROM.h>
#include <Servo.h>
 
// Set digital pin numbers:
const int servoPinA = 8;  // The number of the ServoA pin
const int servoPinB = 6; // The number of the ServoB pin
const int actuatorpinA = 13; // The number of the actuatorA pin
const int ButtonForward = 12;  // The number of the fwd. Pushbutton pin
const int ButtonReverse = 7; // The number of rev. Pushbutton pin
const int ButtonMotorToggle = 10; // Motor toggle push button
const int ButtonReset = 11;
const int ActuatorPos = 0; //Potentiometer wiper
 
int ButtonStateFwd;  // Variable for reading the pushbutton status
int ButtonStateRev;
int ButtonStateToggle;
int RESET;
int timer1000 = 1000;
int timer1500 = 1500;
int lastfwdpress;
int lastrevpress;
int lastresetpress;
int posA;
int posB;
int posC;
int AnalogposC = analogRead(ActuatorPos);
float posCmicro;
 
int readposA = 99;
int readposB = 100;
 
int servoNum = 0; // Variable to select servo to be controlled

Servo servoA;  // Create servo object to control a servo
Servo servoB;
Servo actuatorA;
 
void setup() {
  Serial.begin(9600); // initialize serial
  delay(50);
 
  pinMode(ButtonForward, INPUT);  // initialize the pushbutton pin as an input
  pinMode (ButtonReverse, INPUT);  // initialize the pushbutton pin as an input
  pinMode (ButtonMotorToggle, INPUT);
  pinMode (ButtonReset, INPUT);
  pinMode (servoPinA, OUTPUT);
  pinMode (servoPinB, OUTPUT);
  pinMode (actuatorpinA, OUTPUT);
 
  posA = EEPROM.read(readposA);  // Variable to store servoA's position
  posB = EEPROM.read(readposB); // Variable to store servoB's position
  AnalogposC = analogRead(ActuatorPos);
  posCmicro = map(AnalogposC, 0, 1023, 1000, 2000);
  posC = map(posCmicro, 1000, 2000, 0, 180);
 
  Serial.print('\n');
  Serial.println("posA from EEPROM:");
  Serial.println(posA);
  Serial.println("posB from EEPROM:");
  Serial.println(posB);
  Serial.println("posC (microseconds):");
  Serial.println(posCmicro);
  float voltage = AnalogposC * (3.3 / 1023.0);
  Serial.println("actuatorA Pot Position (0 to 1023):");
  Serial.println(AnalogposC);
  Serial.println("actuatorA Pot Reference Voltage (0 to 3.3V):");
  Serial.println(voltage);

  servoA.write(posA);
  servoB.write(posB);
  actuatorA.writeMicroseconds(posCmicro);
  servoA.attach(8);  // attaches servoA to pin 8
  servoB.attach(6); // attaches servoB to pin 6
  actuatorA.attach(13, 1000, 2000); // attaches linear actuator A to pin 13
 
  Serial.print("Servo Selected:");
  Serial.print(servoNum);
  Serial.print('\n');
  Serial.println("servoA Starting Angle:");
  Serial.println(posA);
  Serial.println("servoB Starting Angle:");
  Serial.println(posB);
  Serial.println ("actuatorA Starting Angle (Micro Seconds):");
  Serial.println(posCmicro);
}
 
void loop() {
  // read the state of the pushbutton value:
  ButtonStateFwd = digitalRead(ButtonForward);
  ButtonStateRev = digitalRead(ButtonReverse);
  ButtonStateToggle = digitalRead(ButtonMotorToggle);
  RESET = digitalRead(ButtonReset);
 
  if (ButtonStateToggle == HIGH) {
    servoNum = servoNum + 1;
    Serial.print('\n');
    Serial.print("Servo Selected:");
    Serial.print(servoNum);
    
    if (servoNum == 4) {
      servoNum = 1;
      Serial.print('\n');
      Serial.print("Servo Selected:");
      Serial.print(servoNum);
    }
    delay(1500);
  }
 
  if (ButtonStateFwd == LOW) {
    lastfwdpress = millis(); // Button not pressed set so reset clock
  }
 
    if (ButtonStateRev == LOW) {
    lastrevpress = millis(); // Button not pressed set so reset clock
  }
 
  if ((millis() - lastfwdpress >= timer1000) && (servoNum == 1) && (ButtonStateFwd == HIGH))
  {
    posA += 1;
    delay(5);
    servoA.write(posA);
    Serial.print('\n');
    Serial.print("servoA Angle:");
    Serial.print(posA);
    delay(15);
 
    if (posA >= 176) {
      posA = 175;
      delay(15);
    }
  }
 
  if ((millis() - lastrevpress >= timer1000) && (servoNum == 1) && (ButtonStateRev == HIGH))
  {
    posA -= 1;
    delay(5);
    servoA.write(posA);
    Serial.print('\n');
    Serial.print("servoA Angle:");
    Serial.print(posA);
    delay(15);
 
    if (posA <= 4) {
      posA = 5;
      delay(15);
    }
  }
 
  if ((millis() - lastfwdpress >= timer1000) && (servoNum == 2) && (ButtonStateFwd == HIGH))
  {
    posB += 1;
    delay(5);
    servoB.write(posB);
    Serial.print('\n');
    Serial.print("servoB Angle:");
    Serial.print(posB);
    delay(15);
 
    if (posB >= 176) {
      posB = 175;
      delay(5);
    }
  }
 
  if ((millis() - lastrevpress >= timer1000) && (servoNum == 2) && (ButtonStateRev == HIGH))
  {
    posB -= 1;
    delay(5);
    servoB.write(posB);
    Serial.print('\n');
    Serial.print("servoB Angle:");
    Serial.print(posB);
    delay(5);
 
    if (posB <= 4) {
      posB = 5;
      delay(5);
    }
  }
 
  if ((millis() - lastfwdpress >= timer1000) && (servoNum == 3) && (ButtonStateFwd == HIGH))
  {
    posCmicro += 25; // increment 10 degrees
    delay(5);
    actuatorA.writeMicroseconds(posCmicro);
    Serial.print('\n');
    Serial.print("actuatorA Angle (microseconds):");
    Serial.println(posCmicro);
    AnalogposC = analogRead(ActuatorPos);
    Serial.print("actuatorA Analog Reading:");
    Serial.println(AnalogposC);
    delay(500);
 
    if (posCmicro >= 2001) {
      posCmicro = 2000;
      Serial.print('\n');
      Serial.print("actuatorA Angle (microseconds):");
      Serial.println(posCmicro);
      delay(1000);
      delay(5);
    }
  }
 
  if ((millis() - lastrevpress >= timer1000) && (servoNum == 3) && (ButtonStateRev == HIGH))
  {
    posCmicro -= 25; // decrement 10 degrees
    delay(5);
    actuatorA.writeMicroseconds(posCmicro);
    Serial.print('\n');
    Serial.print("actuatorA Angle (microseconds):");
    Serial.println(posCmicro);
    AnalogposC = analogRead(ActuatorPos);
    Serial.print("actuatorA Analog Reading:");
    Serial.println(AnalogposC);
    delay(500);
 
    if (posCmicro <= 999) {
      posCmicro = 1000;
      Serial.print('\n');
      Serial.print("actuatorA Angle (microseconds):");
      Serial.println(posCmicro);
      delay(1000);
    }
  }
 
   if (posA <= 4) {
      posA = 5;
      Serial.print('\n');
      Serial.print("servoA Angle:");
      Serial.print(posA);
      delay(1000);
    }
 
  if (posA >= 176) {
      posA = 175;
      Serial.print('\n');
      Serial.print("servoA Angle:");
      Serial.print(posA);
      delay(5);
    }
    
   if (posB <= 4) {
      posB = 5;
      Serial.print('\n');
      Serial.print("actuaorA Angle (degrees):");
      Serial.print(posB);
      delay(1000);
    }
 
  if (posB >= 176) {
      posB = 175;
      Serial.print('\n');
      Serial.print("actuaorA Angle (degrees):");
      Serial.print(posB);
      delay(1000);
    }
    
  if (posCmicro <= 999) {
      posCmicro = 1000;
      Serial.print('\n');
      Serial.print("actuatorA Angle (microseconds):");
      Serial.println(posCmicro);
      delay(1000);
    }
 
  if (posCmicro >= 2001) {
      posCmicro = 2000;
      Serial.print('\n');
      Serial.print("actuatorA Angle (microseconds):");
      Serial.println(posCmicro);
      delay(1000);
    }
 
  if (RESET == LOW) {
    lastresetpress = millis(); // Button not pressed set so reset clock
  }
 
  if ((millis() - lastresetpress >= timer1500) && (RESET == HIGH))
  {
    readposA = 99;
    readposB = 100;
    posA = servoA.read();
    posB = servoB.read();
    AnalogposC = analogRead(ActuatorPos);
    EEPROM.put(readposA, posA);
    delay(5);
    EEPROM.put(readposB, posB);
    delay(5);
    Serial.print('\n');
    Serial.print("servoA Angle Saved At:");
    Serial.println(posA);
    Serial.print("servoB Angle Saved At:");
    Serial.println(posB);
    Serial.print("actuatorA Analog Position:");
    Serial.println(AnalogposC);
    Serial.print("actuatorA Angle (microseconds):");
    Serial.println(posCmicro);
    Serial.println("Positions Saved, System Ready for Restart");
    delay(2000);
  }
}

Bump

Hi, Can you measure with a DMM the actual position volts you are getting from the actuator, in fully extended and retracted positions please?

Tom... :)

TomGeorge:
Hi,
Can you measure with a DMM the actual position volts you are getting from the actuator, in fully extended and retracted positions please?

Tom… :slight_smile:

It ranges from about 100mV (fully retracted) to 3.25V (fully extended).

The analog reading is completely random.. No pattern and have only seen it range by about a value of 500.

If the arduino is to read the pot referenced below, you will need to connect the wiper wire to the arduino analog input pin, and one of the remaining pot wires to the arduino +5v, and the remaining pot wire to the arduino ground.

MikeC93: I'm having an issue because my AnalogRead is giving me really funky values. Between the actuators fully retracted and fully extended I'm getting values between 650 (fully retracted) to about 100-200 (fully extended).

Nothing odd about that 3.3V = 680 counts or so and there's no reason whatever to expect the motion range to use the whole wiper range (in fact its never done because of the variability in potentiometer track manufacture).

MarkT: Nothing odd about that 3.3V = 680 counts or so and there's no reason whatever to expect the motion range to use the whole wiper range (in fact its never done because of the variability in potentiometer track manufacture).

That makes a little bit of sense why the range is low, but the counts are changing directions too like it's floating.

As zoomkat said, maybe I need to supply the voltage from the arduino so the arduino knows it's relative position. Or maybe I need to tie to negative to the arduino ground, even though the power ground is tied to the arduino ground.

The motor controller supplies 3.3V to the potentiometer leads so I'm not sure if I can apply it externally.

I will give it a try.