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.
for more details can be found in the link http://mearm.com
Video demonstration:
I use Sequence Programming for 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 thickfor more details can be found in the link http://mearm.com
Video demonstration:
Arduino Robot Arm (MeArm) - Modbus - PLC
Hardware Required for Arduino Robot Arm
- MeArm
- 4 pieces Servo MG90S
- 5 Volt Power Supply for Servos
- Arduino UNO
- Power Supply for Arduino
- TTL to RS232 Module
- PLC with Slave Modbus support, I use Siemens S7-200
- RS232 PLC Cable
- Limit switch for Object Detection
Hardware Connections for Arduino Robot Arm
- Limit Switch connect to PLC Input I0.0
- TTL - RS232 Module and Arduino UNO :
- TTL - RS232 Module connect to RS232 PLC Cable
- RS232 PLC Cable Connect to PLC
- 4 pieces Servo and Power Supply :
- 4 pieces Servo and Arduino UNO
TTL - RS232 Module
|
Arduino UNO
|
VCC
|
5V
|
GND
|
GND
|
RX
|
RX (Pin 0)
|
TX
|
TX (Pin 1)
|
Color servo cables
|
Power Supply 5 Volt
|
Red
|
+ 5 Volt
|
Brown
|
GND / - 5 Volt
|
If all servo connect to 5 volt Arduino there will be errors servo movement
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
- I use Arduino Software version 1.6.6
- Libraries , click here Copy paste libraries to Arduino software folder .. \libraries
Project File download
- Arduino Project File, click here
- Siemens PLC S7-200 Project File, click here
Modbus Communication between Arduino Robot Arm (MeArm) and PLC
- Arduino UNO such as Modbus Master
- Siemens PLC S7-200 such as Modbus Slave
Arduino Robot Arm (MeArm) Movement from PLC
- MeArm Rotary Servo movement from Modbus 40001 / VW0 of S7-200
- MeArm Left Side Servo movement from Modbus 40002 / VW2 of S7-200
- MeArm Right Side Servo movement from Modbus 40003 / VW4 of S7-200
- MeArm Claw Servo movement from Modbus 40004 / VW6 of S7-200
- Feed Rate movement from Modbus 40005 / VW8 of S7-200
- 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 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; }