Easy Acces to digital GPIOs on arm platform

  • Karsten Hoffmann
  • Topic Author
  • Visitor
  • Visitor
3 years 9 months ago - 3 years 9 months ago #167 by Karsten Hoffmann
Easy Acces to digital GPIOs on arm platform was created by Karsten Hoffmann
It is possible to acces the GPIOs of an arm SOC like the BeagleBone Black in logi.CAD 3 compact.

Normaly In Linux on arm SOCs the GPIOs are mapped to the file system.
To get acces to Linux GPIO 66 on BeagleBone Black as digital input, you have to do something like this:
root@beaglebone:~# echo 66 > /sys/class/gpio/export
root@beaglebone:~# echo in > /sys/class/gpio/gpio66/direction
root@beaglebone:~# cat /sys/class/gpio/gpio66/value
1
root@beaglebone:~#

How to do this in logi.CAD 3 compact?

It is a little more complicated, so here is a function set to easy access the GPIOs
In these GPIO functions the ascii functions Asc and Chr are used.
Cause these functions are not implemented in logi.CAD 3 compact yet, you will need these functions too.
Listing is down below.

You also can download the two zip files and import them to your project.
/*
 * Function set to easy access digital GPIO's on arm platforms
 */

/*
 * initializes a GPIO                   <br>
 *                                      <br>
 * takes the Linux GPIO Number as STRING<br>
 *                                      <br>
 * example:                             <br>
 * initGPIO('66');
 */
FUNCTION initGPIO
 VAR_INPUT
   gpio  :STRING[3];
 END_VAR
 VAR
   FD      :DINT;
    data    :ARRAY[0..63]OF BYTE;
   write   :DINT:=1;
   length    :UINT;
    count   :UINT;
    openENO   :BOOL;
    writeENO  :BOOL;
  END_VAR
 length:=LEN(gpio);
  FD:=System_open(pathname:='/sys/class/gpio/export',flags:=write,ENO=>openENO);
  IF openENO THEN
   FOR count:=0 TO length-1 DO
     data[count]:=TO_BYTE(Asc(gpio[count+1]));
   END_FOR;
    System_write(fd:=FD,data:=data,count:=length,ENO=>writeENO);
    IF writeENO THEN
      System_close(fd:=FD);
     ENO:=TRUE;
    ELSE
      ENO:=FALSE;
   END_IF;
 ELSE
    ENO:=FALSE;
 END_IF;
END_FUNCTION

/*
 * deinitializes a GPIO                 <br>
 *                                      <br>
 * takes the Linux GPIO Number as STRING<br>
 *                                      <br>
 * example:                             <br>
 * deinitGPIO('66');
 */
FUNCTION deinitGPIO
 VAR_INPUT
   gpio  :STRING[3];
 END_VAR
 VAR
   FD    :DINT;
    data  :ARRAY[0..63]OF BYTE;
   write :DINT:=1;
   length  :UINT;
    count :UINT;
  END_VAR
 length:=LEN(gpio);
  FD:=System_open(pathname:='/sys/class/gpio/unexport',flags:=write);
 FOR count:=0 TO length-1 DO
   data[count]:=TO_BYTE(Asc(gpio[count+1]));
 END_FOR;
  System_write(fd:=FD,data:=data,count:=length);
  System_close(fd:=FD);
END_FUNCTION

/*
 * set a GPIO as input                  <br>
 *                                      <br>
 * takes the Linux GPIO Number as STRING<br>
 *                                      <br>
 * example:                             <br>
 * setGPIOinput('66');
 */
FUNCTION setGPIOinput
 VAR_INPUT
   gpio  :STRING[3];
 END_VAR
 VAR
   FD      :DINT;
    write   :DINT:=1;
   pathName  :STRING[255];
   data    :ARRAY[0..63]OF BYTE;
   openENO   :BOOL;
    writeENO  :BOOL;
  END_VAR
 // put 'in' to payload
  data[0]:=TO_BYTE(Asc('i'));
 data[1]:=TO_BYTE(Asc('n'));
 pathName:='/sys/class/gpio/gpio';
 pathName:=CONCAT(pathName,gpio,'/direction');
 system_open(pathname:=pathName,flags:=write,ENO=>openENO);
  IF openENO THEN
   system_write(fd:=FD,data:=data,count:=2,ENO=>writeENO);
   IF writeENO THEN
      ENO:=TRUE;
    ELSE
      ENO:=FALSE;
   END_IF; 
    system_close(fd:=FD);
 ELSE
    ENO:=FALSE;
 END_IF;
