mirror of
https://github.com/thiagoralves/OpenPLC_v3.git
synced 2026-09-23 23:12:19 +08:00
Added new hardware layer driver
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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__()
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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!"
|
||||
|
||||
Reference in New Issue
Block a user