Introduction: Potentiometer Feedback Control Part 2: RF Control of Extended Limit

About: Progressive Automations is your primary source for electric linear actuators, motion control systems and automation accessories. For over a decade, we have supplied various industries with top quality automati…

Welcome to the continuation of the potentiometer feedback actuator control series. In this tutorial we will be implementing wireless RF remote control with our extended limit control loop.

For this tutorial we will be using the following components:

  • 1 xArduino Uno
  • 1 xWASP Motor Driver
  • 1 x DF Robot RF Shield (315MHz)
  • 1 x Remote Wireless Keyfob (315MHz)
  • 1 x Tactile Pushbutton
  • 1 xPS-11 (12VDC / 300W)
  • 1 x USB Cable for Arduino Power

Arduino shields are likely to be compatible with the UNO – in this case the DF Robot RF shield fits perfectly. In this part of the series we have replaced the Arduino Micro(which we used in Part 1) for the UNO ,for this reason only.

Before we get started, please note the following risks and limitations risks associated with setting a soft limit:

1. The saved extended limit is reset to the original full extension limit once the Arduino loses power/reset.

2. This system should not be used in applications where human life or health or significant property value depend on its proper operation.

3. Please note that Progressive Automations is not responsible for user caused error due to improper handling of electric components.

Step 1: Hardware Setup

As we are now using a similar but new system, the hardware setup has changed. We will be using the DF Robot 315MHz RF shield for Arduino. This will stack directly on top of the Arduino UNO.

The schematic diagram does not illustrate the RF module.