END_FUNCTION

/*
 * set a GPIO as output                 <br>
 *                                      <br>
 * takes the Linux GPIO Number as STRING<br>
 *                                      <br>
 * example:                             <br>
 * setGPIOoutput('66');
 */
FUNCTION setGPIOoutput
 VAR_INPUT
   gpio  :STRING[3];
 END_VAR
 VAR
   FD      :DINT;
    write   :DINT:=1;
   pathName  :STRING[255];
   data    :ARRAY[0..63]OF BYTE;
   openENO   :BOOL;
    writeENO  :BOOL;
  END_VAR
 // put 'out' to payload
 data[0]:=TO_BYTE(Asc('o'));
 data[1]:=TO_BYTE(Asc('u'));
 data[2]:=TO_BYTE(Asc('t'));
 pathName:='/sys/class/gpio/gpio';
 pathName:=CONCAT(pathName,gpio,'/direction');
 system_open(pathname:=pathName,flags:=write,ENO=>openENO);
  IF openENO THEN
   system_write(fd:=FD,data:=data,count:=3,ENO=>writeENO);
   IF writeENO THEN
      ENO:=TRUE;
    ELSE
      ENO:=FALSE;
   END_IF; 
    system_close(fd:=FD);
 ELSE
    ENO:=FALSE;
 END_IF;
END_FUNCTION

/*
 * open a GPIO to read or write         <br>
 *                                      <br>
 * takes the Linux GPIO Number as STRING<br>
 * and a flag:                          <br>
 * 0 for reading                        <br>
 * 1 for writing                        <br>
 *                                      <br>
 * example:                             <br>
 * openGPIO('66',0);
 */
FUNCTION openGPIO :DINT
 VAR_INPUT
   gpio  :STRING[3];
   flag  :DINT;
  END_VAR
 VAR
   FD      :DINT;
    pathName  :STRING[255];
   openENO   :BOOL;
  END_VAR
 pathName:='/sys/class/gpio/gpio';
 pathName:=CONCAT(pathname,gpio,'/value');
 FD:=System_open(pathname:=pathName,flags:=flag,ENO=>openENO);
 IF openENO THEN
   openGPIO:=FD;
   ENO:=TRUE;
  ELSE
    openGPIO:=-1;
   ENO:=FALSE;
 END_IF;
END_FUNCTION

/*
 * reads the value from a GPIO          <br>
 *                                      <br>
 * takes the Linux fileDescriptor       <br>
 * given by the openGPIO function       <br>
 *                                      <br>
 * example:                             <br>
 * DI:=readGPIO(fileDescriptor);
 */
FUNCTION readGPIO :BOOL
 VAR_INPUT
   fileDescriptor  :DINT;
  END_VAR
 VAR
   data  :ARRAY[0..63]OF BYTE;
   readENO :BOOL;
  END_VAR
 System_read(fd:=fileDescriptor,data=>data,count:=1,ENO=>readENO);
 IF readENO THEN
   IF Chr(TO_USINT(data[0]))='1' THEN
      readGPIO:=TRUE;
   ELSE
      readGPIO:=FALSE;
    END_IF;
   ENO:=TRUE;
  ELSE
    readGPIO:=FALSE;
    ENO:=FALSE;
 END_IF;
END_FUNCTION

/*
 * writes value to a GPIO               <br>
 *                                      <br>
 * takes the Linux fileDescriptor       <br>
 * given by the openGPIO function       <br>
 * and the value as BOOL                <br>
 *                                      <br>
 * example:                             <br>
 * writeGPIO(fileDescriptor,TRUE);
 */
FUNCTION writeGPIO  :BOOL
 VAR_INPUT
   fileDescriptor  :DINT;
    value     :BOOL;
  END_VAR
 VAR
   data    :ARRAY[0..63]OF BYTE;
   writeENO  :BOOL;
  END_VAR
 IF value THEN
   data[0]:=TO_BYTE(Asc('1'));
 ELSE
    data[0]:=TO_BYTE(Asc('0'));
 END_IF;
 System_write(fd:=fileDescriptor,data:=data,count:=1,ENO=>writeENO);
 IF writeENO THEN
    ENO:=TRUE;
  ELSE
    ENO:=FALSE;
 END_IF;
END_FUNCTION

Here are the ascii functions used above:

