Sunday, December 6, 2015

CP1L-L10 Omron PLC USB and Arduino plus USB Host Shield




CP1L-L10 Omron PLC use USB only for communication with other device such as Arduino, Raspberry Pi and other devices.
For communication with CP1L-L10 using Omron PLC USB Protocol.
This PLC application about Omron PLC USB and connected to Arduino.
Iin Arduino, usually connect to output analog, expand I/O, reading sensor, SCADA communication and others applications.
This application same with the application on my previous article about Omron PLC USB Protocol and Raspberry Pi


Sample case:
  1. Arduino to CP1L-L10 Omron PLC (D2 memory):
  2. Turning potentiometer (Analog Input) and moving the CP1L PLC outputs.
  3. CP1L-L10 Omron PLC (D0 memory) to Arduino:
  4. Pressing the switch (PLC Input) and increase the numbers on voltmeter /multi tester (Analog Output)

The image below about Omron PLC and Arduino that are discussed in this article:

CP1L-L10 Omron PLC USB and Arduino



Video demonstration :

USB Communication between CP1L-L10 Omron PLC USB and Arduino plus USB Host Shield




Hardware for Omron PLC USB and Arduino

  1. CP1L-L10 Omron PLC
  2. Arduino UNO
  3. Arduino USB Host Shield is based on the MAX3421E
  4. Optional for testing :
    • 1 piece potentiometer
    • 2 pieces switch
    • Voltmeter / multi tester

Hardware of Omron PLC USB and Arduino


Arduino plus USB Host Shield



Hardware Connections of Omron PLC USB and Arduino

Hardware Connections of Omron PLC USB and Arduino


Software for Omron PLC USB and Arduino

  1. Arduino Software (IDE), I use Arduino 1.6.6 Hourly Build : https://www.arduino.cc/en/Main/Software
  2. Arduino USB Host Shield Library, click here
  3. Copy paste : USBHostShield2  folder to  .. \arduino-nightly\libraries


Project File for Omron PLC USB and Arduino

  1. for Upload to Arduino, click here
  2. for Transfer to CP1L-L10 Omron PLC, click here


How does the work of Omron PLC USB and Arduino

  1. Press Switch 1 (PLC Input I0.00 is ON) and then Voltmeter value is ~ 1.60 Volt
  2. Press Switch 2 (PLC Input I0.01 is ON) and then Voltmeter value is ~ 3.20 Volt
  3. Press both switches ( I0.00 ON and I0.01 ON) ) and then Voltmeter value is ~ 4.80 Volt
  4. Turning the potentiometer on Arduino and then light is lit on PLC Output (based on binary value from 0 to 15)


Arduino Code for Access  Omron PLC USB

#include <usbhub.h>

#define VendorID 0x0590
#define ProductID 0x005B

USB Usb;
USB_DEVICE_DESCRIPTOR buf;
uint8_t addr;
uint8_t rcode;
uint8_t PLC_State;
uint16_t Omron_PLC_D0_Value;
uint16_t Omron_PLC_D2_Value;
bool USB_RUN = false;
static unsigned long timeout=1000;

const int analogInPin = A0;  // Potentiometer
const int analogOutPin = 5;  // VoltMeter
uint16_t PotentiometerValue = 0;
uint16_t VoltMeterValue = 0;


void setup() {
    Serial.begin(115200);
    if (Usb.Init() == -1){
      Serial.println("OSC did not start and Will be Reset");
      while(1);   
    }

    randomSeed(analogRead(0));
    Serial.println("PLC START");
    PLC_State=0;
}

void loop() {
  Usb.Task();
  if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
  {
  USB_RUN = true;
            switch(PLC_State) {
                    case 0: // Omron PLC Find 
                            rcode = Omron_PLC_Find(VendorID, ProductID);
                            if(rcode){
                              Serial.println("Omron PLC Not Found");
                              while(1);
                            }else{
                              PLC_State=1;
                            }
                            break;
                            
                    case 1: //Command Omron PLC for RUN Mode
                            rcode = Command_Omron_PLC_RUN_Mode();
                            if(rcode==0)PLC_State=2;
                            break;
                            
                    case 2: // Received Omron PLC RUN Mode
                            rcode = Receive_Omron_PLC_RUN_Mode();
                            if(rcode==0)PLC_State=3;
                            break; 
                             
                    case 3: // Command Omron PLC for D memory Read                            
                            rcode = Command_Omron_PLC_D_Read(0);
                            if(rcode==0)PLC_State=4;
                            break;
                            
                    case 4: // Received Omron PLC from D memory Read
                            // Save to Omron_PLC_D0_Value                             
                            rcode = Receive_Omron_PLC_D_Read(&Omron_PLC_D0_Value);  
                            Serial.println(Omron_PLC_D0_Value,DEC); 
                            VoltMeterValue = map(Omron_PLC_D0_Value, 0, 255, 0, 255);
                            analogWrite(analogOutPin, VoltMeterValue);
                            if(rcode){
                                  PLC_State=3; // error goto command again              
                            }else{
                                  PLC_State=5; // no error goto next
                            }                          
                            break;  
                            
                    case 5: // Command Omron PLC for D memory Write 
                            //Omron_PLC_D2_Value = Omron_PLC_D0_Value ; 
                            PotentiometerValue = analogRead(analogInPin);
                            Omron_PLC_D2_Value = map(PotentiometerValue, 0, 1020, 0, 255);                       
                            rcode = Command_Omron_PLC_D_Write(2,Omron_PLC_D2_Value);
                            if(rcode==0)PLC_State=6;
                            break;
                            
                    case 6: // Received Omron PLC for D memory Write                           
                            rcode = Receive_Omron_PLC_D_Write();
                            if(rcode){
                                  PLC_State=5; // error goto command again                
                            }else{
                                  PLC_State=7; // no error goto next
                            }                          
                            break; 
                                                        
                    case 7: // Finish
                          PLC_State=3;
                          break;  
            }
            
  }else{
    if(USB_RUN){
        Serial.println("USB Not RUN and Will be Reset");
        asm volatile ("  jmp 0"); 
    }
  }

}


