Tuesday, January 5, 2016

Collaboration between Arduino Robot Arm (MeArm) and PLC (Programmable Logic Controller)




in this topic discusses learning robot arm and Arduino or Arduino Robot Arm controlled by PLC.

for Arduino robot arm movement by the PLC with movement data from PLC memory.

Communication between Arduino Robot Arm with PLC using Modbus communication.

This application is used to learn a robotic arm controlled by PLC.

for Robot Arm using MeArm, and  MeArm is Robot Arm with 4 DOF Robot Arm.

Build a Robot Arm

I use acrylic with 3 mm thick
for more details can be found in the link http://mearm.com

Build a Robot Arm MeArm


Video demonstration:

Arduino Robot Arm (MeArm) - Modbus - PLC



Hardware Required for Arduino Robot Arm

  1. MeArm

  2. 4 pieces Servo MG90S

  3. 5 Volt Power Supply for Servos

  4. Arduino UNO

  5. Power Supply for Arduino

  6. TTL to RS232 Module

  7. PLC with Slave Modbus support,  I use Siemens S7-200

  8. RS232 PLC Cable

  9. Limit switch for Object Detection

Arduino Robot Arm and PLC Hardware


Power Supply for Servo and Arduino



Hardware Connections for Arduino Robot Arm

  1. Limit Switch connect to PLC Input I0.0

  2. TTL - RS232 Module and Arduino UNO :

  3. TTL - RS232 Module
    Arduino UNO
    VCC
    5V
    GND
    GND
    RX
    RX (Pin 0)
    TX
    TX (Pin 1)


  4. TTL - RS232 Module connect to RS232 PLC Cable

  5. RS232 PLC Cable Connect to PLC

  6. 4 pieces Servo and Power Supply :

  7. Color servo cables
    Power Supply 5 Volt
    Red
    + 5 Volt
    Brown
    GND / - 5 Volt
    All Servo do not connect to 5 Volt from Arduino,
    If all servo connect to 5 volt Arduino there will be errors servo movement


  8. 4 pieces Servo and Arduino UNO

  9. MeArm
    Color servo cable
    Arduino UNO
    Rotary Servo
    Orange
    Pin 10
    Left Side Servo
    Orange
    Pin 5
    Right Side Servo
    Orange
    Pin 6
    Claw Servo
    Orange
    Pin 9


Software and Libraries

  1. I use Arduino Software version 1.6.6
  2. Libraries , click here
  3. Copy paste libraries to Arduino software folder  .. \libraries


Project File download

  1. Arduino Project File, click here
  2. Siemens PLC S7-200 Project File, click here


Modbus Communication between Arduino Robot Arm (MeArm) and PLC

  1. Arduino UNO such as Modbus Master
  2. Siemens PLC S7-200 such as Modbus Slave

Modbus Arduino Robot Arm MeArm and PLC


Arduino Robot Arm (MeArm) Movement from PLC

  1. MeArm Rotary Servo movement from Modbus 40001 / VW0 of S7-200

  2. MeArm Left Side Servo movement from Modbus 40002 / VW2 of S7-200

  3. MeArm Right Side Servo movement from Modbus 40003 / VW4 of S7-200

  4. MeArm Claw Servo movement from Modbus 40004 / VW6 of S7-200

  5. Feed Rate movement from Modbus 40005 / VW8 of S7-200

  6. Example of MeArm Movement :

    • Rotary move to 90 degree

    • Left Side move to 82 degree

    • Right Side move to 60 degree

    • Claw move to 25 degree

    • Feed Rate is 20 degree per 100 milliseconds

    • In PLC Ladder Programming is :

    MeArm Movement from PLC

  7. MeArm Movement Actual :

    • Read Rotary from Modbus 40006 / VW10 of S7-200

    • Read Left Side from Modbus 40007 / VW12 of S7-200

    • Read Right Side from Modbus 40008 / VW14 of S7-200

    • Read Claw from Modbus 40009 / VW16 of S7-200

    • Read Feed Rate from Modbus 40010 / VW18 of S7-200


Arduino Robot Arm (MeArm) Movement Sequence from PLC

Movement Sequence  from movement 1 to movement 12,
I use Sequence Programming for PLC


Arduino Code for Robot Arm

#include <Servo.h>
#include <SimpleModbusMaster.h>

#define MODBUSSlaveAddress 1
#define MODBUSbaud 9600
#define MODBUSformat SERIAL_8E1
#define MODBUStimeout 1000
#define MODBUSpolling 1
#define MODBUSretry_count 0
#define MODBUSTxEnablePin 13 

enum
{
  MODBUSPACKET1,
  MODBUSPACKET2,
  MODBUSTOTAL_NO_OF_PACKETS
};

Packet MODBUSpackets[MODBUSTOTAL_NO_OF_PACKETS];

packetPointer MODBUSpacket1 = &MODBUSpackets[MODBUSPACKET1];
packetPointer MODBUSpacket2 = &MODBUSpackets[MODBUSPACKET2];

unsigned int MODBUSreadRegs[5];
unsigned int MODBUSwriteRegs[5];


