Beckhoff#Using TwinCAT TF7000 to read the BarCode

Good Morning and welcome to my vision Tutorial. In this tutorial I will explain how to use Tc3_Vision to read the barcode and encode the data, Display by TE1800.There are 2 new concepts that are named “Watchdog” and “Contours”.Do not worry, and I will try my best to explain it easily.Let’s Start!


Watchdogs!!!

In this tutorial , there is a new concept called “Watchdogs”. As we know, watchdog is the function that monitors overtime or something like this.This feature is very important in the Image process – Because function calls can take a long time and may affect the main control task of your control system.

Here are some case may affect the processing time:

  1. changing lighting conditions
  2. unexpected objects in the image
  3. Special Functions like  F_VN_FindContours() – The images that tokenize in the normal lighting, only 10 contours are found but 100 contours  may be found in the un normal conditions.

These abnormal operations may trigger your system to cycle overruns and be undefined behavior. 

So- Watch Dogs is very useful here and monitoring the execution time of the Functions can be stopped if the execution time is too long.

Activate

Go to your Plc project> SYSTEM>Task>your Task.

There is a checkbox called “Watchdog stack”.

Please check it.

Contours

OK, the next concept that I would like to explain is Contours.

Contours, also called an outline, is the demarcation of an object from its surroundings.

In the picture below, you may see a small red frame that is put in the barcode label.

That is the contours. 

The Contours describes these item of the object:

  • shape
  • size
  • location of that object

Fields of contours

we can find more than 1 contours in One Images and found by F_VN_FindContours().In technically all data will save as a 2D container Array.

Contour[0].point.. something.

Function block

This time I will explain the New Function/Function Blocks that are used in this tutorial.

FB_VN_WriteImage

This FB writes an image to the hard drive.

VAR_INPUT

ipImageReference To ITcVnImageThe return image that is loaded.
sFilePathSTRING The Full path of your Image file.
bWrite BOOL use a rising edge to write the image as file
nTimeout TIME VISION_ADS_TIME OUTThe time before the function is canceled.

VAR_OUTPUT

bBusyBOOL True=Function Block is running..
bErrorBOOL True=Error has occurred.
nErrorIdUDINTError information

F_VN_StartRelWatchdog

Starts a cooperative watchdog given a stop time relative to the current time.

VAR_INPUT

tStop DINT Stop time in us
hrPrevHRESULTThe last execute result

Return Value

F_VN_StartRelWatchdogHRESULTThe execute result

F_VN_StopWatchdog

Stop a watchdog and provide runtime information.

VAR_INPUT

hrStartWatchdogHRESULTThe execute result of start watchdog function

VAR_OUTPUT

nFunctionsMonitoredULINT Returns the number of functions monitored.
bEnFractionProcerrorssed UDINT Returns the fraction processed accumulated over the monitored functions in percen
tRest DINT Returns the remaining computation time in us (may be negative)

Return Value

F_VN_StopWatchdogHRESULTThe execute result


F_VN_PutTextExp

Write text into an image. 

VAR_INPUT

sText STRING Text ipDestImage
nX UDINT x coordinate (bottom left)
nYUDINT y coordinate (bottom left)
eFontType ETcVnFontType 
fFontScale LREAL Scaling factor
aColor Reference To TcVnVector4_LREALText color
nThickness DINT Line thickness
eLineType ETcVnLineType 
bBottomLeftOrigin BOOL Sets the image origin to the bottom left corner, if true
hrPrev HRESULT indicating the result of previous operation

Return Value

F_VN_PutTextExpHRESULTThe execute result


ETcVnFontType

Offers font types.

Further information

ETcVnLineType

Offers line types

F_VN_DrawContours

Here is a function that allows us to draw a single point set or multiple point sets that are interpreted as contours.

 in an Image.

  • The Contour is defined based on the Container that you passed into the function.
  • The contours that are saved into your Container are based on your find contours functions.
  • In this Tutorial, the Contours are found by function F_VN_ReadBarcodeExp()

VAR_INPUT

ipContours ITcVnContainer Single contour (ContainerType_Vector_TcVnPoint2_DINT) or multiple contours (ContainerType_Vector_Vector_TcVnPoint2_DINT)
nContourIndex DINT Index of a specific contour to be drawn (if negative, all contours within the container are drawn)
ipDestImage ITcVnImage  Destination image
eFontType ETcVnFontType 
aColor Reference To TcVnVector4_LREALText color
nThickness DINT Line thickness (if negative, the contours are filled)
hrPrev HRESULT indicating the result of previous operation

