Serial communication(MODBUS relay board) with PlanetCNC TNG – Part 1

This series of tutorials will try to explain and demonstrate how to use PlanetCNC TNG software for the means of serial communication.

The final goal would be a successful control of external MODBUS input/output relay board, but, to achieve this, we need to start with the basics.

 

PlanetCNC TNG software possesses all the tools for serial communication with external equipment. PlanetCNC motion controllers also support hardware UART serial interface, but this will not be a subject of this tutorial, at least not in this part.

While serial communication comes with its own rules, requirements and data framing, you would not need to worry for any of that. TNG already provides all required commands that implement serial specification so that you can just relax and read/send the data on command so to speak.

Since serial communication is associated with relatively large amount of data transfer and to make manipulation of this data easier, there is a special group of functions with a prefix array.

 

Array expression functions:

These functions are important tool for data manipulation, since serial communication requires correct data flow in a sense of sending/reading  structured data to/from designated  addresses of external devices. In short, these functions will help you to prepare the data you wish to send.

array_new() - Creates new array. Returns handle to newly created array. 
 Return value: Handle of newly created array. Handle is integer number.

array_delete(hnd) - Deletes array referenced by handle. 
  hnd - array handle
  Return value: Returns handle of the array that was just deleted, or zero if array does not exist. Returned value is integer number.  

array_clear(hnd) - Clears array data. 
  hnd - array handle
  Return value: Returns handle of the array that was just cleared, or zero if array does not exist. Returned value is integer number.

array_isvalid(hnd) - Checks if array with this handle is valid.
  hnd - array handle
  Return value: Returns value 1 for valid array, returns value 0 for invalid array. Returned value is integer number.

array_size(hnd) - Returns array data size. 
  hnd - array handle
  Return value: Returns array size. Returned value is integer number.
array_setstring(hnd, str) - Replaces array with string. Old data is cleared, array now contains only string data.  
  hnd - array handle 
  str - string data
  Return value: Returns array size. Returned value is integer number.
array_printstring(hnd) - Prints string of specified array. 
  hnd - array handle
  Return value: Returns array size. Returned value is integer number.
array_setdata(hnd,pos,data) - Sets byte data to array. Old data at position is cleared, array now contains new data. If new data is set at the end of array, data is appended.  
  hnd - array handle
  pos - data position ; 0: -start position of array -1:-end position of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  data - byte data
  Return value: Returns array size. Returned value is integer number.
array_setdata16(hnd,pos,data) - Sets two byte(16-bit) data to array. Old data at position is cleared, array now contains new data. If new data is set at the end of array, data is appended. 
  hnd - array handle
  pos - set data position ; 0: -start of array -1:-end of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  data - two byte data
  Return value: Returns array size. Returned value is integer number.
array_setdata32(hnd,pos,data) - Sets four byte(32-bit) data to array. Old data at position is cleared, array now contains new data. If new data is set at the end of array, data is appended. 
  hnd - array handle 
  pos - set data position ; 0: -start of array ; -1:-end of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) ) 
  data - four byte data
  Return value: Returns array size. Returned value is integer number.
array_printdata(hnd) - Prints array data. 
  hnd - array handle
  Return value: Returns array size. Returned value is integer number.
array_crc16(hnd,pos,len) - Calculates 16-bit CRC number.
  hnd - array handle
  pos - CRC data start position ; 0: -start of array; Other: 1,2,3...zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  len - CRC data length value ; -1:-end of array ; Other: 1,2,3...
  Return value: 16-bit CRC number. Value is integer number
array_crc32(hnd,pos,len) - Calculates 32-bit CRC number.
 hnd - array handle
 pos - CRC data start position ; 0: -start of array ; Other: 1,2,3...(zero based numbering is used (1st position has number zero, 2nd number one etc…) )
 len - CRC data length value ; -1:-end of array ; Other: 1,2,3... 
 Return value: 32-bit CRC number. Value is integer number
array_getdata(hnd,pos) - Returns byte data from array position. 
  hnd - array handle  
  pos - array data position ; 0: -first position of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  Return value: Return value is byte data. Value is integer number.
array_getdata16(hnd,pos) - Returns two byte data from array position.
  hnd - array handle 
  pos - array data position ; 0: -first position of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  Return value: Return value is two byte data. Value is integer number.
array_getdata32(hnd,pos) - Returns four byte data from array position.
  hnd - array handle 
  pos - array data position ; 0: -first position of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  Return value: Return value is four byte data. Value is integer number.