The RF receiver module has 8 x tristate address pins which can be programmed via the user with jumpers. In our application we need to remove all 8 jumpers which enable all inputs to be floating. The address of the RF remote ( that we are using is floating as well, allowing the connection to the RF module.

This method that we are using will allow third-parties to be able to control your device with a 315MHz remote with a floating address. Please use caution if following this method directly where other users would be able to control your system.

This device uses a PT2272-Lx version of the PT2272 RF decoder. There are two version of the PT2272 – Latching (Lx) and Momentary (Mx). This latching encoder means that once a signal is received, the decoded output will not change until a different signal has been received.

The RF decode pins D11, D10, D9, D8 will not change unless a different button has been pressed on the RF remote.

The remote has 4 buttons:

  • Lock Symbol = Extend
  • Un-lock Symbol = Retract
  • Lightning Symbol = Stop
  • Bell = Stop

Step 2: Programming

IO on the Arduino:


  • A5 = Pot: Wiper (Blue)
  • 5V = Pot: +5VDC (Yellow)
  • GND = Pot: GND (White)


  • D3 = WASP: Control (White)
  • D5 = WASP: Power (Red)
  • D6 = WASP: GND (Black)


  • D12 = Pins {3,4}
  • GND = Pins {1,2}

On-board LED

  • D13 = Leave disconnected. Indicator light for control

Programming Procedure for the RF Module:

Turn the switch to PROG > Upload program to Arduino > Turn the switch to RUN

Once the code is uploaded you must turn the switch to RUN and operation can begin.

Step 3: Code Definitions

#include <Servo.h>
Servo myservo;         //Servo Object
#define POT A5         //Potentiometer Wiper Feedback
#define SAVE 12       //Pushbutton to save extended limit (Changed 3 to 2)
#define WSP_CNTRL 3   //WASP Control
#define WSP_ENABLE 5   //WASP Enable
#define WSP_GND  6    //WASP Ground (Changed from 11)
#define LED 13

#define BACKWARDS 1000  //Servo value to retract actuator
#define FORWARDS  2000 //Servo value to extend actuator
#define MTR_STOP  1520 //Servo value to stop actuator

#define HOLD_TIME 3000  //Save Button Hold Time

int potValue = 0;       //Potentiometer analog value init

int extendLimit = 1023; //Extension limit is set to maximum
bool limitFlag = false;
int strokeLimit = 1023;         //Set stroke limit to max analog value

bool pbSave = false;            //PushButton - Save Deactive
bool saveFlag = false;          //Flag that activates when the save pushbutton is active
bool ledState = false;

int currentState = 1;           //State machine init
int mtrState = 1520;            //Motor State init

int buttonState;                //the current reading from the input pin
int lastButtonState = LOW;      //the previous reading from the input pin
long lastDebounceTime = 0;       //the last time the output pin was toggled
long previousMillis = 0;        //stores how long button is pressed

long debounceDelay = 3000;    // the debounce time in ms

int D1 = 8;   //The digital output pin 1 of decoder chip(SC2272)
int D2 = 9;   //The digital output pin 2 of decoder chip(SC2272)
int D3 = 10;  //The digital output pin 3 of decoder chip(SC2272)
int D4 = 11;  //The digital output pin 4 of decoder chip(SC2272)

volatile bool rf_code[4];
volatile bool interrupt_flag = 0;

Step 4: Code Edits Part 1

As we are now using a different method of control and have removed a rocker switch, we now need to make code edits. All code edits are highlighted in bold.


Void setup(){
  myservo.attach(WSP_CNTRL); //Attaches the servo on pin 3

  pinMode(POT, INPUT), digitalWrite(POT, LOW); //Initialize potentiometer value to be low
  pinMode(SAVE, INPUT), digitalWrite(SAVE, HIGH);
  pinMode(LED, OUTPUT), digitalWrite(LED, LOW);

  pinMode(WSP_ENABLE, OUTPUT), digitalWrite(WSP_ENABLE, HIGH);
  pinMode(WSP_GND, OUTPUT), digitalWrite(WSP_GND, LOW);

  pinMode(D4, INPUT);  //Initialized to input pin, in order to read the level of the output pins from the decoding chip
  pinMode(D2, INPUT); 
  pinMode(D1, INPUT);  
  pinMode(D3, INPUT);


void loop() {

Step 5: Code Edits Part 2

Input Scan

We have added a function to read the signal from the RFmodule, this function is readCode that requires an addition to the inputScan function.

void inputScan() {
  potFeedback(); //Check potentiometer value
  strokeSave(); //Check to see if the stroke save pushbutton is active

RF Code

In our program rf_code[0] and rf_code[1] correspond to the buttons that extend or retract the actuator. If the user presses one of the two buttons that activate the rf_code[2 or 3] bit the actuator will stop.

void readCode(){
  rf_code[0] = digitalRead(D4); // Extend
  rf_code[1] = digitalRead(D2); // Retract
  rf_code[2] = digitalRead(D1); // Stop
  rf_code[3] = digitalRead(D3); // Stop

Flag Function

There is one major aspect to recognize in the following function – that is the “retract” code of rf_code[0]. If the extend code is not active than the limitFlag is false. This means that to clear the limitFlag , you must retract the actuator.

void flagFunc() {
  //Determine if the potentiometer value is at the user set extended limit
  if (potValue >= extendLimit) limitFlag = true;
  Serial.print("LimitFlag: "), Serial.print(limitFlag), Serial.print("\t\t");
  if (rf_code[0] == false) limitFlag = false;

Step 6: Code Edits Part 3

State Machines

We are now using the input codes from the RF module as a means of control. All necessary changes are outlines in the following code.

void stateSelect() {<br>  Serial.print("Case: "), Serial.print(currentState), Serial.print("\t\t");
  Serial.print("Extend Limit: "), Serial.print(extendLimit), Serial.print("\t\t");
  switch (currentState) {
    case 1: //STOP - Active when the rocker switch is in its neutral position
      mtrState = MTR_STOP; //Turn motor off
      ledState = false;
      if (rf_code[0] == true && saveFlag == false && limitFlag == false) currentState = 2;
      if (rf_code[1] == true && saveFlag == false)currentState = 3;
      if (limitFlag == true) currentState = 1;
      if (rf_code[2] == true | rf_code[3] == true) currentState = 1;
      if (saveFlag == true) currentState = 4;
    case 2: // Extend
      mtrState = FORWARDS; //Set motor to full retract speed
      ledState = false;
      if (rf_code[0] == true && saveFlag == false && limitFlag == false) currentState = 2;
      if (rf_code[1] == true && saveFlag == false)currentState = 3;
      if (limitFlag == true) currentState = 1;
      if (rf_code[2] == true | rf_code[3] == true) currentState = 1;
      if (saveFlag == true) currentState = 4;
    case 3: // Retract
      mtrState = BACKWARDS; //Set motor to full extend speed
      ledState = false;
      if (rf_code[0] == true && saveFlag == false && limitFlag == false) currentState = 2;
      if (rf_code[1] == true && saveFlag == false)currentState = 3;
      if (limitFlag == true) currentState = 1;
      if (rf_code[2] == true | rf_code[3] == true) currentState = 1;
      if (saveFlag == true) currentState = 4;
    case 4: //Limit Save
      mtrState = MTR_STOP; // Turn motor off
      delay(50); // Wait to stabilize potValue
      extendLimit = potValue; //Save the extend limit value to 
      ledState = true; //Turn on LED
      if (rf_code[0] == true && saveFlag == false && limitFlag == false) currentState = 2;
      if (limitFlag == true) currentState = 1;
      if (rf_code[2] == true | rf_code[3] == true) currentState = 1;
      if (rf_code[1] == true && saveFlag == false)currentState = 3;
      if (saveFlag == true) currentState = 4;

Here we are enabling the state machine to perform the extend/retract based on the states of rf_code[0] and rf_code[1]. The state machine then uses the rf_code[2] and rf_code[3] to stop the actuator.

Step 7: Un-Edited Functions

The following functions have been taken directly from Part 1 of this tutorial and have not been edited.

void strokeSave() {<br>  unsigned long currentMillis = millis();
  pbSave = digitalRead(SAVE); //Read Push Button
  if (pbSave != lastButtonState) { 
    lastDebounceTime = millis();
  if ((millis() - lastDebounceTime) > debounceDelay) { //Check to see if the button has been pressed for 3 seconds
    if (pbSave != buttonState) {
      buttonState = pbSave;
    saveFlag = true;
  lastButtonState = pbSave;
  if (pbSave == true) saveFlag = false;
  Serial.print("saveFlag:  "), Serial.print(saveFlag), Serial.print("\n");

Step 8: Conclusion

If you'd like to take a look at our selection of linear actuators, motions control systems and microcontrollers then please visit us at 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 -

Facebook -

YouTube -