Monday, June 1, 2015

Motion Control / Positioning Control for PLC using Arduino

Motion control / positioning control of three axes using Arduino CNC/ GRBL.
This application using two arduino, one arduino UNO for CNC controller/GRBL and one arduino ATMega for GCode Sender and connect to PLC.
Communication for GCode Sender between Arduino UNO and Arduino ATMega using Serial (TTL serial port).
Communication between PLC and Arduino ATMega using Modbus Protocol.
Three axis consisting of the X axis, Y axis and Z axis is set in the PLC Modbus Registers.

For simulation, I use stepper motor from DVD-ROM Drive.

Servo Motor/Stepper Motor connect to Arduino CNC and PLC

Servo Motor Stepper Motor connect to Arduino CNC and PLC

1. Stepper Motor / Servo Motor:
I use stepper motor from DVD-ROM Drive.
I use small motor, for big motor, I don't have money : Donate

2. Driver/Servo Amplifier with support voltage 5 Volt for STEP PULSE and DIRECTION:
I use A4988 Micro Stepping Motor Driver.

3. Arduino UNO
4. Arduino ATMega
5. TTL to RS232 male connector
6. RS232 PLC Cable
7. Siemens PLC or other PLCs that support Modbus
8. Power Supply 12 Volt
9. Micro Limit Switch for Homing Stepper Motor Drive.
10. Push Button for Start: connect to I0.0 on PLC Input
11. Push Button for Homing: connect to I0.1 on PLC Input

Hardware Setting and Connection:
1. Arduino CNC layout:
2. The specification of the DVD-ROM Drive:
2a.The maximum current of roughly 200mA
2b. Stepper motor have 20 steps per revolution.
2c. The lead screw has a pitch of 3mm per revolution.
2d. In Driver, I use Micro step Resolution = 16
2d. STEPS PER MM = (20 X 16) STEPS PER 3 MM = 106.667 (Parameter Setting in Grbl)

Hardware of DVD-ROM Drive and Limit Switch for Homing

A4988 Micro Stepping Motor Driver and Arduino UNO

Arduino UNO, Arduino ATMega and PLC

Download Project File:
1. Download Arduino libraries, click here
Copy-Paste folder: SimpleModbusMaster and Grbl9fUno into folder C:\Program Files (x86)\Arduino\libraries

2. Upload program to Arduino UNO:
In Arduino Software (IDE): Click File -- Click Examples -- Click Grbl9fUno -- Click GRBL9funo And Then Click Upload Icon

3. Upload program to Arduino ATMega:
In Arduino Software (IDE): Click File -- Click Examples -- Click SimpleModbusMaster -- Click MotionControlForPLC And Then Click Upload Icon

4. Download PLC Ladder Programming, click here
5. Download Hardware Connection, click here
6. Download A4988 Micro Stepping Motor Driver, click here

Arduino ATMega Code:
#include <SimpleModbusMaster.h>
//Arduino Serial Port Connect to Port 0 of Siemens PLC S7 200
//for more info
#define slaveAddr 1
#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 0
#define TxEnablePin 2 
Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];
unsigned int readRegs[1];
unsigned int writeRegs[7];
unsigned int Motion_Command = 0;
bool CommandEx=true;

int stat=0;
long MPosX=0;
long WPosX=0;

void setup() {  
  modbus_construct(packet1, slaveAddr, READ_HOLDING_REGISTERS, 7, 1, readRegs);
  modbus_construct(packet2, slaveAddr, PRESET_MULTIPLE_REGISTERS, 0, 7, writeRegs);
  modbus_configure(&Serial2, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);  


void loop() { 
  unsigned int p2sr=packet2->successful_requests;
  Motion_Command = (word)readRegs[0];
  writeRegs[4] = stat;  
  writeRegs[5]= (word)random(1, 32760);;
     case 1: //Reset Grbl
     case 2: //Kill Alarm Lock
        Sender("$X", "ok",5000);//Kill Alarm Lock
     case 3: //Run Homing Cycle
        stat = 5;//Home=5
        writeRegs[4] = stat;
        Sender("$H", "ok",60000);// Run Homing Cycle 
     case 4: //cycle start 
        Sender("~", "ok",5000);//cycle start 
     case 5: //feed hold 
        Sender("!", "ok",5000);//feed hold 
      case 6://go to x0
        Sender("g90 g0 x0", "ok",5000);
      case 7://increment 10.5mm for pills with 10.5mm diameter 
        Sender("g91 g1 x-10.5 f400", "ok",5000);
      case 8://GCode Programming for Cutting Material
        Sender("g90 g0 x-25", "ok",5000);// High Speed with G0
        Sender("g90 g1 x-33 f60", "ok",5000);//Low Speed / Cutting Process with G1
        Sender("g90 g1 x-25 f60", "ok",5000);//Low Speed / Cutting Process with G1
        Sender("g90 g0 x0", "ok",5000);// High Speed with G0
  writeRegs[6]= (word)Motion_Command;     
    writeRegs[6]= (word)0;  

String Sender(String command, char *UntilChar,int millisWait)
    String data="";
    unsigned long start;
    start = millis();
    while (millis()-start<millisWait) {
       char c;
       if (data.indexOf(UntilChar)!=-1)break;
       if (data.indexOf("Reset to continue")!=-1){
    return data;

void ResetGrbl()
    Serial1.write(0x18); //Reset
    String data="";
    unsigned long start;
    start = millis();
    while (millis()-start<5000) {
       char c;
       if (data.indexOf("['$' for help]")!=-1)return;
    asm volatile ("  jmp 0"); 

void CurrentStatus(){
  String cur = Sender("?", "ok",5000);
  if (cur==""){
    stat=11; //No Data=11
    if (cur.indexOf("Idle")!=-1)stat=1;//Idle=1
    if (cur.indexOf("Queue")!=-1)stat=2;//Queue=2
    if (cur.indexOf("Run")!=-1)stat=3;//Run=3
    if (cur.indexOf("Hold")!=-1)stat=4;//Hold=4
    if (cur.indexOf("Home")!=-1)stat=5;//Home=5
    if (cur.indexOf("Check")!=-1)stat=6;//Check=6
    if (cur.indexOf("Alarm")!=-1)stat=7;//Alarm=7 
    if (cur.indexOf("ALARM: Hard/soft limit")!=-1)stat=8;//ALARM=8    
    if (cur.indexOf("Reset to continue")!=-1)stat=9;//Reset to continue=9 
    if (cur.indexOf("'$H'|'$X' to unlock")!=-1)stat=9;//Reset to continue=10
    if((cur.indexOf("<")!=-1) && (cur.indexOf(">")!=-1)){
     if((cur.indexOf(",MPos:")!=-1) && (cur.indexOf(",WPos:")!=-1)){
      String buff = cur.substring(cur.indexOf(",MPos:")+6,cur.indexOf(",WPos:"));
      String buffvalX = buff.substring(0,buff.indexOf(","));
      MPosX= (long)buffvalX.toInt();     
      buff = cur.substring(cur.indexOf(",WPos:")+6,cur.indexOf(">"));
      buffvalX = buff.substring(0,buff.indexOf(","));
      WPosX = (long)buffvalX.toInt();

void Long2unInt(long l,unsigned int *i0,unsigned int *i1)
  *i0 = (l & 0xFFFF);
  unsigned int buff = l >> 16;
  *i1 = (buff & 0xFFFF);


Newer Post Older Post Home

You may also like these ebook:

Get Free PLC eBook directly sent to your email,
and email subscription to

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

Your Email Will Be 100% Secured !