Monitoring Load Feedback of an Actuator
by Progressive Automations in Circuits > Arduino
12239 Views, 142 Favorites, 0 Comments
Monitoring Load Feedback of an Actuator

In this Instructable, we'll be learning how to monitor the amount of current that an actuator is using, so that you can tell how much force it is applying. This is a more advanced project, requiring in-depth coding and calibrating.
The programming we will be doing today will cover debouncing of switches through two methods, the monitoring of an analog input, and the use of functions.
First we will wire the circuit together, then go over the coding, and finish by calibrating the code to suit your application.
Parts required:
- 1x Megamoto
- 1x Linear actuator
- 1x Arduino Uno
- 1x 12V power supply
Let's get started!
Wiring



The wiring part of this project is attaching the motor controller to the Arduino, and adding two buttons to move the actuators.
Do the following:
1) Plug the MegaMoto shield into the Arduino
2) Connect a wire from the BAT+ terminal to the Vin pin on the Arduino. Since it is a shield, the GNDs are already connected
3) Connect your actuator to the A and B terminals
4) Connect 12V to BAT+, and GND to BAT-
5) Verify the jumper settings on the MegaMoto. See here for detailed instructions on each jumper.
For the buttons:
1) Wire a button between an unused pin and GND, so that when you push the button the pin is pulled LOW
2) Do the same with a second button
On to coding!
Basic Coding
The goal of this code is to check the buttons, and depending on the state of them move the motor to extend or retract. Once the motor is extending, the current is constantly monitored, to see if it surpasses the max current limit. If it has passed the limit, then the motor stops, and will no longer extend, until you retract it.
Since motors have a large current spike when they start, the code has a small delay before it starts taking current readings. This can be changed depending on the motor. The value to change is firstfeedbacktimedelay.
The code also monitors for when the actuators have reached the limit switches. When the current drops to 0, the actuator knows that it has reached the limits. The current sensor will only stop the motor if it has read 0 a few times in a row, else a false reading would stop the motor mid stroke.
The code is attached, the code pasted below has more detailed comments. The code uses lots of functions, so that each part can be changed individually.
/* Code to monitor the current amp draw of the actuator, and to cut power if it rises above a certain amount. Written by Progressive Automations August 19th, 2015 Hardware: - RobotPower MegaMoto control boards - Arduino Uno - 2 pushbuttons */ const int EnablePin = 8; const int PWMPinA = 11; const int PWMPinB = 3; // pins for Megamoto const int buttonLeft = 4; const int buttonRight = 5;//buttons to move the motor const int CPin1 = A5; // motor feedback int leftlatch = LOW; int rightlatch = LOW;//motor latches (used for code logic) int hitLimits = 0;//start at 0 int hitLimitsmax = 10;//values to know if travel limits were reached long lastfeedbacktime = 0; // must be long, else it overflows int firstfeedbacktimedelay = 750; //first delay to ignore current spike int feedbacktimedelay = 50; //delay between feedback cycles, how often you want the motor to be checked long currentTimefeedback = 0; // must be long, else it overflows int debounceTime = 300; //amount to debounce buttons, lower values makes the buttons more sensitive long lastButtonpress = 0; // timer for debouncing long currentTimedebounce = 0; int CRaw = 0; // input value for current readings int maxAmps = 0; // trip limit bool dontExtend = false; bool firstRun = true; bool fullyRetracted = false;//program logic void setup() { Serial.begin(9600); pinMode(EnablePin, OUTPUT); pinMode(PWMPinA, OUTPUT); pinMode(PWMPinB, OUTPUT);//Set motor outputs pinMode(buttonLeft, INPUT); pinMode(buttonRight, INPUT);//buttons digitalWrite(buttonLeft, HIGH); digitalWrite(buttonRight, HIGH);//enable internal pullups pinMode(CPin1, INPUT);//set feedback input currentTimedebounce = millis(); currentTimefeedback = 0;//Set initial times maxAmps = 15;// SET MAX CURRENT HERE }//end setup void loop() { latchButtons();//check buttons, see if we need to move moveMotor();//check latches, move motor in or out }//end main loop void latchButtons() { if (digitalRead(buttonLeft)==LOW)//left is forwards { currentTimedebounce = millis() - lastButtonpress;// check time since last press if (currentTimedebounce > debounceTime && dontExtend == false)//once you've tripped dontExtend, ignore all forwards presses { leftlatch = !leftlatch;// if motor is moving, stop, if stopped, start moving firstRun = true;// set firstRun flag to ignore current spike fullyRetracted = false; // once you move forwards, you are not fully retracted lastButtonpress = millis();//store time of last button press return; }//end if }//end btnLEFT if (digitalRead(buttonRight)==LOW)//right is backwards { currentTimedebounce = millis() - lastButtonpress;// check time since last press if (currentTimedebounce > debounceTime) { rightlatch = !rightlatch;// if motor is moving, stop, if stopped, start moving firstRun = true;// set firstRun flag to ignore current spike lastButtonpress = millis();//store time of last button press return; }//end if }//end btnRIGHT }//end latchButtons void moveMotor() { if (leftlatch == HIGH) motorForward(255); //speed = 0-255 if (leftlatch == LOW) motorStop(); if (rightlatch == HIGH) motorBack(255); //speed = 0-255 if (rightlatch == LOW) motorStop(); }//end moveMotor void motorForward(int speeed) { while (dontExtend == false && leftlatch == HIGH) { digitalWrite(EnablePin, HIGH); analogWrite(PWMPinA, speeed); analogWrite(PWMPinB, 0);//move motor if (firstRun == true) delay(firstfeedbacktimedelay); // bigger delay to ignore current spike else delay(feedbacktimedelay); //small delay to get to speed getFeedback(); firstRun = false; latchButtons();//check buttons again }//end while }//end motorForward void motorBack (int speeed) { while (rightlatch == HIGH) { digitalWrite(EnablePin, HIGH); analogWrite(PWMPinA, 0); analogWrite(PWMPinB, speeed);//move motor if (firstRun == true) delay(firstfeedbacktimedelay);// bigger delay to ignore current spike else delay(feedbacktimedelay); //small delay to get to speed getFeedback(); firstRun = false; latchButtons();//check buttons again }//end while dontExtend = false;//allow motor to extend again, after it has been retracted }//end motorBack void motorStop() { analogWrite(PWMPinA, 0); analogWrite(PWMPinB, 0); digitalWrite(EnablePin, LOW); firstRun = true;//once the motor has stopped, reenable firstRun to account for startup current spikes }//end stopMotor void getFeedback() { CRaw = analogRead(CPin1); // Read current if (CRaw == 0 && hitLimits < hitLimitsmax) hitLimits = hitLimits + 1; else hitLimits = 0; // check to see if the motor is at the limits and the current has stopped if (hitLimits == hitLimitsmax && rightlatch == HIGH) { rightlatch = LOW; // stop motor fullyRetracted = true; }//end if else if (hitLimits == hitLimitsmax && leftlatch == HIGH) { leftlatch = LOW;//stop motor hitLimits = 0; }//end if if (CRaw > maxAmps) { dontExtend = true; leftlatch = LOW; //stop if feedback is over maximum }//end if lastfeedbacktime = millis();//store previous time for receiving feedback }//end getFeedback
Downloads
Advanced Coding
Now that you've seen the code, we will go over individual sections to give deeper explanations.
First, we'll look at a section of code within the latchButtons() function. We're going to look at the button debouncing. When the left button is pushed, the time since the last button press must be calculated. This is done by using the last value that was stored, and calling the millis() function to check the current time. Once we know that the time is greater then our debounce time, the function then checks if the actuator is allowed to extend. If both of these conditions are met, the function can continue, and do all the things related to the button press.
if (digitalRead(buttonLeft)==LOW)//left is forwards { currentTimedebounce = millis() - lastButtonpress;// check time since last press if (currentTimedebounce > debounceTime && dontExtend == false)//once you've tripped dontExtend, ignore all forwards presses { leftlatch = !leftlatch;// if motor is moving, stop, if stopped, start moving firstRun = true;// set firstRun flag to ignore current spike fullyRetracted = false; // once you move forwards, you are not fully retracted lastButtonpress = millis();//store time of last button press return; }//end if }//end btnLEFT
This next section is the while loop within the motorForward() function. The part to look at here is the two delays. The loop starts by enabling the motor controller, and starting the motor. If it is the first run though the loop, there is a bigger delay. This bigger delay is to ignore the current spike that comes with the starting of a motor. When setting this delay, be careful not to set it too big, because there is no control during it. If the motor is stuck for any reason, it will not be able to be stopped until this delay is over. If it is not the first run, there is a much smaller delay.
Once the motor is moving, getFeedback() is used to check the current sensor. firstRun is turned off, so that the next time through the loop it takes the small delay, rather then the big one. And finally, the buttons are checked to see what new action should be taken.
while (dontExtend == false && leftlatch == HIGH) { digitalWrite(EnablePin, HIGH); analogWrite(PWMPinA, speeed); analogWrite(PWMPinB, 0);//move motor if (firstRun == true) delay(firstfeedbacktimedelay); else delay(feedbacktimedelay); //small delay to get to speed getFeedback(); firstRun = false; latchButtons(); }//end while
The next sections are all in the getFeedback() routine. The routine starts by reading the analog pin connected to the sensor, then acts accordingly.
The first thing that is checked is if the motor is at it's limits. The code knows when the motor is at the limits when the current reading is 0. Sometimes, there is a false reading, so we need to set up a counter, so that the motor only stops when it is actually at the limits. This piece of code has to count up to the hitLimitsmax before the motor will stop. If it counts less then that, the counter resets.
if (CRaw == 0 && hitLimits < hitLimitsmax) hitLimits = hitLimits + 1; else hitLimits = 0; // check to see if the motor is at the limits and the current has stopped
This next part is just after the hit limits. If the motor is moving forwards when it reached the limit, it turns off the rightlatch. If it was moving backwards, it turns off the leftlatch. The code is the same for leftlatch.
if (hitLimits == hitLimitsmax && rightlatch == HIGH) { rightlatch = LOW; hitLimits = 0; }//end if
Finally, the current limit is checked against it's maximum. If it is over, the leftlatch is turned off, and the motor is no longer allowed to extend. To reenable extension, the motor must be reversed.
if (CRaw > maxAmps) { dontExtend = true; leftlatch = LOW; //stop if feedback is over maximum }//end if
Now that we've gone over the code, we can customize it for your needs.
Calibration
There are a few modifications that you can do to make this code more suited to your application.
The first thing to do is set the max current limit. To find out what value you want to set it at, you need to do some testing. The easiest way is to use the Arduino example code "AnalogReadSerial", and look at the serial monitor to see what the feedback is from the motor. Once you know the value that you want to stop at, you can set it in the void setup() routine, by changing the maxAmps value.
Another option is to make the limit adjustable. If you attach a potentiometer to the Arduino on one of the analog pins, you can vary the max amps by varying the potentiometer. To do so, all you need to add is a declaration at the beginning to set the potentiometer pin, like so:
const int CPin1 = A5; // motor feedback const int Pot = 4; // potentiometer for feedback adjustment
Once that is there, you need to put "pinMode(Pot, INPUT);" into the void setup() routine. Once that's there, you can use the analogRead() to set the limit. Every time the code loops, the max amperage will be updated. It would look like this:
void loop(){ maxAmps = analogRead(Pot); latchButtons();//check buttons, see if we need to move moveMotor();//check latches, move motor in or out }//end main loop
Another setting you can edit is the debounce timers, to make the buttons more or less responsive. The value to change is debounceTime, in the beginning of the program. If you make the value higher, the button can be pressed slower, without it being registered twice. If the value is too high, you have to wait a long time before it will register the button press again. If the value is too low, and you press the button slowly, it may register twice, and start/stop the motor immediately. Keeping the value between 300 and 1000 is a good range.
int debounceTime = 300; //amount to debounce long lastButtonpress = 0; // timer for debouncing long currentTimedebounce = 0;
The last thing to change is the hitLimitsmax variable. This variable is used to tell when the actuator is at the fully retracted or fully extended position. When the actuator is in one of those positions, the current monitor will be reading 0 amps. By adjusting the hitLimitsmax variable, you can set how long it takes for the actuator to realize that it is at the limits.
Ideally, the limit would be able to be set to 1. As soon as the feedback is 0, the actuator will stop. If you have a low amperage actuator (~1A), due to the fluctuations in the current reading, the current may be read as 0 even when the actuator is moving. This would cause the actuator to stop randomly. To fix this, the hitLimitsmax value is set so that the sensor needs to read 0 amps X amount of times before it will stop. If you have a higher current (>5 Amps) actuator, this value can be lower. I have it set at 10, so that the actuator will take 0.5 seconds to stop once it hits the limits. It will take 0.5 seconds because the feedbacktimedelay is 50 milliseconds, and it loops 10 times.
Conclusion

In this Instructable, we learned how to monitor the current of an actuator so that we could know how much pressure the actuator is applying. This could be used as a safety system, so that if your actuator is pressing too hard in your application, it knows to automatically stop moving so it protects itself and everything around it. You can use the principles we learned here to add any analog sensor to your actuator project.
If you'd like to take a look at our selection of linear actuators, motions control systems and microcontrollers then please visit us at www.progressiveautomations.com for all your actuator needs! We can even build a custom actuator or control system for you based on your own custom specifications with the help of our highly trained staff of engineers. You can learn more about the custom order process right here!
Follow, Like and Subscribe!
Twitter - twitter.com/ProgAutoInc
Facebook - www.facebook.com/ProgressiveAutomations
Youtube - www.youtube.com/user/MrActuators