Monitoring Actuator Current with an LCD Screen

In this blog post we will be learning how to monitor the current of a linear actuator using an LCD screen. Using an LCD screen is a great option because it lets you see just how much current the actuator is using and also lets you adjust the current limits as needed. First we will go over how to how to use the LCD board and its buttons and how to integrate it with out Arduino microcontroller. Then we'll go over how to write and set values on to the LCD which will allow us to see whats its doing in real time.

For this project we will be using:

Take the LCD screen and you'll see there are six buttons on it; Up, Down, Left, Right, Select and Reset. For this project we will be using the four directional buttons. The Up and Down buttons will be controlling the current limit while the Left and Right buttons will be controlling the actuator. One of the nice things about this LCD board is that all six buttons are put through a digital to analog converter so that they all only take up one pin. The only downside to this is that you need to calibrate each button individually.

IMG_0355

The best way to do this is to use the Arduino AnalogReadSerial example code to see the value of each button press. There are six values that you need to be able to see; the five values of the buttons and the value that you get when you don't press any buttons. Once you get the readings of the button presses you'll want to confirm they are all working by using the provided code below. Some extra comments have been added to it to explain what every line is for. Once everything is tested and all the values are recorded we'll be able to go on to the next step

//Sample using LiquidCrystal library

#include <LiquidCrystal.h>

/*******************************************************

This program will test the LCD panel and the buttons
Mark Bramwell, July 2010

********************************************************

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //rs, enable, d4,d5,d6,d7

// define some values used by the panel and buttons
int lcd_key     = 0;//which button was pressed
int adc_key_in  = 0;//what was the input of the DAC

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5 //set button return values

const int btnup = 130;
const int btndown = 306;
const int btnleft = 479;
const int btnright = 0;
const int select = 720;
const int none = 127; //Put your button values here
const int threshold = 2; //Put threshold value here

int read_LCD_buttons()
{
 adc_key_in = analogRead(A0);      // read the value from the sensor 
if (adc_key_in > none - threshold && adc_key_in < none + threshold)   return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
if (adc_key_in > btnup - threshold && adc_key_in < btnup + threshold)   return btnUP;
if (adc_key_in > btndown - threshold && adc_key_in < btndown + threshold)   return btnDOWN;
if (adc_key_in > btnleft - threshold && adc_key_in < btnleft + threshold)   return btnLEFT;
if (adc_key_in > btnright - threshold && adc_key_in < btnright + threshold)   return btnRIGHT;
if (adc_key_in > select - threshold && adc_key_in < select + threshold)   return btnSELECT;

//if else statements could be used, but since each statement uses return, you don't lose speed for using all if's

 return btnNONE;  // when all others fail, return this...
}//end read_LCD_Buttons

void setup()
{
 lcd.begin(16, 2);              // start the library
 lcd.setCursor(0,0); // Set cursor to upper left corner
 lcd.print("Push the buttons"); // print a simple message
}//end setup
 
void loop()
{
 lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over
 lcd.print(millis()/1000);      // display seconds elapsed since power-up

 lcd.setCursor(0,1);            // move to the begining of the second line
 lcd_key = read_LCD_buttons();  // read the buttons

 switch (lcd_key)               // depending on which button was pushed, we perform an action
 {
   case btnRIGHT:
     {
     lcd.print("RIGHT ");
     break;
     }
   case btnLEFT:
     {
     lcd.print("LEFT   ");
     break;
     }
   case btnUP:
     {
     lcd.print("UP    ");
     break;
     }
   case btnDOWN:
     {
     lcd.print("DOWN  ");
     break;
     }
   case btnSELECT:
     {
     lcd.print("SELECT");
     break;
     }
     case btnNONE:
     {
     lcd.print("NONE  ");
     break;
     }
 }//end switch

}//end loop

Now we'll need to do some wiring with our MegaMoto. Connect your power supply to the BAT +/- terminals and connect the actuator to the MOTA and MOTB terminals. Then set the MegaMoto pins like so: Enable - 13, PWMA - 11, PWMB - 3 and Sensor - A5. With this wiring the Left button should make our actuator extend while the Right button should make it retract. If for some reason the directions are reversed just switch the MOTA and MOTB connections.

IMG_0359

With the buttons configured we'll add the LCD program with four new functions. These functions are Read_LCD_buttons(), updateTrip(), updateLCD() and printFeedback(). Read_LCD_buttons() is the same as the text program and monitors the status of the button presses from the LCD. UpdateTrip() monitors the results of the Up and Down buttons as well as changing the amp limit. UpdateLCD() is the primary writing function and writes all the new information to the screen while PrintFeedback() shows the current amperage on the screen. Now to test everything using the code below.

/*  Code to display the current amp draw of the actuator, and to cut power if it
  rises above a certain amount.

  Written by Progressive Automations
  July 16th, 2015

  Hardware:
  - RobotPower MegaMoto control boards
  - LCD shield
  - Arduino Uno
 */
