Esmacat
Published © GPL3+

Pi & CODESYSPLC-Arduino to control Motors using a LCD Shield

Use a Raspberry Pi with CODESYS PLC to control motors attached to an Arduino Uno and EASE using input from another LCD Shield with EASE.

IntermediateProtip2 hours2,854

Things used in this project

Hardware components

Raspberry Pi 4 Model B
Raspberry Pi 4 Model B
×1
Arduino UNO
Arduino UNO
×2
EtherCAT Arduino Shield by Esmacat (EASE)
×2
Ethernet Cable, Cat6a
Ethernet Cable, Cat6a
×3
Power over Ethernet (POE) Injector
×1
DC Adapter
×1
16x2 LCD Shield
×1
Adafruit Motor Shield
×1
Servo Motor
(Optional to test the code). Any Servo motor can be used. This specific motor has been used in this tutorial.
×1
DC Motor
(Optional Motor to test the code). Any dc motor can be used. This specific motor has been used in this tutorial.
×1
Stepper Motor
(Optional Motor to test the code). Any stepper motor can be used. This specific motor has been used in this tutorial.
×1
Power Source
Any power source like a lipo battery or battery eliminator to power the motors.
×1
Raspberry Pi Power Supply
Power Supply for the Raspberry Pi
×1

Story

Read more

Schematics

Physical Hardware Connection schematic

Hardware setup after final connections

Hardware Setup Schematic

Schematic of the connection used in the tutorial

Code

Arduino with EASE and Motor Shield Code

Arduino
Code to be uploaded with the Arduino Board with EASE and Motor Shield.
/*
  Motors Control

  This sketch does the following:
  1) Gets update for the speed from another Arduino connected to the EASE master.
  2) Depending on the motor chosen, it does the following
      2.1) If the motor chosen is a DC Motor, the motor is set to run at the set speed.
           The current speed of the motor is printed on the LCD.
      2.2) If the motor chosen is a Servo Motor, the motor is set at the desired position.
           The current position of the motor is printed on the LCD.
      2.3) If the motor chosen is a Stepper Motor, the motor is set to run at the set speed.          

  created 25 Feb 2020
  by Harmonic Binonics Inc. (https://www.harmonicbionics.com/). 
  
*/

/*
    Buton Encoding Relation
    -------------------------------------------
    |    Button on LCD     |    Encoded Value  |
    -------------------------------------------
    |         Left         |          1        |
    |          Up          |          2        |
    |         Down         |          3        |
    |         Right        |          4        |
    |        Select        |          5        |
    --------------------------------------------
*/
 
/*
    Motor Select Options
    |--------------------------------------------------------|
    |   Motor Select Integer Value   |    Motor Controlled   |
    |--------------------------------------------------------|
    |               0                |       Servo Motor     |
    |               1                |         DC  Motor     |
    |               2                |     Stepper Motor     |
    |--------------------------------------------------------|
*/

#include <Wire.h>
#include <Adafruit_MotorShield.h>   // Include the Adafruit Motor Shield Library

#include <Servo.h>   // Include the Arduino Servo Library
#include <Esmacatshield.h>      //Include the Esmacat Arduino Library

// Define the Pin Numbers as Macros
# define servo_control_pin 9   // Servo is connected to Servo port #1 on the Motor Shield
# define Serial_baud_rate 9600
# define ARDUINO_UNO_SLAVE_SELECT 10      // The chip selector pin for Arduino Uno is 10 

// Create objects for various motor classes and EASE
Esmacatshield ease_with_motor(ARDUINO_UNO_SLAVE_SELECT);      // Create a slave object and specify the Chip Selector Pin

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 

// Create an object for Stepper Motor
Adafruit_StepperMotor *stepper_motor = AFMS.getStepper(200, 2);   // Connect a stepper motor with 200 steps per revolution
                                                                  // (1.8 degree) to motor port #2 (M3 and M4)
// Create an object for DC Motor
Adafruit_DCMotor *dc_motor = AFMS.getMotor(2);   // Connect a DC motor to motor port #2 (M2)

// Create an object for the Servo Motor Class
Servo servo_2;   // Servo is connected to Servo port #2 on the Motor Shield so the name servo_2 is used

// Required variables Initialization
int motor_select = 0;   // Variable to choose which motor to control
int servo_angle = 0;   // Variable to store the input angle
int stepper_speed = 0;   // Variable to store stepper motor speed
int dc_speed = 0;   // Variable to store dc motor speed
int ease_registers[8];      // EASE 8 registers

