Hi, I am quite new to Arduino and programming and desperately need help. I have a linear actuator (50mm 35:1 6V RC Control) and a force sensor. So using the sweep code on Arduino, the linear actuator moves which is great! I also know how to programme the force sensor. However, what I need help is merging the two codes together, and I want the linear actuator to move until it reaches a certain force- that I don't know how to do it or even where to start! I would really appreciate any help given!!
Below is the code I am using for the linear actuator
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
This is the code I am using for the force sensor:
int pressurePin = A0;
int force;
void setup() {
Serial.begin(9600);
}
void loop() {
force = analogRead(pressurePin);
Serial.println(force);
delay(100);
}
Move the actuator position 1 degree. Wait a moment for the actuator finish the move. Read the force sensor. If the force is equal to or over the force, stop, else increment the position and repeat.
while (read_force() < some_value) {
myservo.write(pos++);
delay(100);
}
You would need to write the function read_force().
We strongly recommend working through the examples that come with the Arduino IDE to learn the programming language and special features of the boards.
Here is a simple sketch that will move the servo until the ADC output counts are equal or more than 500. Replace 500 with the ADC counts that equal the required force. Find the ADC counts experimentally. Once the force is applied the sketch will not move the servo any further. Tested on my Uno with a servo and FSR.
#include <Servo.h>
Servo myServo;
byte forcePin = A0;
byte servoPin = 9;
byte ledPin = 13;
byte servoPos = 0;
int countsFor10 = 500; // find how many ADC counts = 10 force units
boolean forceApplied = false;
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
myServo.attach(servoPin);
}
void loop()
{
if (forceApplied == false) // only run once until force is applied
{
while (analogRead(forcePin) <= countsFor10)
{
myServo.write(servoPos);
delay(100); // change delay to suit
servoPos++;
}
forceApplied = true;
digitalWrite(ledPin, HIGH);
}
}
It looks like these examples are tangled a bit. Good advice, and it ‘works’.
While there is nothin wrong, other than they can execute the while() loop (faster than the actuator can move to each incremented position) until the sensor is triggered, then stop the actuator motor.
This is effectively an open-loop system.
The delay() works by minimising that overshoot effect, but is not really the best way to resolve it, and may stress/draw excess current with the perpetual states of starting & stopping during the motion cycle.
The closed-loop solution is a bit more complex, because you need to know where the actuator is, while making the next step decision with pressure.
Measuring pressure before making each step, rather than running the motor until reaches the setpoint.
This is all a bit academic, but will make the system tighter, and eliminate delay(), so you can thread other activity around the pressure/motion activity.
One of the problems with motors, especially with gearing, is that when you turn off the power to the motor, the motor continues to spin down. think taking your foot off the gas. you can coast for a long distance.
if you run the motor and wait until you reach the force, and then send a signal to stop the motor, then you have a good chance that the delays of sensing and delays of physical motor movement can have you run past your desired point.
You may want to 'take up the slack' and run the motor until you reach, say 10% of force. and then do the stop-measure-move....
or, if your motor has variable speed to it, you can start to slow down as you approach the desired force.
lastly, I used to do HVAC and the motors we used to move duct dampers were current limited. they could move a damper that was not restricted, but as the damper came to a close,the power to move the damper increased, so by watching the power to the motor, we knew what it was doing and would shut it off to stop the movement and limit possible damage.
@dave-in-nj, Good points.
The actuator which the OP is using looks like a ‘hobby servo’ (Firgelli etc) to the controller. So progressive control is a bit harder to achieve.
The 10% or other margin-point idea - has merit, but it will always be a tradeoff unless you have - also as mentioned - direct proportional control (e.g. H-bridge PWM) of a DC motor.# Creating your own closed-loop servo with the pressure sensor.
Firgelli (and others) make the same actuators without the internal electronics.
I am obvioulsy baseing my notes on my experiance.
a duct damper can move a long distance before having any resistance.
if one were do the step/stop/check/step it would take huge amounts of time.
Also, I do not like to start and stop motors if it is unnecessary.
obviously, the application will dictate the best control.
my intention is to offer a more rounded set of information
I do hope that it was not so far off that it was confusing.
When you get it sorted, post a video and code - i for one would love to see the action!
It’s always pleasing to see micros controlling real world gadgets,