array_copy(hnd,from,pos,start,len) - Copies data from one array to another. 
  hnd - Destination array handle. Array to which we copy the data 
  from - Source array handle. Array from which we copy the data 
  pos - Destination position of copied data ; 0: -first position of array; -1: -end position ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
        If data exist it will be replaced with new data for its length. If position is -1(end position of array), data will be appended. 
  start - Source start position of data to be copied ; 0: -first position of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) ) 
  len - Length of the copied data 
  Return value: Return value is destination array size. Returned value is integer number.

array_resize(hnd,newsize) - Resizes array. 
  hnd - array handle of to be resized array
  newsize - new array size. When resizing, data can be added or removed. Negative number will preappend/remove the data at the start position of array and positive number will append/remove the data at the end position of array
  Return value: Returned value is new array size. Returned value is integer number. 

array_insert(hnd,pos,len) - Inserts byte data filled with zeros to existing array.
  hnd - array handle 
  pos - position of inserted data ; 0: -first position of array -1:-last position ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  len - length of inserted data
  Return value: Return value is array size. Returned value is integer number.

array_remove(hnd,pos,len)- Removes byte data from existing array 
  hnd - array handle
  pos - position where we want to remove the data ; 0: -first position of array ; Other: 1,2,3... (zero based numbering is used (1st position has number zero, 2nd number one etc…) )
  len - length of removed data
  Return value: Return value is array size. Returned value is integer number.

Example:

We would like to set a string data type(sequence of characters), to array with a handle name hnd. String data would be: PlanetCNC

First we need to create a array. Then we need to assign it a handle with a name hnd. Don’t forget to delete this array at the end of its use.

hnd = array_new()

In this array we need to copy string “PlanetCNC”:

array_setstring(hnd,"PlanetCNC")

We can  check the arrays data if we print its value in the output window:

array_printstring(hnd)

It is mandatory to delete the array handler at the end of its use:

array_delete(hnd)

You can use MDI input field to execute functions above. To display the expression evaluation use output window:

 

Let’s try to do this same example in a slightly different way. Since we usually want to communicate with different devices that usually provide the data in e.g. HEX type, we will set ASCII HEX representation values of the characters and achieve the same result.

To find the ASCII HEX values, use ASCII table for reference or online text to HEX converter.

The main difference is that instead of using array_setstring(), we used array_setdata() function:

Since we used HEX representation values of string PlanetCNC, array_printstring() will still print PlanetCNC:

 

To our string of characters “PlanetCNC”, we want to add HEX representation of characters ” rules!” Final text would be “PlanetCNC rules!” 

 

Here, is where we append additional data(” rules!”) to the array. Second argument “-1” defines the location of newly added data. -1 means it will be added at the end of the array.

 

With array_printdata(), we print all HEX values of array:

 

If we want to obtain desired data from a specific array location, we can use the array_getdata() function. Say we want to read the fourth byte of hnd array:

Output window will print the value of fourth byte. Decimal value 110 is equal in HEX 0x6E.

 

When sending data, there is a possibility of data corruption or data change. Receiver would somehow need to validate that the received data is indeed the one that sender intended to send.

For this purpose CRC code is used. CRC stands for “Cyclic redundancy check”, and it represents our data payload, in a form of calculated/encoded number, that is appended at the end of our data message. This way receiver can calculate the CRC of  received payload data and compare received CRC with the one it calculates on its own.

If everything is ok, both CRC numbers should be identical.

 

To generate 16-bit CRC value of the hnd array data, we can use array_crc16() function and save CRC number in the rc variable:

hnd represents the array that CRC16 function will calculate CRC number of

0 represents the start position of hnd array data

-1 represents the length or width of data to be calculated. Since -1  represents the end position of array, this means that we will calculate all data of hnd array.

rc is the variable to which we will save our CRC number.

 

Now we just need to append the 16-bit CRC value to our hnd  array and data is ready:

Since we want to append the two byte data to our array, we need to use array_setdata16() function.

hnd represents array that we will append data to

-1 represents the position of array where we will append data. -1 means that we will append it at the end position of array

rc is the variable that contains calculated CRC number, and it represents the appending data.

 

 

In the next part of this tutorial series we will describe function group for serial communication.

Serial expression functions:

serial_list - 
serial_info -

serial_open - 
serial_config - 
serial_close -

serial_write - 
serial_writedata - 
serial_writearray -

serial_read - 
serial_readdata - 
serial_readarray -

Continued at part 2:
https://planet-cnc.com/serial-communication-with-planetcnc-tng-part-2/