void setup() 
{
  Serial.begin(9600);           // set up Serial library at 9600 bps

  AFMS.begin();  // create with the default frequency 1.6KHz
  
  stepper_motor->setSpeed(10);  // 10 rpm 
  
  dc_motor->setSpeed(0);   // Set the initial Speed of DC Motor to 0
  // dc_motor->run(FORWARD);  

  servo_2.attach(servo_control_pin);   // Servo 1 on Adafruit Motor Shield is connected
                                       // to Pin 10 of the Arduino board
  ease_with_motor.start_spi();      // Start SPI for EASE
}

void loop() 
{
  ease_with_motor.get_ecat_registers(ease_registers);

  motor_select = ease_registers[0];   // Motor to control
  servo_angle = ease_registers[1];   // Actual Servo position
  dc_speed = ease_registers[2];   // Actual dc motor speed
  stepper_speed = ease_registers[3];   // Actual Stepper Motor Speed
  Serial.println(motor_select);
  if(motor_select == 0)
  {
    servo_2.write(servo_angle);
    Serial.print("Servo Angle ");
    Serial.println(servo_angle);
  }
  
  if(motor_select == 1)
  {
    if(dc_speed > 0)
    {
      dc_motor->setSpeed(dc_speed);
      dc_motor->run(FORWARD);
    }
    else
    {
      dc_motor->setSpeed(dc_speed);
      dc_motor->run(BACKWARD);
    }
    Serial.print("DC Speed");
    Serial.println(dc_speed);
  }

  if(motor_select == 2)
  {
    if(stepper_speed > 0)
    {
      stepper_motor->step(stepper_speed,FORWARD,SINGLE);
    }

    else
    {
      stepper_motor->step(stepper_speed,BACKWARD,SINGLE);
    }
    Serial.print("Stepper Speed");
    Serial.println(stepper_speed);
   }
}

Arduino with EASE and LCD Shield Code

Arduino
Code to be uploaded with the Arduino Board with EASE and LCD Shield.
/*
  Motors Control

  This sketch does the following:
  1) Gets user input for choice of motor from another Arduino connected to the EASE master.
  2) Depending on the motor chosen, it does the following
      2.1) If the motor chosen is a DC Motor, using the up and down buttons on the second Arduino
           the speed can be controlled.
           The current speed of the motor is printed on the LCD.
      2.2) If the motor chosen is a Servo Motor, using the up and down buttons on the second Arduino
           the angle can be controlled.
           The current position of the motor is printed on the LCD.
      2.3) If the motor chosen is a Stepper Motor, using the up and down buttons on the second Arduino
           the speed can be controlled.
           The current speed of the motor is printed on the LCD.            

  created 25 Feb 2020
  by Harmonic Binonics Inc. (https://www.harmonicbionics.com/).
  
*/

/*
    PIN CONFIGURATION of the LCD Shield Used
    |-----------------------------------------|
    |  LCD PIN Number  |   Arduino PIN Number |
    |-----------------------------------------|
    |       RS         |      Digital Pin 8   |
    |     ENABLE       |      Digital Pin 9   |
    |       D4         |      Digital Pin 4   |
    |       D5         |      Digital Pin 5   |
    |       D6         |      Digital Pin 6   |
    |       D7         |      Digital Pin 7   |
    |     Buttons      |      Analog Pin A0   |
    |-----------------------------------------|
    
*/

/*
    Analog Input Values for the Push Buttons
    |------------------------------------------------|
    |    Push Button     |          A0 value         |
    |------------------------------------------------|
    |       SELECT       |   val >= 500 & val <= 750 |
    |        LEFT        |   val >= 300 & val < 500  |
    |        DOWN        |   val >= 150 & val < 300  |
    |         UP         |   val >= 50  & val < 150  |
    |        RIGHT       |   val >= 0   & val < 50   |
    |------------------------------------------------|
*/

/*
    Buton Encoding Relation
    -------------------------------------------
    |    Button on LCD     |    Encoded Value  |
    -------------------------------------------
    |         Left         |          1        |
    |          Up          |          2        |
    |         Down         |          3        |
    |         Right        |          4        |
    |        Select        |          5        |
    --------------------------------------------
*/
 
/*
    Motor Select Options
    |--------------------------------------------------------|
    |   Motor Select Integer Value   |    Motor Controlled   |
    |--------------------------------------------------------|
    |               0                |       Servo Motor     |
    |               1                |         DC  Moror     |
    |               2                |     Stepper Motor     |
    |--------------------------------------------------------|
*/

#include <LiquidCrystal.h>      // Include LCD Arduino Library
#include <Esmacatshield.h>      //Include the Esmacat Arduino Library


// Define the Pin Numbers as Macros

# define Serial_baud_rate 9600
#define ARDUINO_UNO_SLAVE_SELECT 10      // The chip selector pin for Arduino Uno is 10 
# define RS_pin 8
# define Enable_pin 9
# define LCD_coloumns 16
# define LCD_rows 2