You have to copy the VAR_GLOBAL CONSTANT section to your resource
// copy this to your resource
//
//  VAR_GLOBAL CONSTANT
//   ascii_characters  :ARRAY[0..255]OF CHAR :=
//    [
//     '$00','$01','$02','$03','$04','$05','$06','$07','$08','$09','$0A','$0B','$0C','$0D','$0E','$0F',
//      '$10','$11','$12','$13','$14','$15','$16','$17','$18','$19','$1A','$1B','$1C','$1D','$1E','$1F',
//      '$20','$21','$22','$23','$24','$25','$26','$27','$28','$29','$2A','$2B','$2C','$2D','$2E','$2F',
//      '$30','$31','$32','$33','$34','$35','$36','$37','$38','$39','$3A','$3B','$3C','$3D','$3E','$3F',
//      '$40','$41','$42','$43','$44','$45','$46','$47','$48','$49','$4A','$4B','$4C','$4D','$4E','$4F',
//      '$50','$51','$52','$53','$54','$55','$56','$57','$58','$59','$5A','$5B','$5C','$5D','$5E','$5F',
//      '$60','$61','$62','$63','$64','$65','$66','$67','$68','$69','$6A','$6B','$6C','$6D','$6E','$6F',
//      '$70','$71','$72','$73','$74','$75','$76','$77','$78','$79','$7A','$7B','$7C','$7D','$7E','$7F',
//      '$80','$81','$82','$83','$84','$85','$86','$87','$88','$89','$8A','$8B','$8C','$8D','$8E','$8F',
//      '$90','$91','$92','$93','$94','$95','$96','$97','$98','$99','$9A','$9B','$9C','$9D','$9E','$9F',
//      '$A0','$A1','$A2','$A3','$A4','$A5','$A6','$A7','$A8','$A9','$AA','$AB','$AC','$AD','$AE','$AF',
//      '$B0','$B1','$B2','$B3','$B4','$B5','$B6','$B7','$B8','$B9','$BA','$BB','$BC','$BD','$BE','$BF',
//      '$C0','$C1','$C2','$C3','$C4','$C5','$C6','$C7','$C8','$C9','$CA','$CB','$CC','$CD','$CE','$CF',
//      '$D0','$D1','$D2','$D3','$D4','$D5','$D6','$D7','$D8','$D9','$DA','$DB','$DC','$DD','$DE','$DF',
//      '$E0','$E1','$E2','$E3','$E4','$E5','$E6','$E7','$E8','$E9','$EA','$EB','$EC','$ED','$EE','$EF',
//      '$F0','$F1','$F2','$F3','$F4','$F5','$F6','$F7','$F8','$F9','$FA','$FB','$FC','$FD','$FE','$FF'
//   ];
//  END_VAR

/*
 * This function gives the ASCII code of a character
 */
FUNCTION Asc :USINT
 VAR_EXTERNAL CONSTANT
   ascii_characters  :ARRAY[0..255]OF CHAR;
  END_VAR
 VAR_INPUT
   character :CHAR;
  END_VAR
 VAR
   count :USINT;                   
  END_VAR
 FOR count:=0 TO 255 DO
    IF character = ascii_characters[count] THEN
     Asc:=count;
   END_IF;
 END_FOR;
END_FUNCTION

/*
 * This function gives a character from an ASCII code
 */
FUNCTION Chr :CHAR
  VAR_EXTERNAL CONSTANT
   ascii_characters  :ARRAY[0..255]OF CHAR;
  END_VAR
 VAR_INPUT
   num :USINT;
 END_VAR
 Chr:=ascii_characters[num];
END_FUNCTION

To import the zip files you have to right click on your src folder and chose import
click on archive, select the zip file and open.

This imports the iecst files to your src folder and you can use the functions.

Here's a little Program to get the digital inputs from the Beagle-IO board

BeagleBone IO cape
FUNCTION initGPIOs
 initGPIO('66');
 initGPIO('67');
 initGPIO('69');
 initGPIO('68');
 initGPIO('45');
 initGPIO('44');
 initGPIO('23');
 initGPIO('26');
 initGPIO('47');
 initGPIO('46');
 initGPIO('27');
 initGPIO('65');
END_FUNCTION

FUNCTION setGPIOsInput
 setGPIOinput('66');
 setGPIOinput('67');
 setGPIOinput('69');
 setGPIOinput('68');
 setGPIOinput('45');
 setGPIOinput('44');
 setGPIOinput('23');
 setGPIOinput('26');
 setGPIOinput('47');
 setGPIOinput('46');
 setGPIOinput('27');
 setGPIOinput('65');
END_FUNCTION