#include <LiquidCrystal.h>


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);// select the pins used on the LCD panel

// define some values used by the panel and buttons
#define btnRIGHT  1
#define btnUP     2
#define btnDOWN   3
#define btnLEFT   4
#define btnSELECT 5
#define btnNONE   0

int lcd_key     = 0;
int adc_key_in  = 0;//value to read LCD button input

const int btnup = 130;
const int btndown = 306;
const int btnleft = 479;
const int btnright = 0;
const int select = 720;
const int none = 1023;
const int threshold = 2;//Analog values for LCD buttons

const int EnablePin = 13;
const int PWMPinA = 11;
const int PWMPinB = 3; // pins for Megamoto

const int CPin1 = A5;  // motor feedback

int button = 0;//value to read LCD buttons

int leftlatch = LOW;
int rightlatch = LOW;//motor latches

int hitLimits = 0;
int hitLimitsmaxfront = 10;
int hitLimitsmaxback = 5;//values to know if travel limits were reached

long lastfeedbacktime = 0;
int firstfeedbacktimedelay = 750; //first delay to ignore current spike
int feedbacktimedelay = 50; //delay between feedback cycles
long currentTimefeedback = 0;

int debounceTime = 500; //amount to debounce
long lastButtonpress = 0; // timer for debouncing
long currentTimedebounce = 0;

int CRaw = 0;      // raw A/D value

int maxAmps = 0; // trip limit

long currentTimetrip = 0;
long lastUpdate = 0;
int updateTime = 100;//how fast can trip values update

bool dontExtend = false;
bool firstRun = true;//program logic

char* title[] = {"  PROGRESSIVE", "  AUTOMATIONS"};        //Power on title

void setup()
{
  Serial.begin(9600);

  pinMode(EnablePin, OUTPUT);
  pinMode(PWMPinA, OUTPUT);
  pinMode(PWMPinB, OUTPUT);//Set motor outputs

  pinMode(CPin1, INPUT);//set feedback input

  lcd.begin(16, 2);// start the library
  lcd.setCursor(0, 0), lcd.print(title[0]), lcd.setCursor(0, 1), lcd.print(title[1]); //Print title
  delay(2000);//show title for 2 seconds

  currentTimetrip = millis();
  currentTimedebounce = millis();
  currentTimefeedback = 0;//Set initial times

  lcd.setCursor(0, 0);
  lcd.print("Amps Feedback"); // print the menu message

  updateLCD(); //write new values to the screen

}//end setup

void loop()
{
  //Serial.println("Main loop");

  updateTrip();//check buttons, update amperage

  latchButtons();//check buttons, see if we need to move

  moveMotor();//check latches, move motor in or out

}//end main loop

void updateLCD()
{
  lcd.setCursor(0, 1);
  lcd.print("Amps:  0");

  lcd.setCursor(8, 1);
  lcd.print("Trip:  0");

  lcd.setCursor(13, 1);
  lcd.print("   ");//clear old value

  if (maxAmps > 99) lcd.setCursor(13, 1);
  else if (maxAmps > 9) lcd.setCursor(14, 1);
  else lcd.setCursor(15, 1);

  lcd.print(maxAmps);//write new value

}//end updateLCD

void latchButtons()
{
  button = read_LCD_buttons();

  if (button == btnLEFT && rightlatch != HIGH)//left is forwards
  {
    currentTimedebounce = millis() - lastButtonpress;
    if (currentTimedebounce > debounceTime && dontExtend == false)//once you've tripped dontExtend, ignore all forwards presses
    {
      leftlatch = !leftlatch;
      button = btnNONE;
      firstRun = true;
      lastButtonpress = millis();
      return;
    }//end if
  }//end btnLEFT

  if (button == btnRIGHT && leftlatch != HIGH)//right is backwards
  {
    currentTimedebounce = millis() - lastButtonpress;
    if (currentTimedebounce > debounceTime)
    {
      rightlatch = !rightlatch;
      button = btnNONE;
      firstRun = true;
      lastButtonpress = millis();
      return;
    }//end if
  }//end btnRIGHT
}//end latchButtons