LiquidCrystal lcd_display(RS_pin, Enable_pin, 4, 5, 6, 7);      // Create an object for the Library class
Esmacatshield ease_with_lcd(ARDUINO_UNO_SLAVE_SELECT);      // Create a slave object and specify the Chip Selector Pin

int analog_value;      // Initialise analog input value variable
int servo_angle = 0;   // Variable to store the input angle
int stepper_speed = 0;   // Variable to store stepper motor speed
int dc_speed = 0;   // Variable to store dc motor speed
int motor_select = 0;   // Variable to choose the motor to be controlled
int prev_motor_select = 0;
int prev_servo_angle = 0;
int prev_dc_speed = 0;
int prev_stepper_speed = 0;

int ease_registers[8];      // EASE 8 registers


void setup() 
{
  lcd_display.begin(LCD_coloumns,LCD_rows);      //Initialise the number of (coloumns, rows) in the LCD
  
  lcd_display.print("Servo Motor");      // Print a message onto the LCD Display
                                         // Default is Servo Motor 
  Serial.begin(Serial_baud_rate);      // Initialise the Serial Communication with the specified Baud Rate
  
  ease_with_lcd.start_spi();      // Start SPI for EASE
}

void loop() 
{

  analog_value = analogRead(A0);
  Serial.println(analog_value);
  ease_with_lcd.write_reg_value(0,analog_value);      //Write register data (register,value, led_on)
  
  delay(50);
  
  ease_with_lcd.get_ecat_registers(ease_registers);
  servo_angle = ease_registers[1];   // Actual Servo position
  dc_speed = ease_registers[2];   // Actual dc motor speed
  stepper_speed = ease_registers[3];   // Actual Stepper Motor Speed
  motor_select = ease_registers[4];

  if(motor_select == 0)   // Servo Motor Selected
  {
    if(prev_motor_select != motor_select)
    {
      for(int i = 0; i < 16; i++)
      {
        lcd_display.setCursor(i,0);
        lcd_display.print(" ");      // Remove the previous characters (if any)
      }
    }
    lcd_display.setCursor(0,0);
    lcd_display.print("Servo Motor");
    if(prev_servo_angle != servo_angle)
    {
      for (int i = 0;i < 4;i++)
      {
        lcd_display.setCursor(i,1);
        lcd_display.print(" ");
      }
    }
    lcd_display.setCursor(0,1);
    lcd_display.print(servo_angle);
    lcd_display.setCursor(10,1);      // set the LCD cursor position (Coloumn number,Row number)
    lcd_display.print("angle"); 
  }
  
  if(motor_select == 1)   // DC Motor Selected
  {
    if(prev_motor_select != motor_select)
    {
      for(int i = 0; i < 16; i++)
      {
        lcd_display.setCursor(i,0);
        lcd_display.print(" ");      // Remove the previous characters (if any)
      }
    }
    
    lcd_display.setCursor(0,0);
    lcd_display.print("DC Motor");
    
    if(prev_dc_speed != dc_speed)
    {
      for (int i = 0;i < 4;i++)
      {
        lcd_display.setCursor(i,1);
        lcd_display.print(" ");
      }
    }
    
    lcd_display.setCursor(0,1);
    lcd_display.print(dc_speed);
    lcd_display.setCursor(10,1);      // set the LCD cursor position (Coloumn number,Row number)
    lcd_display.print("speed"); 
  }
  
  if(motor_select == 2)   // Stepper Motor Selected
  {
    if(prev_motor_select != motor_select)
    {
      for(int i = 0; i < 16; i++)
      {
        lcd_display.setCursor(i,0);
        lcd_display.print(" ");      // Remove the previous characters (if any)
      }
    }
    
    lcd_display.setCursor(0,0);
    lcd_display.print("Stepper Motor");
    
    if(prev_stepper_speed != stepper_speed)
    {
      for (int i = 0;i < 4;i++)
      {
        lcd_display.setCursor(i,1);
        lcd_display.print(" ");
      }
    }
    
    lcd_display.setCursor(0,1);
    lcd_display.print(stepper_speed);
    lcd_display.setCursor(10,1);      // set the LCD cursor position (Coloumn number,Row number)
    lcd_display.print("speed"); 
  }
  prev_motor_select = motor_select;
  prev_servo_angle = servo_angle;
  prev_dc_speed = dc_speed;
  prev_stepper_speed = stepper_speed;
}

Codesys Master Code

C/C++
Master Code to be run on Pi
No preview (download only).

EtherCAT Arduino Shield by Esmacat (EASE) Arduino Library

Esmacat Arduino Library

Credits

Esmacat

Esmacat

11 projects • 16 followers
Esmacat is an easy yet powerful EtherCAT solution for robotics. Our EtherCAT tech allow users to run EtherCAT applications in minutes!

Comments