Added new hardware layer driver

This commit is contained in:
Autonomy Server
2023-11-16 14:05:30 -05:00
parent 2716efcd16
commit b6f6fe3bd6
7 changed files with 281 additions and 3 deletions
+181
View File
@@ -0,0 +1,181 @@
//-----------------------------------------------------------------------------
// Copyright 2015 Thiago Alves
//
// This file is part of the OpenPLC Runtime.
//
// OpenPLC is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenPLC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OpenPLC. If not, see <http://www.gnu.org/licenses/>.
//------
//
// This file is the hardware layer for the OpenPLC. If you change the platform
// where it is running, you may only need to change this file. All the I/O
// related stuff is here. Basically it provides functions to read and write
// to the OpenPLC internal buffers in order to update I/O state.
// Thiago Alves, Dec 2015
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include "ladder.h"
#include "custom_layer.h"
#define I2C_DEVICE_PATH "/dev/i2c-1"
#define I2C_ADDRESS 0x1C
#define SWITCH_REG_1 0x03
#define SWITCH_REG_2 0x02
#define SWITCH_REG_3 0x00
int i2cHandle = -1;
int16_t initI2C()
{
i2cHandle = open(I2C_DEVICE_PATH, O_RDWR);
if (i2cHandle < 0)
{
perror("Error opening I2C device");
return -1;
}
if (ioctl(i2cHandle, I2C_SLAVE, I2C_ADDRESS) < 0)
{
perror("Error setting I2C address");
close(i2cHandle);
return -1;
}
return 0;
}
void closeI2C()
{
close(i2cHandle);
}
int16_t getSwitchId()
{
if (i2cHandle == -1)
{
int ret = initI2C();
if (ret < 0)
{
return -1;
}
}
char buf[1];
buf[0] = SWITCH_REG_1;
buf[1] = 0xFF;
if (write(i2cHandle, buf, 2) != 2)
{
perror("Error writing to register");
return -1;
}
buf[0] = SWITCH_REG_2;
buf[1] = 0x00;
if (write(i2cHandle, buf, 2) != 2)
{
perror("Error writing to register");
return -1;
}
buf[0] = SWITCH_REG_3;
if (write(i2cHandle, buf, 1) != 1)
{
perror("Error writing to register");
return -1;
}
if (read(i2cHandle, buf, 1) != 1)
{
perror("Error reading from register");
return -1;
}
int8_t retData = buf[0];
if (retData >= 0 && retData <= 9)
{
return retData;
}
return -1;
}
//-----------------------------------------------------------------------------
// This function is called by the main OpenPLC routine when it is initializing.
// Hardware initialization procedures should be here.
//-----------------------------------------------------------------------------
void initializeHardware()
{
}
//-----------------------------------------------------------------------------
// This function is called by the main OpenPLC routine when it is finalizing.
// Resource clearing procedures should be here.
//-----------------------------------------------------------------------------
void finalizeHardware()
{
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersIn()
{
pthread_mutex_lock(&bufferLock); //lock mutex
/*********READING AND WRITING TO I/O**************
*bool_input[0][0] = read_digital_input(0);
write_digital_output(0, *bool_output[0][0]);
*int_input[0] = read_analog_input(0);
write_analog_output(0, *int_output[0]);
**************************************************/
pthread_mutex_unlock(&bufferLock); //unlock mutex
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
pthread_mutex_lock(&bufferLock); //lock mutex
/*********READING AND WRITING TO I/O**************
*bool_input[0][0] = read_digital_input(0);
write_digital_output(0, *bool_output[0][0]);
*int_input[0] = read_analog_input(0);
write_analog_output(0, *int_output[0]);
**************************************************/
pthread_mutex_unlock(&bufferLock); //unlock mutex
}
+60
View File
@@ -0,0 +1,60 @@
int16_t initI2C();
void closeI2C();
int16_t getSwitchId();
// FUNCTION_BLOCK ROTARY_SWITCH
// Data part
typedef struct {
// FB Interface - IN, OUT, IN_OUT variables
__DECLARE_VAR(BOOL,EN)
__DECLARE_VAR(BOOL,ENO)
__DECLARE_VAR(BOOL,READ)
__DECLARE_VAR(BOOL,ERROR)
__DECLARE_VAR(INT,OUT)
// FB private variables - TEMP, private and located variables
} ROTARY_SWITCH;
static void ROTARY_SWITCH_init__(ROTARY_SWITCH *data__, BOOL retain);
// Code part
static void ROTARY_SWITCH_body__(ROTARY_SWITCH *data__);
static void ROTARY_SWITCH_init__(ROTARY_SWITCH *data__, BOOL retain) {
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
__INIT_VAR(data__->READ,__BOOL_LITERAL(FALSE),retain)
__INIT_VAR(data__->ERROR,__BOOL_LITERAL(FALSE),retain)
__INIT_VAR(data__->OUT,0,retain)
}
// Code part
static void ROTARY_SWITCH_body__(ROTARY_SWITCH *data__) {
// Control execution
if (!__GET_VAR(data__->EN)) {
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
return;
}
else {
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
}
// Initialise TEMP variables
if ((__GET_VAR(data__->READ,) == __BOOL_LITERAL(TRUE))) {
int16_t rotary_read = getSwitchId();
if (rotary_read < 0)
{
__SET_VAR(data__->,OUT,,0);
__SET_VAR(data__->,ERROR,,1);
}
else
{
__SET_VAR(data__->,OUT,,rotary_read);
__SET_VAR(data__->,ERROR,,0);
}
}
goto __end;
__end:
return;
} // ROTARY_SWITCH_body__()
+3
View File
@@ -1889,6 +1889,9 @@ __end:
#if defined(__linux__) && defined(__arm__) && defined(SEQUENT)
#include "sm_cards.h"
#endif
#if defined(__linux__) && defined(__arm__) && defined(SL_RP4)
#include "SL-RP4.h"
#endif
+14
View File
@@ -0,0 +1,14 @@
FUNCTION_BLOCK ROTARY_SWITCH
VAR_INPUT
READ : BOOL;
END_VAR
VAR_OUTPUT
ERROR : BOOL;
OUT : INT;
END_VAR
IF READ = TRUE THEN
OUT := 0;
END_IF;
END_FUNCTION_BLOCK
+1
View File
@@ -45,5 +45,6 @@
{#include "sema.txt" }
{#include "communication_blocks.txt" }
{#include "sm_cards.txt" }
{#include "SL-RP4.txt" }
{enable code generation}
@@ -115,6 +115,13 @@ elif [ "$1" == "sequent" ]; then
echo rpi > ../scripts/openplc_platform
echo sequent > ../scripts/openplc_driver
elif [ "$1" == "sl_rp4" ]; then
echo "Activating SL-RP4 driver"
cp ./hardware_layers/SL-RP4.cpp ./hardware_layer.cpp
echo "Setting Platform"
echo linux > ../scripts/openplc_platform
echo sl_rp4 > ../scripts/openplc_driver
else
echo "Error: Invalid hardware layer"
fi
+15 -3
View File
@@ -78,13 +78,21 @@ if [ "$OPENPLC_PLATFORM" = "win" ]; then
elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
echo "Compiling for Linux"
echo "Generating object files..."
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSL_RP4
else
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
exit 1
fi
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC -DSL_RP4
else
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
@@ -93,7 +101,11 @@ elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC -DSL_RP4
else
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"