int read_LCD_buttons()
{
  adc_key_in = analogRead(A0);      // read the value from the sensor
  delay(20);

  if (adc_key_in > none - threshold && adc_key_in < none + threshold)   return btnNONE;
  if (adc_key_in > btnup - threshold && adc_key_in < btnup + threshold)   return btnUP;
  if (adc_key_in > btndown - threshold && adc_key_in < btndown + threshold)   return btnDOWN;
  if (adc_key_in > btnleft - threshold && adc_key_in < btnleft + threshold)   return btnLEFT;
  if (adc_key_in > btnright - threshold && adc_key_in < btnright + threshold)   return btnRIGHT;
  if (adc_key_in > select - threshold && adc_key_in < select + threshold)   return btnSELECT;

  return btnNONE;  // when all others fail, return none

}//end readLCD

void updateTrip()
{
  if (button == btnUP)
  {
    currentTimetrip = millis() - lastUpdate;
    if (currentTimetrip > updateTime)
    {
      maxAmps = maxAmps + 1;

      if (maxAmps > 999) maxAmps = 0;//check for rollover

      lcd.setCursor(13, 1);
      lcd.print("   ");//clear old value

      if (maxAmps > 99) lcd.setCursor(13, 1);
      else if (maxAmps > 9) lcd.setCursor(14, 1);
      else lcd.setCursor(15, 1);//set cursor accordingly

      lcd.print(maxAmps);//write new value

      lastUpdate = millis();
    }//end if
  }//end if btnUP

  else if (button == btnDOWN)
  {
    currentTimetrip = millis() - lastUpdate;
    if (currentTimetrip > updateTime)
    {
      maxAmps = maxAmps - 1;

      if (maxAmps < 0) maxAmps = 999;//check for rollover

      lcd.setCursor(13, 1);
      lcd.print("   ");//clear old value

      if (maxAmps > 99) lcd.setCursor(13, 1);
      else if (maxAmps > 9) lcd.setCursor(14, 1);
      else lcd.setCursor(15, 1);//set cursor accordingly

      lcd.print(maxAmps);//write new value

      lastUpdate = millis();
    }//end if
  }//end else if btnDOWN

}//end updateTrip

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)
  {
    //Serial.println("Moving forwards");
    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

}//end motorForward

void motorBack (int speeed)
{
  while (rightlatch == HIGH)
  {
    //Serial.println("Moving Back");
    digitalWrite(EnablePin, HIGH);
    analogWrite(PWMPinA, 0);
    analogWrite(PWMPinB, speeed);//move motor
    delay(3); //small delay to get to speed

    currentTimefeedback = millis() - lastfeedbacktime;

    if (firstRun == true && currentTimefeedback > firstfeedbacktimedelay) getFeedback(); //if it hasnt been long enough, do nothing
    if (firstRun == false && currentTimefeedback > feedbacktimedelay) getFeedback(); //if it hasnt been long enough, do nothing

    firstRun = false;

    latchButtons();

  }//end while

  dontExtend = false;

}//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);

  if (CRaw == 0 && hitLimits < hitLimitsmaxback) hitLimits = hitLimits + 1;
  else if (CRaw == 0 && hitLimits < hitLimitsmaxfront) hitLimits = hitLimits + 1;
  else hitLimits = 0;

  if (hitLimits == hitLimitsmaxback)
  {
    rightlatch = LOW;
  }//end if

  if (hitLimits == hitLimitsmaxfront)
  {
    leftlatch = LOW;
    hitLimits = 0;
  }//end if

  if (CRaw > maxAmps)
  {
    dontExtend = true;
    leftlatch = LOW;
  }//end if

  printFeedback();

  lastfeedbacktime = millis();//store previous time for receiving feedback
}//end getFeedback

void printFeedback()
{
  lcd.setCursor(5, 1);
  lcd.print("   ");

  if (CRaw > 99) lcd.setCursor(5, 1);
  else if (CRaw > 9) lcd.setCursor(6, 1);
  else lcd.setCursor(7, 1);
  lcd.print(CRaw);

}//end printFeedback

IMG_0350

With that you should be able to monitor the force feedback of the linear actuator with the LCD screen. Everything used in this project can be found on our website and is in stock and ready to ship. If you'd like to order any of the products used here or want to learn more about them please contact us by phone or email.

Servicing Top Brands:

Please wait...