FUNCTION deinitGPIOs
 deinitGPIO('66');
 deinitGPIO('67');
 deinitGPIO('69');
 deinitGPIO('68');
 deinitGPIO('45');
 deinitGPIO('44');
 deinitGPIO('23');
 deinitGPIO('26');
 deinitGPIO('47');
 deinitGPIO('46');
 deinitGPIO('27');
 deinitGPIO('65');
END_FUNCTION

PROGRAM IOProgram
  VAR_EXTERNAL
    digitalInput01  :BOOL;
    digitalInput02  :BOOL;
    digitalInput03  :BOOL;
    digitalInput04  :BOOL;
    digitalInput05  :BOOL;
    digitalInput06  :BOOL;
    digitalInput07  :BOOL;
    digitalInput08  :BOOL;
    digitalInput09  :BOOL;
    digitalInput10  :BOOL;
    digitalInput11  :BOOL;
    digitalInput12  :BOOL;
  END_VAR

 VAR
   init  :BOOL;
    run   :BOOL;
    term  :BOOL;
  END_VAR

 VAR
   FD_GPIO_66  :DINT;
    FD_GPIO_67  :DINT;
    FD_GPIO_69  :DINT;
    FD_GPIO_68  :DINT;
    FD_GPIO_45  :DINT;
    FD_GPIO_44  :DINT;
    FD_GPIO_23  :DINT;
    FD_GPIO_26  :DINT;
    FD_GPIO_47  :DINT;
    FD_GPIO_46  :DINT;
    FD_GPIO_27  :DINT;
    FD_GPIO_65  :DINT;
    read    :DINT:=0;
 END_VAR
 
  RTSCycleInfo(Init=>init,Run=>run,Term=>term);
 
  IF init THEN
    Trace('Begin init');
    initGPIOs();
    setGPIOsInput();
    FD_GPIO_66:=openGPIO('66', read);
   FD_GPIO_67:=openGPIO('67', read);
   FD_GPIO_69:=openGPIO('69', read);
   FD_GPIO_68:=openGPIO('68', read);
   FD_GPIO_45:=openGPIO('45', read);
   FD_GPIO_44:=openGPIO('44', read);
   FD_GPIO_23:=openGPIO('23', read);
   FD_GPIO_26:=openGPIO('26', read);
   FD_GPIO_47:=openGPIO('47', read);
   FD_GPIO_46:=openGPIO('46', read);
   FD_GPIO_27:=openGPIO('27', read);
   FD_GPIO_65:=openGPIO('65', read);
   Trace('Done init');
 END_IF;
 
  IF run THEN
   digitalInput01:=readGPIO(FD_GPIO_66);
   digitalInput02:=readGPIO(FD_GPIO_67);
   digitalInput03:=readGPIO(FD_GPIO_69);
   digitalInput04:=readGPIO(FD_GPIO_68);
   digitalInput05:=readGPIO(FD_GPIO_45);
   digitalInput06:=readGPIO(FD_GPIO_44);
   digitalInput07:=readGPIO(FD_GPIO_23);
   digitalInput08:=readGPIO(FD_GPIO_26);
   digitalInput09:=readGPIO(FD_GPIO_47);
   digitalInput10:=readGPIO(FD_GPIO_46);
   digitalInput11:=readGPIO(FD_GPIO_27);
   digitalInput12:=readGPIO(FD_GPIO_65);
 END_IF;
 
  if term THEN
    Trace('Begin deinit');
    System_close(FD_GPIO_66);
   System_close(FD_GPIO_67);
   System_close(FD_GPIO_69);
   System_close(FD_GPIO_68);
   System_close(FD_GPIO_45);
   System_close(FD_GPIO_44);
   System_close(FD_GPIO_23);
   System_close(FD_GPIO_26);
   System_close(FD_GPIO_47);
   System_close(FD_GPIO_46);
   System_close(FD_GPIO_27);
   System_close(FD_GPIO_65);
   deinitGPIOs();
    Trace('Done deinit');
 END_IF;
END_PROGRAM

File Attachment:

File Name: gpio.zip
File Size:1 KB

File Attachment:

File Name: ascii.zip
File Size:1 KB
Attachments:
Last edit: 3 years 9 months ago by Karsten Hoffmann. Reason: to be more precise: the program example only reads the digital inputs on Beagle-IO board

Please Log in or Create an account to join the conversation.

LOGI.CALS AUSTRIA

Address

Europaplatz 7/1,
3100 St. Pölten

LOGI.CALS GERMANY

Address

Postfach 1306,
40738 Langenfeld
© 1987 - 2019 logi.cals GmbH