void GetAddresses(UsbDevice *pdev)
{
    UsbDeviceAddress adr;
    adr.devAddress = pdev->address.devAddress;
    addr = adr.devAddress;
}

uint8_t Omron_PLC_Find(uint16_t Vendor_ID, uint16_t Product_ID) {
  uint8_t rcode;
  Usb.ForEachUsbDevice(&GetAddresses);
  rcode = Usb.getDevDescr(addr, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf);
  if (rcode) {
    return (rcode);
  }else{
      if(buf.idVendor == Vendor_ID &&  buf.idProduct == Product_ID){
          rcode = Usb.setConf(addr, 0, buf.bNumConfigurations);
          return (rcode);
      }else{
        return (USB_STATE_ERROR);
      }            
  }        
  return (USB_STATE_ERROR);
}



uint8_t Command_Omron_PLC_RUN_Mode() {
  uint8_t rcode;
  uint8_t msg[20] =  {0xAB,0x00,0x11,0x80,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00};
  msg[12] = random(1, 255);
  msg[13]  =0x04;
  msg[14]  =0x01;
  msg[15]  =0xFF;
  msg[16]  =0xFF;
  msg[17]  =0x04;
  uint16_t sumcheck=0;
  for(uint16_t i=0; i < 18; i++ ) {
    sumcheck +=msg[i];
  }
        
  msg[18]  =((sumcheck >> 8) & 0xFF);
  msg[19]  =(sumcheck & 0xFF); 

 rcode =  OmronPLCsend(sizeof(msg),msg);
 if(rcode)
    return rcode;

return ( rcode);
}

uint8_t Receive_Omron_PLC_RUN_Mode() {
  uint8_t rcode;
  uint8_t  buf[64];
  uint16_t rcvd=0;
  
  rcode = OmronPLCreceived(&rcvd,buf);
 // RecPrintHEX(rcvd,buf);
  
  if(rcode)
    return rcode;     

    if (rcvd==19){
        uint8_t val1=buf[rcvd-1];
        uint8_t val2=buf[rcvd-2];
        uint16_t sum1 = val2<<8 | val1;
      uint16_t sum2=0;
      for(uint16_t i=0; i < 17; i++ ) {
      sum2 +=buf[i];
      }
      
        if (sum1==sum2){           
        uint8_t revc[17] = {0xAB,0x0,0x10,0xC0,0x0,0x2,0x0,0x0,0xFB,0x0,0x0,0x0,0x30,0x4,0x1,0x0,0x0};
        for(uint16_t i=0; i < 17; i++ ){
          if(revc[i]!=buf[i] && i!=12)return (2);
        }
        return (0);
    }else{
      return (1);
    }
  }

return ( rcode);
}

uint8_t Command_Omron_PLC_D_Read(uint16_t D_number) {
  uint8_t rcode;
  uint8_t msg[25] =  {0xAB,0x00,0x16,0x80,0x00,0x2,0x00,0x00,0x00,0x00,0x00,0x00};
  msg[12] = random(1, 255);
  msg[13]  =0x01;
  msg[14]  =0x04;
  msg[15]  =0x07;
  msg[16]  =0x00;
  msg[17]  =0x00;
  msg[18]  =0x00;   
  msg[19]  =0x82;
  msg[20]  =(D_number >> 8);
  msg[21]  =(D_number & 0xFF);
  msg[22]  =0x00;
  
  uint16_t sumcheck=0;
  for(uint16_t i=0; i < 23; i++ ) {
    sumcheck +=msg[i];
  }
        
  msg[23]  =((sumcheck >> 8) & 0xFF);
  msg[24]  =(sumcheck & 0xFF);                 

rcode =  OmronPLCsend(sizeof(msg),msg);

return ( rcode);
}

