Sunday, November 1, 2015

PLC - Mini LCD Touch Screen - Arduino




How to make HMI Screen using mini LCD Touch Screen?
This application about make 2.4 inch TFT LCD Touch Screen such as mini HMI Screen and Simple HMI.
TFT LCD  connect to Arduino , and then arduino connected to PLC via Modbus communication.
The HMI application for simple applications such as HMI to replace the switch with a switch design using pictures / images.

Video Demonstration about Mini LCD Touch Screen and Arduino Connected to PLC via Modbus Communication



Hardware Needed

  1. Arduino UNO
  2. 2.4 inch TFT LCD Touch Screen Shield
  3. Arduino Proto Screw Shield for Arduino UNO
  4. Micro SD Card, I use 2GB Micro SD Card
  5. Male RS-232 to TTL Module
  6. PLC with Modbus Support, I use Siemens S7-200
  7. RS-232 PLC Cable, I use PPI RS-232 for Siemens S7-200
  8. Power Supply for Arduino

Hardware of PLC - Mini LCD Touch Screen - Arduino


Hardware Connections


Hardware Connections of PLC - Mini LCD Touch Screen - Arduino


Software Needed

  1. I use Arduino Software 1.6.6 Hourly Build : http://downloads.arduino.cc/arduino-nightly-windows.zip
  2. Backup all folder file in C:\arduino-nightly\libraries to another folder
  3. Delete all folder file in C:\arduino-nightly\libraries
  4. Download libraries : click here
  5. Unzip libraries and copy paste all folder to C:\arduino-nightly\libraries
  6. In C:\arduino-nightly\libraries only folder : AdafruitGFXLibrary , SD , SimpleModbusMaster , TFTLCDLibrary , and TouchScreenLibrary.

Arduino libraries of PLC - Mini LCD Touch Screen - Arduino


Project File for Arduino

  1. Download image file: click here
  2. Copy paste images file into micro SD Card, only files: hmi.bmp and lamp.bmp (not include folder)
  3. Download project file and Upload to Arduino : click here


Project File for PLC

  1. Download PLC Ladder Programming for Siemens S7-200 : click here
  2. Download to Siemens S7-200 PLC


Touch Position

Data for Touch Position in PLC Memory and used to Touch Area Setting (Position X , Position Y)

Touch Position in PLC Memory

Touch Position X : Modbus Holding Register 40000 / I use VW800 in S7-200
Touch Position Y : Modbus Holding Register 40001 / I use VW802 in S7-200


Touch Area Setting for Menu Pressed / Button Pressed

A. Touch Area Setting for Menu Pressed

Touch Area Setting for Menu Pressed

Press Green point, and get value from PLC Memory VW800 and VW802.
The following Touch Position for change image / menu:
  1. for change to lamp.bmp image with touch position (880,190) and (780,140)
  2. for change to hmi.bmp image with touch position (280,190) and (180,120)


B. Touch Area Setting for Button Pressed

Touch Area Setting for Button Pressed

Press Red point, and get value from PLC Memory VW800 and VW802.

The following Touch Position for Button Pressed:
  1. Menu 0 : lamp.bmp image
    • Lamp ON with touch position (631,518) and (203,242)
    • Lamp OFF with touch position (804,927) and (475,725)

  2. Menu 1: hmi.bmp image
    • Button1 ON with touch position (403,854) and (270,682)
    • Button2 OFF with touch position (383,468) and (273,297)
    • Button3 ON with touch position (760,862) and (669,698)
    • Button4 OFF with touch position (779,476) and (685,316)


Arduino Code for TFT LCD Touch Screen Connect to PLC via Modbus


#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>
#include <SD.h>
#include <SPI.h>
#include "TouchScreen.h"

#define YP A1
#define XM A2
#define YM 7
#define XP 6

#define MINPRESSURE 10
#define MAXPRESSURE 1000

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0

#include <EEPROM.h>
#include <SimpleModbusMaster.h>
//Arduino Serial Port Connect to Port 0 of Siemens S7-200 PLC 
#define slaveAddr 1
#define baud 9600
#define timeout 1000
#define polling 200
#define retry_count 0
#define TxEnablePin 2 
enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];
packetPointer packet1 = &packets[PACKET1];
unsigned int writeRegs[8];

#define SD_CS 10  


Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

int address = 0;
byte currentmenu;
uint16_t identifier;