const int SERVOS = 4;
int PIN[SERVOS], MIN[SERVOS], MAX[SERVOS], INITANGLE[SERVOS];
int POSAngle[SERVOS];
Servo MeArmServo[SERVOS];
uint16_t FEED_RATE;

void setup() {
  //Rotary Servo
  PIN[0] = 10;
  MIN[0] = 0;
  MAX[0] = 180;
  INITANGLE[0] = 90;  
  
  //Left Side
  PIN[1] = 5;
  MIN[1] = 20;
  MAX[1] = 150;
  INITANGLE[1] = 90;
  
  //Right Side
  PIN[2] = 6;
  MIN[2] = 0;
  MAX[2] = 110;
  INITANGLE[2] = 10;
  
  //Claw Servo
  PIN[3] = 9;
  MIN[3] = 0;
  MAX[3] = 130;
  INITANGLE[3] = 25;

modbus_construct(MODBUSpacket1, MODBUSSlaveAddress, READ_HOLDING_REGISTERS, 0, 5, MODBUSreadRegs);
   
modbus_construct(MODBUSpacket2, MODBUSSlaveAddress, PRESET_MULTIPLE_REGISTERS, 5, 5, MODBUSwriteRegs);
  
modbus_configure(&Serial, MODBUSbaud, MODBUSformat, MODBUStimeout, MODBUSpolling, MODBUSretry_count, MODBUSTxEnablePin, MODBUSpackets, MODBUSTOTAL_NO_OF_PACKETS);

   
  MeArmServo[1].attach(PIN[1]);
  MeArmServo[1].write(INITANGLE[1]); 
  delay(1000);
  MeArmServo[2].attach(PIN[2]);
  MeArmServo[2].write(INITANGLE[2]); 
  delay(1000);
  MeArmServo[3].attach(PIN[3]);
  MeArmServo[3].write(INITANGLE[3]); 
  MeArmServo[0].attach(PIN[0]);
  MeArmServo[0].write(INITANGLE[0]);

  MODBUSwriteRegs[0] = INITANGLE[0];
  MODBUSwriteRegs[1] = INITANGLE[1];
  MODBUSwriteRegs[2] = INITANGLE[2];
  MODBUSwriteRegs[3] = INITANGLE[3];
  yield();
}

void loop() {
    modbus_update();
    POSAngle[0] = MODBUSreadRegs[0];
    POSAngle[1] = MODBUSreadRegs[1];
    POSAngle[2] = MODBUSreadRegs[2];
    POSAngle[3] = MODBUSreadRegs[3];
    FEED_RATE = MODBUSreadRegs[4];
    Move_Pos(POSAngle[0] ,POSAngle[1], POSAngle[2], POSAngle[3], FEED_RATE);    
   
   for (int i = 0; i < SERVOS; i++){
    MODBUSwriteRegs[i] = MeArmServo[i].read();
   } 

   MODBUSwriteRegs[4] = FEED_RATE;
   
}