uint8_t Receive_Omron_PLC_D_Read(uint16_t *D_value) {
  uint8_t rcode;
       
uint8_t  buf[64];
uint16_t rcvd=0;
rcode = OmronPLCreceived(&rcvd,buf);
//RecPrintHEX(rcvd,buf);

if(rcode)
   return rcode; 
    
    if (rcvd==24){
        uint8_t val1=buf[rcvd-1];
        uint8_t val2=buf[rcvd-2];
        uint16_t sum1 = val2<<8 | val1;
      uint16_t sum2=0;
      for(uint16_t i=0; i < 22; i++ ) {
      sum2 +=buf[i];
      }

     if (sum1==sum2){  
        uint8_t revc[18] = {0xAB,0x0,0x15,0xC0,0x0,0x2,0x0,0x0,0xFB,0x0,0x0,0x0,0x9C,0x1,0x4,0x0,0x0,0x7};
        for(uint16_t i=0; i < 18; i++ ){
          if(revc[i]!=buf[i] && i!=12)return (2);
        }   
                uint8_t val1=buf[rcvd-3];
                uint8_t val2=buf[rcvd-4];
                uint16_t value = val2<<8 | val1;
        *D_value = value;
        return (0);
    }else{
      return (1);
    }
  }
  
return (1);
}

uint8_t Command_Omron_PLC_D_Write(uint16_t D_number, uint16_t D_value) {
  uint8_t rcode;
  uint8_t msg[25] =  {0xAB,0x00,0x16,0x80,0x00,0x2,0x00,0x00,0x00,0x00,0x00,0x00};
  msg[12] = random(1, 255);
  msg[13]  =0x01;
  msg[14]  =0x02;
  msg[15]  =0x82;
  msg[16]  =(D_number >> 8);
  msg[17]  =(D_number & 0xFF);
  msg[18]  =0x00;   
  msg[19]  =0x00;
  msg[20]  =0x01;
  msg[21]  =(D_value >> 8);
  msg[22]  =(D_value & 0xFF);
  
  uint16_t sumcheck=0;
  for(uint16_t i=0; i < 23; i++ ) {
    sumcheck +=msg[i];
  }
        
  msg[23]  =((sumcheck >> 8) & 0xFF);
  msg[24]  =(sumcheck & 0xFF);          

rcode =  OmronPLCsend(sizeof(msg),msg);

return ( rcode);
}


uint8_t Receive_Omron_PLC_D_Write() {
  uint8_t rcode;
       
uint8_t  buf[64];
uint16_t rcvd=0;
rcode = OmronPLCreceived(&rcvd,buf);
//RecPrintHEX(rcvd,buf);

if(rcode)
   return rcode; 
    
    if (rcvd==19){
        uint8_t val1=buf[rcvd-1];
        uint8_t val2=buf[rcvd-2];
        uint16_t sum1 = val2<<8 | val1;
      uint16_t sum2=0;
      for(uint16_t i=0; i < 17; i++ ) {
      sum2 +=buf[i];
      }

        if (sum1==sum2){           
        uint8_t revc[17] = {0xAB,0x0,0x10,0xC0,0x0,0x2,0x0,0x0,0xFB,0x0,0x0,0x0,0x6F,0x1,0x2,0x0,0x0};
        for(uint16_t i=0; i < 17; i++ ){
          if(revc[i]!=buf[i] && i!=12)return (3);
        }
        return (0);
    }else{
      return (2);
    }
  }
  
return (1);
}



void RecPrintHEX(uint16_t nbytes, uint8_t* data){
      if(nbytes==0)return;
      for(uint16_t i=0; i < nbytes; i++ ) {
      Serial.print(" ,0x");  
      Serial.print(data[i],HEX);
      }
      Serial.println("");
}

uint8_t OmronPLCsend(uint16_t nbytes, uint8_t* data) {
    Usb.bytesWr(rSNDFIFO, nbytes, data);
    Usb.regWr(rSNDBC, nbytes);
    Usb.regWr(rHXFR, 0x21); 
    while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
    Usb.regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ   
             
  return (0);
}


uint8_t OmronPLCreceived(uint16_t *pktsize, uint8_t* data) {
  //unsigned long timeout_start = millis() + USB_XFER_TIMEOUT;
  unsigned long timeout_start = millis() + timeout;
    
  while((long)(millis() - timeout_start) < 0L) {
    Usb.regWr(rHXFR, 0x2);    
      if((Usb.regRd(rHIRQ) & bmRCVDAVIRQ)==bmRCVDAVIRQ){
      uint16_t buff_pktsize = Usb.regRd(rRCVBC);
      *pktsize = buff_pktsize;
      data = Usb.bytesRd(rRCVFIFO, buff_pktsize, data);
      Usb.regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer     
      return (0);   
      }   
   }      
             
  return (1);
}


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