Return Value

F_VN_DrawContoursHRESULTThe execute result

F_VN_ReadBarcodeExp

This Function is the Expert version of F_VN_ReadBarCode. you can Detect and interpret a 1d barcode within the provided image and return the code position and for setting the search direction.

VAR_INPUT

ipSrcImageITcVnImageSource image Type:USINT elements, 1 channel or 3 channel if 3 channel input is expected to be RGB and internally converted to Gray.
ipDecodedDataReference ToITcVnContainerReturns the decoded code Type:ContainerType_Vector_String_SINT
ipContours ITcVnContainer Returns the code positions as contours Type:ContainerType_Vector_Vector_TcVnPoint2_DINT
eBarcodeType UDINTTypes of barcode to search for (ETcVnBarcodeType)All enum values of ETcVnBarcodeType are supoorted.
nCodeNumber DINT  How many barcodes can be searched in images.Only1 is supported.
eSearchDirectionETcVnBarcodeSearchDirection Barcode search direction.
hrPrev HRESULT indicating the result of previous operation

Return Value

F_VN_ReadBarcodeExpHRESULTThe execute result

ETcVnBarcodeSearchDirection

TCVN_BSD_ANYfirst searches in horizontal direction, then in vertical direction.
TCVN_BSD_HORIZONTALonly searches in horizontal direction
TCVN_BSD_VERTICALonly searches in vertical direction

ETcVnBarcodeType

F_VN_ExportSubContainer_String

we can use this function to export the elements into a container as a String.

Only 2D Containers with type ContainerType_Vector_String_SINT are available in this function.

VAR_INPUT

ipContours ITcVnContainer Container of type ContainerType_Vector_String_SINT
nIndex ULINTthe index of requested element
sText STRING  Text output from Container
nMaxLength ULINT 
hrPrev HRESULT indicating the result of previous operation

Return Value

F_VN_ExportSubContainer_StringHRESULTThe execute result

Implemention

Same as last post, I will not explain too much on the RoboDK Side.

Please Download the source project in the Final part of this tutorial.

Configuration

Also Same as the last tutorial, we will use the RoboDK 2D Camera Simulation interface.

and Connect with Beckhoff TwinCAT by using TF6100 OPCUA.


Flow

Here is the flow for RoboDK and twinCAT handshake.

Barcode Reading Flow

This is the Flow of how my sample program works.

It just loads the images>Read the barcode>export the string>draw the text and contours>export the image again.

OPCUA Connections

Please reference the following link to configurare an OPC UA Server.

Beckhoff#Using TwinCAT TF6100 to startup OPCUA Server | (soup01.com)

Script to Create BarCode

Here is a script to generate with random numbers.

from robolink import *  # RoboDK API
from robodk import *  # Robot toolbox
from random import choice
import barcode

defCreateRandomBarCode(i):
    sequence = [i for i in range(9)]
    BarCodeList=[]
    for _ in range(i):
        st=”
        for _ in range(13):
            sel=choice(sequence)
            st1=str(sel)
            st+=st1
#print(st)
#print(type(st))
        BarCodeList.append(st)
    return BarCodeList


BarCodeList=CreateRandomBarCode(5)
print(BarCodeList)

BASE_PATH=r’C:\images\barcode_’
for i in range(1,5):
    print(BASE_PATH+str(i)+’.png’)

data = mbox(“Enter your bar code (EAN 13 digits)”, entry=’5701234567899′)
if data is None or data is False or type(data) is not str:
    # User cancelled
    quit()
if not data.isdecimal() or len(data) != 13:
    # Invalid input
    quit()


#img = barcode.EAN13(data, writer=barcode.writer.ImageWriter())

name = “EAN13_” + data.replace(‘.’, ”).replace(‘:’, ”).replace(‘/’, ”)

filename = None
if filename is None or filename == ”:
    import_install(“tempdir”)
    import tempfile
    tempdir = tempfile.gettempdir()
    filename = r’C:\images\barcode1.png’

for i in range(len(BarCodeList)):
    img = barcode.EAN13(BarCodeList[i], writer=barcode.writer.ImageWriter())
    filename=BASE_PATH+str(i)+’.png’
    img.save(filename)


