Easy Acces to digital GPIOs on arm platform
- Karsten Hoffmann
- Visitor
8 years 10 months ago - 8 years 10 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:
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.
Here are the ascii functions used above:
You have to copy the VAR_GLOBAL CONSTANT section to your resource
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
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:
Code:
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.
Code:
/*
* 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
Code:
// 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
Code:
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
Last edit: 8 years 10 months ago by Karsten Hoffmann. Reason: to be more precise: the program example only reads the digital inputs on Beagle-IO board
Please Anmelden or Create an account to join the conversation.