void Move_Pos(uint16_t Rotary, uint16_t Left, uint16_t Right, uint16_t Claw,uint16_t deg_per_100ms) {
if(deg_per_100ms==0)return;
if(Rotary<MIN[0])Rotary=MIN[0];
if(Rotary>MAX[0])Rotary=MAX[0];  

if(Left<MIN[1])Left=MIN[1];
if(Left>MAX[1])Left=MAX[1]; 

if(Right<MIN[2])Right=MIN[2];
if(Right>MAX[2])Right=MAX[2];

if(Claw<MIN[3])Claw=MIN[3];
if(Claw>MAX[3])Claw=MAX[3];  

int Axis_delta[4] = {0,0,0,0};

int Rotary_delta = MeArmServo[0].read() - Rotary;
if(Rotary_delta<0)Rotary_delta*=-1;
Axis_delta[0] = Rotary_delta;

int Left_delta = MeArmServo[1].read() - Left;
if(Left_delta<0)Left_delta*=-1;
Axis_delta[1] = Left_delta;

int Right_delta = MeArmServo[2].read() - Right;
if(Right_delta<0)Right_delta*=-1;
Axis_delta[2] = Right_delta;

int Claw_delta = MeArmServo[3].read() - Claw;
if(Claw_delta<0)Claw_delta*=-1;
Axis_delta[3] = Claw_delta;

int index_max = getIndexOfMaximumValue(Axis_delta, 4);

int Max_Deg_delta =  Axis_delta[index_max];

float ms_factor = 100.0;
float buf_max_deg_delta = Max_Deg_delta * ms_factor;
float buf_max_time = buf_max_deg_delta /deg_per_100ms;
float buff_Rotary_time = buf_max_time/Axis_delta[0];
float buff_Left_time = buf_max_time/Axis_delta[1];
float buff_Right_time =  buf_max_time/Axis_delta[2];
float buff_Claw_time = buf_max_time/Axis_delta[3];


uint8_t time_factor = 1;
uint16_t Rotary_time = (int) (buff_Rotary_time*time_factor);
uint16_t Left_time = (int) (buff_Left_time*time_factor);
uint16_t Right_time = (int)  (buff_Right_time*time_factor);
uint16_t Claw_time = (int) (buff_Claw_time*time_factor);

bool Pos_Rotary = false;
bool Pos_Left = false;
bool Pos_Right = false;
bool Pos_Claw = false;

unsigned long Rotary_Millis = millis();
unsigned long Left_Millis = millis();
unsigned long Right_Millis = millis();
unsigned long Claw_Millis = millis();

uint16_t Rotary_target =  MeArmServo[0].read(); 
uint16_t Left_target =  MeArmServo[1].read(); 
uint16_t Right_target =   MeArmServo[2].read(); 
uint16_t Claw_target =  MeArmServo[3].read(); 


while(!Pos_Rotary || !Pos_Left || !Pos_Right || !Pos_Claw){ 

  unsigned long currentMillis = millis();
     
    if(MeArmServo[0].read()!=Rotary){  
     if(MeArmServo[0].read()>Rotary){
        if(currentMillis>=Rotary_Millis){
          Rotary_target-=1;
          Rotary_Millis = millis()+Rotary_time;
        }        
        if(MeArmServo[0].read()==Rotary)Rotary_target=Rotary;
        
        if (!MeArmServo[0].attached()){
         MeArmServo[0].attach(PIN[0]);
        } 
        MeArmServo[0].write(Rotary_target);        
       }
       
       if(MeArmServo[0].read()<Rotary){
        if(currentMillis>=Rotary_Millis){
          Rotary_target+=1;
          Rotary_Millis = millis()+Rotary_time;
        } 
        if(MeArmServo[0].read()==Rotary)Rotary_target=Rotary;
        if (!MeArmServo[0].attached()){
         MeArmServo[0].attach(PIN[0]);
        }
        MeArmServo[0].write(Rotary_target);
       }
    }else{
      Pos_Rotary = true;
    }


  
    if(MeArmServo[1].read()!=Left){
       if(MeArmServo[1].read()>Left){
        if(currentMillis>=Left_Millis){
        Left_target-=1;
        Left_Millis = millis()+Left_time;
        }        
        if(MeArmServo[1].read()==Left)Left_target=Left;
        if (!MeArmServo[1].attached()){
         MeArmServo[1].attach(PIN[1]);
        }
        MeArmServo[1].write(Left_target);      
       }
       
       if(MeArmServo[1].read()<Left){
        if(currentMillis>=Left_Millis){
        Left_target+=1;
        Left_Millis = millis()+Left_time;
        } 
        if(MeArmServo[1].read()==Left)Left_target=Left;
        if (!MeArmServo[1].attached()){
         MeArmServo[1].attach(PIN[1]);
        }
        MeArmServo[1].write(Left_target); 
       }
    }else{
      Pos_Left =true;
    }


   
    if(MeArmServo[2].read()!=Right){
       if(MeArmServo[2].read()>Right){
        if(currentMillis>=Right_Millis){ 
        Right_target-=1;
        Right_Millis = millis()+Right_time;
        }
        if(MeArmServo[2].read()==Right)Right_target=Right;
        if (!MeArmServo[2].attached()){
         MeArmServo[2].attach(PIN[2]);
        }
        MeArmServo[2].write(Right_target); 
        
       }
       
       if(MeArmServo[2].read()<Right){
        if(currentMillis>=Right_Millis){ 
        Right_target+=1;
        Right_Millis = millis()+Right_time;
        }
        if(MeArmServo[2].read()==Right)Right_target=Right; 
        if (!MeArmServo[2].attached()){
         MeArmServo[2].attach(PIN[2]);
        }
        MeArmServo[2].write(Right_target);
       }
    }else{
      Pos_Right =true;
    }


    
     if(MeArmServo[3].read()!=Claw){
       if(MeArmServo[3].read()>Claw){
        if(currentMillis>=Claw_Millis){
        Claw_target-=1;
        Claw_Millis = millis()+Claw_time;
        }
        if(MeArmServo[3].read()==Claw)Claw_target=Claw;
        if (!MeArmServo[3].attached()){
         MeArmServo[3].attach(PIN[3]);
        }
        MeArmServo[3].write(Claw_target);
        
       }
       
       if(MeArmServo[3].read()<Claw){
        if(currentMillis>=Claw_Millis){
        Claw_target+=1;
        Claw_Millis = millis()+Claw_time;
        }
        if(MeArmServo[3].read()==Claw)Claw_target=Claw;
        if (!MeArmServo[3].attached()){
         MeArmServo[3].attach(PIN[3]);
        }
        MeArmServo[3].write(Claw_target);
       }
     }else{
      Pos_Claw =true;
     }
}

}


int getIndexOfMaximumValue(int* array, int size){
 int maxIndex = 0;
 int arr_max = array[maxIndex];
 for (int i=1; i<size; i++){
   if (arr_max<array[i]){
     arr_max = array[i];
     maxIndex = i;
   }
 }
 return maxIndex;
}


Labels:






Newer Post Older Post Home

You may also like these ebook:

Get Free PLC eBook directly sent to your email,
and email subscription to program-plc.blogspot.com




We hate SPAM. Your information is never sold or shared with anyone.

Your Email Will Be 100% Secured !

Your email is stored safely on Google FeedBurner