#img.save(filename)

filename += ‘.png’  # barcode .save adds the .png
import os.path
if not os.path.exists(filename):
    quit(-1)

Program

Here is the code that reads the image from the file system and then detects the Barcode. Display the information by TE1800.

VAR

VAR
//FB
FB_Images:FB_VN_ReadImage;
WriteImages:FB_VN_WriteImage;
R_TRIG1,R_TRIG2,R_TRIG5 :R_TRIG;
TON:TON;
hr,hr2:HRESULT:=S_OK;
index:ULINT;
//Pointers
ipImage:ITcVnImage;
ipDecodedData:ITcVnContainer;
stImageInfo_1:TcVnImageInfo;
ImageInfo:TcVnImageInfo;
//System Devices
read:BOOL;
readQR:BOOL;
binit:BOOL;
safetyInit:BOOL;
bwrite:BOOL;
b3,b4:BOOL;
i:INT;
//Image Information
width:UDINT;
height:UDINT;
sText:STRING;
// Watchdog
hrWD :   HRESULT;
tStop:   DINT := 50000;
tRest:   DINT;
sWatchDogTime:STRING;
// BarCode
readBarCode:BOOL;
ipCodeContourList:ITcVnContainer;
eBarcodeType              :   ETcVnBarcodeType := TCVN_BT_EAN13;
eBarcodeSearchDirection   :   ETcVnBarcodeSearchDirection := TCVN_BSD_ANY;
imagePath:STRING:=’C:\images\Images_read’;
imageMarkedPath:STRING:=’C:\images\Images_read_barcode’;
pathOrg,pathMarked:STRING;
// Color
aColorRed                 :   TcVnVector4_LREAL := [255, 0, 0];
//HMI
hmiIndex:INT;
hmis:ARRAY[1..4]OF DUT_VisionDisplay;
EmptyImageInfo:TcVnImageInfo;
END_VAR

Code

//init
IF binit THEN
IF ipImage <> 0 THEN
ipImage.TcRelease();
ipImage:=0;
END_IF
binit:=FALSE;

END_IF
//Safety Init
IF safetyInit THEN

FW_SafeRelease(ADR(ipImage));
FW_SafeRelease(ADR(ipDecodedData));
FW_SafeRelease(ADR(ipCodeContourList));
safetyInit:=FALSE;
read:=FALSE;
readQR:=FALSE;
hr:=0;
hr2:=0;
FOR i :=1 TO 4 DO
hmis[i].Code:=”;
hmis[i].Info:=EmptyImageInfo;
hmis[i].watchDog:=”;
hmis[i].urlMarked:=”;
hmis[i].urlOrg:=”;

END_FOR
i:=0;
END_IF

//HandShake with RoboDK
R_TRIG1
(CLK:=GVL_OPCUAServer.Node.Command2=1);

R_TRIG5(
CLK:=b4
OR GVL_OPCUAServer.Node.Command2 =41
);
IF R_TRIG5.Q THEN
i:=1;
b4:=TRUE;
END_IF
IF R_TRIG1.Q THEN
GVL_OPCUAServer.Node.Command1:=0;
END_IF