void setup()
{
 currentmenu = EEPROM.read(address);
 modbus_construct(packet1, slaveAddr, PRESET_MULTIPLE_REGISTERS, 0, 8, writeRegs);
 modbus_configure(&Serial, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);  

 tft.reset();

  identifier = tft.readID();

  if(identifier == 0x9325) {
  } else if(identifier == 0x9327) {
  } else if(identifier == 0x9328) {
  } else if(identifier == 0x7575) {
  } else if(identifier == 0x9341) {
  } else if(identifier == 0x8357) {
  } else if(identifier == 0x0154) {
  } else if(identifier == 0x9488) {
  } else {
    return;
  }

  tft.begin(identifier);
  tft.setRotation(1);
  tft.setCursor(0, 0);
  tft.setTextColor(0xFFFF);  
  tft.setTextSize(2);
  tft.println("  Initializing SD card...");   
  if (!SD.begin(SD_CS)) {
    tft.println(); 
    tft.println("  SD card failed!"); 
    return;
  }
  tft.println();
  tft.println("  SD card OK!");
  tft.setRotation(0);
  if(currentmenu==1){
    currentmenu=1;
    bmpDraw("hmi.bmp", 0, 0);
  }else{
    currentmenu=0;
    bmpDraw("lamp.bmp", 0, 0);
  }

}


int nopressescount = 0;

void loop()
{
  TSPoint dw,up;
  dw = ts.getPoint();
  if (dw.z > MINPRESSURE && dw.z < MAXPRESSURE) {
  nopressescount = 0;
  writeRegs[0] = (word) dw.x;
  writeRegs[1] = (word) dw.y;

  if(currentmenu!=0 && TouchRech(dw.x,dw.y,880,190,780,140)){
   currentmenu=0;
   EEPROM.write(address, currentmenu);
   asm volatile ( "jmp 0");
  }
  
  if(currentmenu!=1 && TouchRech(dw.x,dw.y,280,190,180,120)){
   currentmenu=1;
   EEPROM.write(address, currentmenu);
   asm volatile ( "jmp 0");
  }
  
  if(currentmenu==0){
  writeRegs[6] = (word)TouchRech(dw.x,dw.y,631,518,203,242);
  writeRegs[7] = (word)TouchRech(dw.x,dw.y,804,927,475,725);  
  }  
  
  if(currentmenu==1){
  writeRegs[2] = (word)TouchRech(dw.x,dw.y,403,854,270,682);
  writeRegs[3] = (word)TouchRech(dw.x,dw.y,383,468,273,297);
  writeRegs[4] = (word)TouchRech(dw.x,dw.y,760,862,669,698);
  writeRegs[5] = (word)TouchRech(dw.x,dw.y,779,476,685,316);  
  }
  }else{    
    nopressescount++;
    if(nopressescount>100){
    memset(writeRegs,0,sizeof(writeRegs));
    nopressescount = 0; 
    } 
    
  }
 
  modbus_update();
}

bool TouchRech(int16_t px, int16_t py, int16_t x0, int16_t y0,int16_t x1, int16_t y1) {
      bool xvalid = false;
      bool yvalid = false;
     if (x0>x1){
        if(x1<px && px<x0)xvalid=true;      
     }else{
        if(x0<px && px<x1)xvalid=true;
     }
     if (y0>y1){
        if(y1<py && py<y0)yvalid=true;      
     }else{
        if(y0<py && py<y1)yvalid=true;
     }
  if(xvalid && yvalid){
    return true;
  }else{
    return false;
  }
}

#define BUFFPIXEL 20

void bmpDraw(char *filename, int x, int y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   
  uint8_t  bmpDepth;              
  uint32_t bmpImageoffset;        
  uint32_t rowSize;               
  uint8_t  sdbuffer[3*BUFFPIXEL]; 
  uint16_t lcdbuffer[BUFFPIXEL];  
  uint8_t  buffidx = sizeof(sdbuffer); 
  boolean  goodBmp = false;       
  boolean  flip    = true;       
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if((x >= tft.width()) || (y >= tft.height())) return;

  if ((bmpFile = SD.open(filename)) == NULL) {
    //Serial.println(F("File not found"));
    return;
  }

  if(read16(bmpFile) == 0x4D42) { 
    read32(bmpFile);
    (void)read32(bmpFile);
    bmpImageoffset = read32(bmpFile);
    read32(bmpFile);
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { 
      bmpDepth = read16(bmpFile); 
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) {
        goodBmp = true;
        rowSize = (bmpWidth * 3 + 3) & ~3;
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) {
          if(flip)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else  
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { 
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer);
          }

          for (col=0; col<w; col++) {
            if (buffidx >= sizeof(sdbuffer)) { 
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0;
            }

            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          }
        } 

        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        } 

      }
    }
  }

  bmpFile.close();
  //if(!goodBmp) Serial.println(F("BMP format not recognized."));
}

uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read();
  ((uint8_t *)&result)[1] = f.read();
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read();
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read();
  return result;
}


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