//BarCode Reading Program
IF b4 THEN
CASE i OF
//init the path,Release the pointer
//Trigger the Read Command
1..4:
pathOrg:=”;
pathMarked:=”;
pathOrg:=CONCAT(STR1:=imagePath,INT_TO_STRING(i));
pathOrg:=CONCAT(pathOrg,’.png’);
hmis[i].urlOrg:=pathOrg;
pathMarked:=CONCAT(STR1:=imageMarkedPath,INT_TO_STRING(i));
pathMarked:=CONCAT(pathMarked,’.png’);
hmis[i].urlMarked:=pathMarked;
i:=1+i*10;
FB_Images.bRead:=TRUE;
//Read the Image
11,21,31,41:
FB_Images(
sFilePath:=pathOrg
,ipDestImage:=ipImage
);
IF ipImage <> 0 THEN
i:=i+1;
FB_Images.bRead:=FALSE;
FB_Images(
sFilePath:=pathOrg
,ipDestImage:=ipImage
);
END_IF
//Take a 0.1s Delay
12,22,32,42:
TON(
IN:=TRUE
,PT:=T#0.1S
);
IF TON.Q THEN
TON(
IN:=FALSE
);
i:=i+1;
END_IF
//Get the Image Info Data and Transfer to HMI
13,23,33,43:
hmiIndex:=i/10;
IF hmiIndex >0 AND hmiIndex <=4 THEN
F_VN_GetImageInfo(
ipImage
,stImageInfo:=hmis[hmiIndex].Info
,hrPrev:=hr
);
i:=i+1;
END_IF
//Search the BarCode
14,24,34,44:
hrWD:=F_VN_StartRelWatchdog(tStop:=tStop,hrPrev:=hrWD);
hr:=F_VN_ReadBarcodeExp(
ipSrcImage:=ipImage
,ipDecodedData:=ipDecodedData
,ipContours:=ipCodeContourList
,eBarcodeType:=eBarcodeType
,nCodeNumber:=1
,eSearchDirection:=eBarcodeSearchDirection
,hrPrev:=hr2
);
hrWD := F_VN_StopWatchdog(hrWD, tRest => tRest);
IF SUCCEEDED(hr)  THEN
i:=i+1;
END_IF
//Image Drawing Operation
15,25,35,45:
//Export the String that Read from Image
hr := F_VN_ExportSubContainer_String(
ipContainer:=ipDecodedData
,nIndex:=0
,sText:=sText
,nMaxLength:=255
,hrPrev:=hr2
);
//Write the Code that you read to HMi
hmis[hmiIndex].Code:=sText;
//Put BarCode Values into Image
hr:=F_VN_PutTextExp(
sText:=sText
,ipDestImage:=ipImage
,nX:=20
,nY:=20
,eFontType:=ETcVnFontType.TCVN_FT_HERSHEY_PLAIN
,fFontScale:=1
,aColor:=aColorRed
,nThickness:=2
,eLineType:=TCVN_LT_4_CONNECTED
,bBottomLeftOrigin:=FALSE
,hrPrev:=hr2
);
//Draw Contours to mark out the barcode in the Image
hr:=F_VN_DrawContours(
ipContours:=ipCodeContourList
,nContourIndex:=0
,ipDestImage:=ipImage
,aColor:=aColorRed
,nThickness:=1
,hrPrev:=hr2

);
//Draw the WatchDog Time into Images
sWatchDogTime := CONCAT(CONCAT(‘Time: ‘, DINT_TO_STRING(tStop – tRest)), ‘us’);
//Put the Text
hr:=F_VN_PutTextExp(
sText:=sWatchDogTime
,ipDestImage:=ipImage
,nX:=20
,nY:=50
,eFontType:=ETcVnFontType.TCVN_FT_HERSHEY_SIMPLEX
,fFontScale:=0.5
,aColor:=aColorRed
,nThickness:=1
,eLineType:=TCVN_LT_4_CONNECTED
,bBottomLeftOrigin:=FALSE
,hrPrev:=hr2
);
//Write the Watchdog time value that you read to HMi
hmis[hmiIndex].watchDog:=sWatchDogTime;
//IF all process is OK, jumpt to next Step by +1
IF SUCCEEDED(hr) THEN
i:=i+1;
END_IF
//Write to image to file system
16,26,36,46:
IF ipImage <> 0 THEN
WriteImages(
ipImage:=ipImage
,sFilePath:=pathMarked
,bWrite:=TRUE
);

END_IF
//Release the pointer
IF (NOT WriteImages.bBusy AND NOT WriteImages.bError)
OR WriteImages.bError
THEN
bWrite:=FALSE;
WriteImages(
bWrite:=FALSE
,sFilePath:=pathMarked
);
FW_SafeRelease(ADR(ipImage));
FW_SafeRelease(ADR(ipDecodedData));
FW_SafeRelease(ADR(ipCodeContourList));
//Check the step again
//To Do list:any Clever way?
//if Step=46, all image are read and back to 0.
CASE i OF
16:
i:=2;
26:
i:=3;
36:
i:=4;
46:
i:=0;
b4:=FALSE;
//A ungly step, finding way to get the status from RoboDK that the Program is finished
GVL_OPCUAServer.Node.Command2:=0;
END_CASE

END_IF;
END_CASE
END_IF

Visualization

Here is the screen for me to display the image information.


Sample Code

TwinCAT3/TwinCAT Project_Vision_Part2_ReadBarCode.zip at main · soup01Threes/TwinCAT3 (github.com)

Result

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする