Updated simulink models and modbus_tcp code to most recent version
This commit is contained in:
parent
c3e0677ce4
commit
e82bbf20de
@ -1,5 +1,4 @@
|
|||||||
#include "modbus_tcp_client.h"
|
#include "modbus_tcp_client.h"
|
||||||
#include <sys/select.h>
|
|
||||||
|
|
||||||
// --- Helper: Compute maximum read response size based on configured counts.
|
// --- Helper: Compute maximum read response size based on configured counts.
|
||||||
int ModbusTCPClient::computeMaxReadResponseSize() const {
|
int ModbusTCPClient::computeMaxReadResponseSize() const {
|
||||||
@ -33,12 +32,13 @@ ModbusTCPClient::ModbusTCPClient(const char* ip, int port, int numCoils, int num
|
|||||||
startCoils(startCoils), startDiscreteInputs(startDI), startInputRegisters(startIR), startHoldingRegisters(startHR) {
|
startCoils(startCoils), startDiscreteInputs(startDI), startInputRegisters(startIR), startHoldingRegisters(startHR) {
|
||||||
|
|
||||||
// Allocate internal storage for automatic readAll()/writeAll() mode.
|
// Allocate internal storage for automatic readAll()/writeAll() mode.
|
||||||
coilsRead = new bool[numCoils]();
|
coilsRead = (numCoils > 0) ? new bool[numCoils]() : nullptr;
|
||||||
coilsWrite = new bool[numCoils]();
|
coilsWrite = (numCoils > 0) ? new bool[numCoils]() : nullptr;
|
||||||
discreteInputs = new bool[numDI]();
|
discreteInputs = (numDI > 0) ? new bool[numDI]() : nullptr;
|
||||||
inputRegisters = new uint16_t[numIR]();
|
inputRegisters = (numIR > 0) ? new uint16_t[numIR]() : nullptr;
|
||||||
holdingRegistersRead = new uint16_t[numHR]();
|
holdingRegistersRead = (numHR > 0) ? new uint16_t[numHR]() : nullptr;
|
||||||
holdingRegistersWrite = new uint16_t[numHR]();
|
holdingRegistersWrite = (numHR > 0) ? new uint16_t[numHR]() : nullptr;
|
||||||
|
|
||||||
|
|
||||||
// Allocate shared communication buffers.
|
// Allocate shared communication buffers.
|
||||||
commRequestBufferSize = computeMaxWriteRequestSize(); // Worst-case request size.
|
commRequestBufferSize = computeMaxWriteRequestSize(); // Worst-case request size.
|
||||||
@ -46,8 +46,12 @@ ModbusTCPClient::ModbusTCPClient(const char* ip, int port, int numCoils, int num
|
|||||||
commRequestBuffer = new uint8_t[commRequestBufferSize];
|
commRequestBuffer = new uint8_t[commRequestBufferSize];
|
||||||
commResponseBuffer = new uint8_t[commResponseBufferSize];
|
commResponseBuffer = new uint8_t[commResponseBufferSize];
|
||||||
|
|
||||||
// Initialize the socket mutex.
|
// Initialize the socket mutex with a recursive attribute.
|
||||||
pthread_mutex_init(&socketMutex, NULL);
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&socketMutex, &attr);
|
||||||
|
pthread_mutexattr_destroy(&attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusTCPClient::ModbusTCPClient(const char* ip, int port)
|
ModbusTCPClient::ModbusTCPClient(const char* ip, int port)
|
||||||
@ -66,8 +70,12 @@ ModbusTCPClient::ModbusTCPClient(const char* ip, int port)
|
|||||||
commRequestBuffer = new uint8_t[commRequestBufferSize];
|
commRequestBuffer = new uint8_t[commRequestBufferSize];
|
||||||
commResponseBuffer = new uint8_t[commResponseBufferSize];
|
commResponseBuffer = new uint8_t[commResponseBufferSize];
|
||||||
|
|
||||||
// Initialize the socket mutex.
|
// Initialize the socket mutex with a recursive attribute.
|
||||||
pthread_mutex_init(&socketMutex, NULL);
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&socketMutex, &attr);
|
||||||
|
pthread_mutexattr_destroy(&attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusTCPClient::~ModbusTCPClient() {
|
ModbusTCPClient::~ModbusTCPClient() {
|
||||||
@ -93,46 +101,134 @@ void ModbusTCPClient::setStartAddresses(int startCoils, int startDI, int startIR
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Connection Functions ---
|
// --- Connection Functions ---
|
||||||
|
// bool ModbusTCPClient::connectServer() {
|
||||||
|
// //pthread_mutex_lock(&socketMutex);
|
||||||
|
// if (socketFD != -1) {
|
||||||
|
// //pthread_mutex_unlock(&socketMutex);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// for (int attempts = 0; attempts < 5; attempts++) {
|
||||||
|
// socketFD = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
// if (socketFD < 0) {
|
||||||
|
// printf("MODBUS_TCP_CLIENT: Could not create socket\n");
|
||||||
|
// //pthread_mutex_unlock(&socketMutex);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// struct sockaddr_in serverAddr;
|
||||||
|
// serverAddr.sin_family = AF_INET;
|
||||||
|
// serverAddr.sin_port = htons(serverPort);
|
||||||
|
// inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);
|
||||||
|
// printf("MODBUS_TCP_CLIENT: Attempting to connect (Try %d)...\n", attempts + 1);
|
||||||
|
// if (connect(socketFD, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == 0) {
|
||||||
|
// printf("MODBUS_TCP_CLIENT: Connected to %s:%d\n", serverIP, serverPort);
|
||||||
|
// //pthread_mutex_unlock(&socketMutex);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// printf("MODBUS_TCP_CLIENT: Connection failed, retrying...\n");
|
||||||
|
// disconnectServer();
|
||||||
|
// usleep(timeoutMilliseconds*1000);
|
||||||
|
// }
|
||||||
|
// //pthread_mutex_unlock(&socketMutex);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
bool ModbusTCPClient::connectServer() {
|
bool ModbusTCPClient::connectServer() {
|
||||||
pthread_mutex_lock(&socketMutex);
|
// If already connected, return true.
|
||||||
if (socketFD != -1) {
|
if (socketFD != -1) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int attempts = 0; attempts < 5; attempts++) {
|
for (int attempts = 0; attempts < 5; attempts++) {
|
||||||
|
// Create a new socket.
|
||||||
socketFD = socket(AF_INET, SOCK_STREAM, 0);
|
socketFD = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (socketFD < 0) {
|
if (socketFD < 0) {
|
||||||
printf("MODBUS_TCP_CLIENT: Could not create socket\n");
|
printf("MODBUS_TCP_CLIENT: Could not create socket\n");
|
||||||
pthread_mutex_unlock(&socketMutex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the socket to non-blocking mode.
|
||||||
|
int flags = fcntl(socketFD, F_GETFL, 0);
|
||||||
|
if (flags < 0) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: fcntl F_GETFL");
|
||||||
|
disconnectServer();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fcntl(socketFD, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: fcntl F_SETFL O_NONBLOCK");
|
||||||
|
disconnectServer();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the server address.
|
||||||
struct sockaddr_in serverAddr;
|
struct sockaddr_in serverAddr;
|
||||||
serverAddr.sin_family = AF_INET;
|
serverAddr.sin_family = AF_INET;
|
||||||
serverAddr.sin_port = htons(serverPort);
|
serverAddr.sin_port = htons(serverPort);
|
||||||
inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);
|
inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);
|
||||||
|
|
||||||
printf("MODBUS_TCP_CLIENT: Attempting to connect (Try %d)...\n", attempts + 1);
|
printf("MODBUS_TCP_CLIENT: Attempting to connect (Try %d)...\n", attempts + 1);
|
||||||
if (connect(socketFD, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == 0) {
|
int res = connect(socketFD, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
|
||||||
printf("MODBUS_TCP_CLIENT: Connected to %s:%d\n", serverIP, serverPort);
|
if (res < 0) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
if (errno == EINPROGRESS) {
|
||||||
|
// Connection is in progress, use select() to wait.
|
||||||
|
fd_set wfds;
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_SET(socketFD, &wfds);
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = timeoutMilliseconds / 1000;
|
||||||
|
tv.tv_usec = (timeoutMilliseconds % 1000) * 1000;
|
||||||
|
|
||||||
|
int sel = select(socketFD + 1, NULL, &wfds, NULL, &tv);
|
||||||
|
if (sel > 0) {
|
||||||
|
int so_error = 0;
|
||||||
|
socklen_t len = sizeof(so_error);
|
||||||
|
if (getsockopt(socketFD, SOL_SOCKET, SO_ERROR, &so_error, &len) < 0) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: getsockopt failed\n");
|
||||||
|
disconnectServer();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (so_error == 0) {
|
||||||
|
// Connected successfully. Restore blocking mode.
|
||||||
|
flags = fcntl(socketFD, F_GETFL, 0);
|
||||||
|
fcntl(socketFD, F_SETFL, flags & ~O_NONBLOCK);
|
||||||
|
printf("MODBUS_TCP_CLIENT: Connected to %s:%d\n", serverIP, serverPort);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Connect failed with error %d\n", so_error);
|
||||||
|
}
|
||||||
|
} else if (sel == 0) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Connect select timeout\n");
|
||||||
|
} else {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Select during connect failed\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Connect error\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unexpected immediate success in non-blocking mode.
|
||||||
|
flags = fcntl(socketFD, F_GETFL, 0);
|
||||||
|
fcntl(socketFD, F_SETFL, flags & ~O_NONBLOCK);
|
||||||
|
printf("MODBUS_TCP_CLIENT: Connected immediately to %s:%d\n", serverIP, serverPort);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If connection failed, disconnect and wait before retrying.
|
||||||
printf("MODBUS_TCP_CLIENT: Connection failed, retrying...\n");
|
printf("MODBUS_TCP_CLIENT: Connection failed, retrying...\n");
|
||||||
pthread_mutex_unlock(&socketMutex);
|
|
||||||
disconnectServer();
|
disconnectServer();
|
||||||
usleep(100000);
|
usleep(timeoutMilliseconds * 1000);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModbusTCPClient::disconnectServer() {
|
void ModbusTCPClient::disconnectServer() {
|
||||||
pthread_mutex_lock(&socketMutex);
|
////pthread_mutex_lock(&socketMutex);
|
||||||
if (socketFD != -1) {
|
if (socketFD != -1) {
|
||||||
|
shutdown(socketFD, SHUT_RDWR);
|
||||||
close(socketFD);
|
close(socketFD);
|
||||||
socketFD = -1;
|
socketFD = -1;
|
||||||
printf("MODBUS_TCP_CLIENT: Disconnected from server\n");
|
printf("MODBUS_TCP_CLIENT: Disconnected from server\n");
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//thread_mutex_unlock(&socketMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModbusTCPClient::isConnected() const {
|
bool ModbusTCPClient::isConnected() const {
|
||||||
@ -150,7 +246,7 @@ void ModbusTCPClient::setTimeout(int milliseconds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ModbusTCPClient::sendRequest(uint8_t* request, int requestSize) {
|
bool ModbusTCPClient::sendRequest(uint8_t* request, int requestSize) {
|
||||||
if (socketFD == -1) {
|
if (!isConnected()) {
|
||||||
printf("MODBUS_TCP_CLIENT: Not connected. Cannot send request.\n");
|
printf("MODBUS_TCP_CLIENT: Not connected. Cannot send request.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -182,6 +278,11 @@ bool ModbusTCPClient::receiveResponse(uint8_t* response, int expectedSize) {
|
|||||||
disconnectServer();
|
disconnectServer();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Make sure we are still connected before we do a read to prevent a hardfault
|
||||||
|
if (!isConnected()) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Connection lost while reading. Disconnecting...\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int bytesReceived = read(socketFD, response + totalBytesReceived, expectedSize - totalBytesReceived);
|
int bytesReceived = read(socketFD, response + totalBytesReceived, expectedSize - totalBytesReceived);
|
||||||
if (bytesReceived <= 0) {
|
if (bytesReceived <= 0) {
|
||||||
printf("MODBUS_TCP_CLIENT: Connection lost while reading. Disconnecting...\n");
|
printf("MODBUS_TCP_CLIENT: Connection lost while reading. Disconnecting...\n");
|
||||||
@ -262,33 +363,33 @@ void ModbusTCPClient::buildWriteMultipleRequest(uint8_t* buffer, ModbusFunction
|
|||||||
// --- High-Level Read/Write Functions ---
|
// --- High-Level Read/Write Functions ---
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readCoil(int address, bool &coilState) {
|
ModbusError ModbusTCPClient::readCoil(int address, bool &coilState) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_COIL, address, 1);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_COIL, address, 1);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Expect 10 bytes: header (9 bytes) + 1 byte data
|
// Expect 10 bytes: header (9 bytes) + 1 byte data
|
||||||
int expectedSize = 9 + 1;
|
int expectedSize = 9 + 1;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
// Handle MODBUS exception responses (0x80 + function code)
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
// Ensure the function code in the response matches the request.
|
// Ensure the function code in the response matches the request.
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Set the internal coil state from the response
|
// Set the internal coil state from the response
|
||||||
coilState = (commResponseBuffer[9] & 0x01) != 0;
|
coilState = (commResponseBuffer[9] & 0x01) != 0;
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,28 +398,28 @@ ModbusError ModbusTCPClient::readMultipleCoils(int address, int count, bool coil
|
|||||||
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-2000 allowed)\n");
|
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-2000 allowed)\n");
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_COIL, address, count);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_COIL, address, count);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Expected response size: fixed header (9 bytes) + variable byte count.
|
// Expected response size: fixed header (9 bytes) + variable byte count.
|
||||||
int byteCount = (count + 7) / 8; // 1 byte per 8 coils
|
int byteCount = (count + 7) / 8; // 1 byte per 8 coils
|
||||||
int expectedSize = 9 + byteCount;
|
int expectedSize = 9 + byteCount;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
// Handle MODBUS exception responses (0x80 + function code)
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
// Ensure the function code in the response matches the request.
|
// Ensure the function code in the response matches the request.
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Extract coil values: data starts at index 9.
|
// Extract coil values: data starts at index 9.
|
||||||
@ -327,38 +428,38 @@ ModbusError ModbusTCPClient::readMultipleCoils(int address, int count, bool coil
|
|||||||
int bitIndex = i % 8;
|
int bitIndex = i % 8;
|
||||||
coilStates[i] = (commResponseBuffer[byteIndex] >> bitIndex) & 0x01;
|
coilStates[i] = (commResponseBuffer[byteIndex] >> bitIndex) & 0x01;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readDiscreteInput(int address, bool &discreteInput) {
|
ModbusError ModbusTCPClient::readDiscreteInput(int address, bool &discreteInput) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
// Build a request for one discrete input (quantity = 1)
|
// Build a request for one discrete input (quantity = 1)
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_DISCRETE_INPUT, address, 1);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_DISCRETE_INPUT, address, 1);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Expect 10 bytes: header (9 bytes) + 1 byte data
|
// Expect 10 bytes: header (9 bytes) + 1 byte data
|
||||||
int expectedSize = 9 + 1;
|
int expectedSize = 9 + 1;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Check for MODBUS exception response
|
// Check for MODBUS exception response
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
// Validate function code
|
// Validate function code
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Extract the discrete input state (first bit of the data byte at index 9)
|
// Extract the discrete input state (first bit of the data byte at index 9)
|
||||||
discreteInput = (commResponseBuffer[9] & 0x01) != 0;
|
discreteInput = (commResponseBuffer[9] & 0x01) != 0;
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,26 +468,26 @@ ModbusError ModbusTCPClient::readMultipleDiscreteInputs(int address, int count,
|
|||||||
printf("MODBUS_TCP_CLIENT: Invalid discrete input count (1- allowed)\n");
|
printf("MODBUS_TCP_CLIENT: Invalid discrete input count (1- allowed)\n");
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_DISCRETE_INPUT, address, count);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_DISCRETE_INPUT, address, count);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Expected response: 9-byte header + ceil(count/8) bytes of data
|
// Expected response: 9-byte header + ceil(count/8) bytes of data
|
||||||
int byteCount = (count + 7) / 8;
|
int byteCount = (count + 7) / 8;
|
||||||
int expectedSize = 9 + byteCount;
|
int expectedSize = 9 + byteCount;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Extract each discrete input bit from the data starting at index 9
|
// Extract each discrete input bit from the data starting at index 9
|
||||||
@ -395,35 +496,35 @@ ModbusError ModbusTCPClient::readMultipleDiscreteInputs(int address, int count,
|
|||||||
int bitIndex = i % 8;
|
int bitIndex = i % 8;
|
||||||
discreteInputsArray[i] = (commResponseBuffer[byteIndex] >> bitIndex) & 0x01;
|
discreteInputsArray[i] = (commResponseBuffer[byteIndex] >> bitIndex) & 0x01;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readHoldingRegister(int address, uint16_t &holdingRegister) {
|
ModbusError ModbusTCPClient::readHoldingRegister(int address, uint16_t &holdingRegister) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_HOLDING_REGISTER, address, 1);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_HOLDING_REGISTER, address, 1);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// For one register, expect 9-byte header + 2 bytes data = 11 bytes total
|
// For one register, expect 9-byte header + 2 bytes data = 11 bytes total
|
||||||
int expectedSize = 9 + 2;
|
int expectedSize = 9 + 2;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Extract the register value (big-endian: data at indices 9 and 10)
|
// Extract the register value (big-endian: data at indices 9 and 10)
|
||||||
holdingRegister = (commResponseBuffer[9] << 8) | commResponseBuffer[10];
|
holdingRegister = (commResponseBuffer[9] << 8) | commResponseBuffer[10];
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,59 +533,59 @@ ModbusError ModbusTCPClient::readMultipleHoldingRegisters(int address, int count
|
|||||||
printf("MODBUS_TCP_CLIENT: Invalid holding register count (1-125 allowed)\n");
|
printf("MODBUS_TCP_CLIENT: Invalid holding register count (1-125 allowed)\n");
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_HOLDING_REGISTER, address, count);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_HOLDING_REGISTER, address, count);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// For multiple registers: expected size = 9 + (count * 2)
|
// For multiple registers: expected size = 9 + (count * 2)
|
||||||
int expectedSize = 9 + (count * 2);
|
int expectedSize = 9 + (count * 2);
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Extract each register value (each register is 2 bytes, big-endian)
|
// Extract each register value (each register is 2 bytes, big-endian)
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
holdingRegistersArray[i] = (commResponseBuffer[9 + (i * 2)] << 8) | commResponseBuffer[10 + (i * 2)];
|
holdingRegistersArray[i] = (commResponseBuffer[9 + (i * 2)] << 8) | commResponseBuffer[10 + (i * 2)];
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readInputRegister(int address, uint16_t &inputRegister) {
|
ModbusError ModbusTCPClient::readInputRegister(int address, uint16_t &inputRegister) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_INPUT_REGISTER, address, 1);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_INPUT_REGISTER, address, 1);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// For one input register: expected size = 9 + 2 = 11 bytes
|
// For one input register: expected size = 9 + 2 = 11 bytes
|
||||||
int expectedSize = 9 + 2;
|
int expectedSize = 9 + 2;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
inputRegister = (commResponseBuffer[9] << 8) | commResponseBuffer[10];
|
inputRegister = (commResponseBuffer[9] << 8) | commResponseBuffer[10];
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,63 +594,63 @@ ModbusError ModbusTCPClient::readMultipleInputRegisters(int address, int count,
|
|||||||
printf("MODBUS_TCP_CLIENT: Invalid input register count (1-125 allowed)\n");
|
printf("MODBUS_TCP_CLIENT: Invalid input register count (1-125 allowed)\n");
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildReadRequest(commRequestBuffer, ModbusFunction::READ_INPUT_REGISTER, address, count);
|
buildReadRequest(commRequestBuffer, ModbusFunction::READ_INPUT_REGISTER, address, count);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// For multiple registers: expected size = 9 + (count * 2)
|
// For multiple registers: expected size = 9 + (count * 2)
|
||||||
int expectedSize = 9 + (count * 2);
|
int expectedSize = 9 + (count * 2);
|
||||||
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] & 0x80) {
|
if (commResponseBuffer[7] & 0x80) {
|
||||||
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
return ModbusError::EXCEPTION_RESPONSE;
|
||||||
}
|
}
|
||||||
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Extract each register value (each register is 2 bytes, big-endian)
|
// Extract each register value (each register is 2 bytes, big-endian)
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
inputRegistersArray[i] = (commResponseBuffer[9 + (i * 2)] << 8) | commResponseBuffer[10 + (i * 2)];
|
inputRegistersArray[i] = (commResponseBuffer[9 + (i * 2)] << 8) | commResponseBuffer[10 + (i * 2)];
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeCoil(int address, bool value) {
|
ModbusError ModbusTCPClient::writeCoil(int address, bool value) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
buildWriteSingleRequest(commRequestBuffer, ModbusFunction::WRITE_SINGLE_COIL, address, value ? 0xFF00 : 0x0000);
|
buildWriteSingleRequest(commRequestBuffer, ModbusFunction::WRITE_SINGLE_COIL, address, value ? 0xFF00 : 0x0000);
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
if (!receiveResponse(commResponseBuffer, 12)) {
|
if (!receiveResponse(commResponseBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 12; i++) {
|
for (int i = 0; i < 12; i++) {
|
||||||
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bool values[]) {
|
ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bool values[]) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
|
|
||||||
if (count < 1 || count > numCoils) {
|
if (count < 1 || count > numCoils) {
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-%d allowed)\n", numCoils);
|
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-%d allowed)\n", numCoils);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,14 +673,14 @@ ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bo
|
|||||||
buildWriteMultipleRequest(commRequestBuffer, ModbusFunction::WRITE_MULTIPLE_COILS, address, count, coilData, byteCount);
|
buildWriteMultipleRequest(commRequestBuffer, ModbusFunction::WRITE_MULTIPLE_COILS, address, count, coilData, byteCount);
|
||||||
// Send the request.
|
// Send the request.
|
||||||
if (!sendRequest(commRequestBuffer, requestSize)) {
|
if (!sendRequest(commRequestBuffer, requestSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The expected response size for a write multiple coils request is always 12 bytes.
|
// The expected response size for a write multiple coils request is always 12 bytes.
|
||||||
int expectedResponseSize = 12;
|
int expectedResponseSize = 12;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedResponseSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedResponseSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,45 +690,45 @@ ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bo
|
|||||||
if (i == 5) continue; // Skip the length field.
|
if (i == 5) continue; // Skip the length field.
|
||||||
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request at byte %d!\n", i);
|
printf("MODBUS_TCP_CLIENT: Response does not match request at byte %d!\n", i);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeHoldingRegister(int address, uint16_t value) {
|
ModbusError ModbusTCPClient::writeHoldingRegister(int address, uint16_t value) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
// Build the write single holding register request.
|
// Build the write single holding register request.
|
||||||
buildWriteSingleRequest(commRequestBuffer, ModbusFunction::WRITE_SINGLE_HOLDING_REGISTER, address, value);
|
buildWriteSingleRequest(commRequestBuffer, ModbusFunction::WRITE_SINGLE_HOLDING_REGISTER, address, value);
|
||||||
// Send the 12-byte request.
|
// Send the 12-byte request.
|
||||||
if (!sendRequest(commRequestBuffer, 12)) {
|
if (!sendRequest(commRequestBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Expect a full 12-byte echo response.
|
// Expect a full 12-byte echo response.
|
||||||
if (!receiveResponse(commResponseBuffer, 12)) {
|
if (!receiveResponse(commResponseBuffer, 12)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Validate that the entire 12-byte response matches the request.
|
// Validate that the entire 12-byte response matches the request.
|
||||||
for (int i = 0; i < 12; i++) {
|
for (int i = 0; i < 12; i++) {
|
||||||
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request at byte %d!\n", i);
|
printf("MODBUS_TCP_CLIENT: Response does not match request at byte %d!\n", i);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]) {
|
ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]) {
|
||||||
pthread_mutex_lock(&socketMutex);
|
//pthread_mutex_lock(&socketMutex);
|
||||||
if (count < 1 || count > numHoldingRegisters) {
|
if (count < 1 || count > numHoldingRegisters) {
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid register count (1-%d allowed)\n", numHoldingRegisters);
|
printf("MODBUS_TCP_CLIENT: Invalid register count (1-%d allowed)\n", numHoldingRegisters);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
// Each register is 2 bytes.
|
// Each register is 2 bytes.
|
||||||
@ -644,13 +745,13 @@ ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int coun
|
|||||||
buildWriteMultipleRequest(commRequestBuffer, ModbusFunction::WRITE_MULTIPLE_HOLDING_REGISTERS, address, count, registerData, byteCount);
|
buildWriteMultipleRequest(commRequestBuffer, ModbusFunction::WRITE_MULTIPLE_HOLDING_REGISTERS, address, count, registerData, byteCount);
|
||||||
// Send the request.
|
// Send the request.
|
||||||
if (!sendRequest(commRequestBuffer, requestSize)) {
|
if (!sendRequest(commRequestBuffer, requestSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// The expected response size for a write multiple holding registers request is 12 bytes.
|
// The expected response size for a write multiple holding registers request is 12 bytes.
|
||||||
int expectedResponseSize = 12;
|
int expectedResponseSize = 12;
|
||||||
if (!receiveResponse(commResponseBuffer, expectedResponseSize)) {
|
if (!receiveResponse(commResponseBuffer, expectedResponseSize)) {
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::TIMEOUT;
|
return ModbusError::TIMEOUT;
|
||||||
}
|
}
|
||||||
// Validate the response: Compare the first 10 bytes, skipping byte 5 (length field).
|
// Validate the response: Compare the first 10 bytes, skipping byte 5 (length field).
|
||||||
@ -658,16 +759,24 @@ ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int coun
|
|||||||
if (i == 5) continue; // Skip the length field.
|
if (i == 5) continue; // Skip the length field.
|
||||||
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
if (commRequestBuffer[i] != commResponseBuffer[i]) {
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request at byte %d!\n", i);
|
printf("MODBUS_TCP_CLIENT: Response does not match request at byte %d!\n", i);
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::INVALID_RESPONSE;
|
return ModbusError::INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&socketMutex);
|
//pthread_mutex_unlock(&socketMutex);
|
||||||
return ModbusError::NONE;
|
return ModbusError::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readAll() {
|
ModbusError ModbusTCPClient::readAll() {
|
||||||
// For brevity, call low-level functions that update internal storage.
|
// For brevity, call low-level functions that update internal storage.
|
||||||
|
printf("readAll()\n");
|
||||||
|
if (!isConnected()) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Not connected when readAll() called. Connecting...");
|
||||||
|
if (connectServer()) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Failed to connect to MODBUS server\n");
|
||||||
|
}
|
||||||
|
return ModbusError::CONNECTION_LOST;
|
||||||
|
}
|
||||||
ModbusError error = ModbusError::NONE;
|
ModbusError error = ModbusError::NONE;
|
||||||
if (coilsRead) {
|
if (coilsRead) {
|
||||||
error = readMultipleCoils(startCoils, numCoils, coilsRead);
|
error = readMultipleCoils(startCoils, numCoils, coilsRead);
|
||||||
@ -688,6 +797,13 @@ ModbusError ModbusTCPClient::readAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeAll() {
|
ModbusError ModbusTCPClient::writeAll() {
|
||||||
|
if (!isConnected()) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Not connected when readAll() called. Connecting...");
|
||||||
|
if (connectServer()) {
|
||||||
|
printf("MODBUS_TCP_CLIENT: Failed to connect to MODBUS server\n");
|
||||||
|
}
|
||||||
|
return ModbusError::CONNECTION_LOST;
|
||||||
|
}
|
||||||
ModbusError error = ModbusError::NONE;
|
ModbusError error = ModbusError::NONE;
|
||||||
if (coilsWrite) {
|
if (coilsWrite) {
|
||||||
error = writeMultipleCoils(startCoils, numCoils, coilsWrite);
|
error = writeMultipleCoils(startCoils, numCoils, coilsWrite);
|
||||||
@ -736,3 +852,79 @@ uint16_t ModbusTCPClient::getDesiredHoldingRegister(int address) const {
|
|||||||
uint16_t ModbusTCPClient::getInputRegister(int address) const {
|
uint16_t ModbusTCPClient::getInputRegister(int address) const {
|
||||||
return (address >= 0 && address < numInputRegisters) ? inputRegisters[address] : 0;
|
return (address >= 0 && address < numInputRegisters) ? inputRegisters[address] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModbusError ModbusTCPClient::getMultipleDiscreteInputs(int startAddress, int count, bool* destination) const {
|
||||||
|
// Validate inputs
|
||||||
|
if (startAddress < 0 || count <= 0 || destination == nullptr) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the range is within bounds
|
||||||
|
if (startAddress + count > numDiscreteInputs) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the data manually
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
destination[i] = discreteInputs[startAddress + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModbusError::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusError ModbusTCPClient::getMultipleCoils(int startAddress, int count, bool* destination) const {
|
||||||
|
// Validate inputs
|
||||||
|
if (startAddress < 0 || count <= 0 || destination == nullptr) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the range is within bounds
|
||||||
|
if (startAddress + count > numCoils) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the data manually
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
destination[i] = coilsRead[startAddress + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModbusError::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusError ModbusTCPClient::getMultipleInputRegisters(int startAddress, int count, uint16_t* destination) const {
|
||||||
|
// Validate inputs
|
||||||
|
if (startAddress < 0 || count <= 0 || destination == nullptr) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the range is within bounds
|
||||||
|
if (startAddress + count > numInputRegisters) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the data manually
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
destination[i] = inputRegisters[startAddress + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModbusError::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusError ModbusTCPClient::getMultipleHoldingRegisters(int startAddress, int count, uint16_t* destination) const {
|
||||||
|
// Validate inputs
|
||||||
|
if (startAddress < 0 || count <= 0 || destination == nullptr) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the range is within bounds
|
||||||
|
if (startAddress + count > numHoldingRegisters) {
|
||||||
|
return ModbusError::INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the data manually
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
destination[i] = holdingRegistersRead[startAddress + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModbusError::NONE;
|
||||||
|
}
|
||||||
@ -4,8 +4,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/select.h>
|
||||||
#include <pthread.h> // Use mutexes
|
#include <pthread.h> // Use mutexes
|
||||||
|
|
||||||
// Enum class for MODBUS function codes
|
// Enum class for MODBUS function codes
|
||||||
@ -54,12 +56,18 @@ public:
|
|||||||
// Getters and setters for data values (if using the automatic mode).
|
// Getters and setters for data values (if using the automatic mode).
|
||||||
void setCoil(int address, bool value);
|
void setCoil(int address, bool value);
|
||||||
void setHoldingRegister(int address, uint16_t value);
|
void setHoldingRegister(int address, uint16_t value);
|
||||||
|
|
||||||
|
bool getDiscreteInput(int address) const;
|
||||||
bool getCoil(int address) const;
|
bool getCoil(int address) const;
|
||||||
bool getDesiredCoil(int address) const;
|
bool getDesiredCoil(int address) const;
|
||||||
bool getDiscreteInput(int address) const;
|
uint16_t getInputRegister(int address) const;
|
||||||
uint16_t getHoldingRegister(int address) const;
|
uint16_t getHoldingRegister(int address) const;
|
||||||
uint16_t getDesiredHoldingRegister(int address) const;
|
uint16_t getDesiredHoldingRegister(int address) const;
|
||||||
uint16_t getInputRegister(int address) const;
|
|
||||||
|
ModbusError getMultipleCoils(int startAddress, int count, bool* destination) const;
|
||||||
|
ModbusError getMultipleDiscreteInputs(int startAddress, int count, bool* destination) const;
|
||||||
|
ModbusError getMultipleInputRegisters(int startAddress, int count, uint16_t* destination) const;
|
||||||
|
ModbusError getMultipleHoldingRegisters(int startAddress, int count, uint16_t* destination) const;
|
||||||
|
|
||||||
// High-level functions: readAll and writeAll update the internal buffers.
|
// High-level functions: readAll and writeAll update the internal buffers.
|
||||||
ModbusError readAll();
|
ModbusError readAll();
|
||||||
@ -1,757 +0,0 @@
|
|||||||
#include "modbus_tcp_client.h"
|
|
||||||
#include <sys/select.h> // For select() timeout
|
|
||||||
|
|
||||||
ModbusTCPClient::ModbusTCPClient(const char* ip, int port, int numCoils, int numDI, int numIR, int numHR,
|
|
||||||
int startCoils, int startDI, int startIR, int startHR)
|
|
||||||
: serverIP(ip), serverPort(port), socketFD(-1), transactionID(1),
|
|
||||||
numCoils(numCoils), numDiscreteInputs(numDI), numInputRegisters(numIR), numHoldingRegisters(numHR),
|
|
||||||
startCoils(startCoils), startDiscreteInputs(startDI), startInputRegisters(startIR), startHoldingRegisters(startHR) {
|
|
||||||
|
|
||||||
// Allocate memory dynamically based on provided sizes
|
|
||||||
coilsRead = new bool[numCoils]();
|
|
||||||
coilsWrite = new bool[numCoils]();
|
|
||||||
discreteInputs = new bool[numDiscreteInputs]();
|
|
||||||
|
|
||||||
inputRegisters = new uint16_t[numInputRegisters]();
|
|
||||||
holdingRegistersRead = new uint16_t[numHoldingRegisters]();
|
|
||||||
holdingRegistersWrite = new uint16_t[numHoldingRegisters]();
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusTCPClient::ModbusTCPClient(const char* ip, int port)
|
|
||||||
: serverIP(ip), serverPort(port), socketFD(-1) {
|
|
||||||
/*
|
|
||||||
This constructor is if the user manually wants to call MODBUS TCP functions and not
|
|
||||||
use readAll() and writeAll() and the setters/getters
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Set everything to nullptr so that readAll() and writeAll() won't work
|
|
||||||
coilsRead = nullptr;
|
|
||||||
coilsWrite = nullptr;
|
|
||||||
discreteInputs = nullptr;
|
|
||||||
|
|
||||||
inputRegisters = nullptr;
|
|
||||||
holdingRegistersRead = nullptr;
|
|
||||||
holdingRegistersWrite = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusTCPClient::~ModbusTCPClient() {
|
|
||||||
delete[] coilsRead;
|
|
||||||
delete[] coilsWrite;
|
|
||||||
delete[] discreteInputs;
|
|
||||||
|
|
||||||
delete[] inputRegisters;
|
|
||||||
delete[] holdingRegistersRead;
|
|
||||||
delete[] holdingRegistersWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::setStartAddresses(int startCoils, int startDI, int startIR, int startHR) {
|
|
||||||
this->startCoils = startCoils;
|
|
||||||
this->startDiscreteInputs = startDI;
|
|
||||||
this->startInputRegisters = startIR;
|
|
||||||
this->startHoldingRegisters = startHR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::connectServer() {
|
|
||||||
// Step 1: If socket is already open, verify it's still connected
|
|
||||||
if (socketFD != -1) {
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = 100000; // 100ms timeout for connection check
|
|
||||||
|
|
||||||
fd_set read_fds;
|
|
||||||
FD_ZERO(&read_fds);
|
|
||||||
FD_SET(socketFD, &read_fds);
|
|
||||||
|
|
||||||
int result = select(socketFD + 1, &read_fds, NULL, NULL, &timeout);
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
// No error in select, socket is still connected
|
|
||||||
printf("MODBUS_TCP_CLIENT: Already connected to MODBUS server\n");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Connection is broken, close and reset
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Connection lost, reconnecting...\n");
|
|
||||||
disconnectServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: Create a new socket
|
|
||||||
for (int attempts = 0; attempts < 5; attempts++) { // Retry up to 5 times
|
|
||||||
socketFD = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (socketFD < 0) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Could not create socket\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in serverAddr;
|
|
||||||
serverAddr.sin_family = AF_INET;
|
|
||||||
serverAddr.sin_port = htons(serverPort);
|
|
||||||
inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);
|
|
||||||
|
|
||||||
// Step 3: Attempt to connect
|
|
||||||
printf("MODBUS_TCP_CLIENT: Attempting to connect to MODBUS server (Try %d)...\n", attempts + 1);
|
|
||||||
if (connect(socketFD, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == 0) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Connected to MODBUS server at %s:%d\n", serverIP, serverPort);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("MODBUS_TCP_CLIENT: Connection failed, retrying...\n");
|
|
||||||
disconnectServer(); // Close socket before retrying
|
|
||||||
usleep(100000); // Wait 100ms before retrying
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::disconnectServer() {
|
|
||||||
if (socketFD != -1) {
|
|
||||||
close(socketFD);
|
|
||||||
socketFD = -1;
|
|
||||||
printf("MODBUS_TCP_CLIENT: Disconnected from MODBUS server\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::setTimeout(int milliseconds) {
|
|
||||||
timeoutMilliseconds = milliseconds;
|
|
||||||
printf("MODBUS_TCP_CLIENT: Timeout set to %d ms\n", timeoutMilliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::isConnected() const {
|
|
||||||
return socketFD != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::reconnectServer() {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Attempting manual reconnection...\n");
|
|
||||||
disconnectServer();
|
|
||||||
return connectServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::sendRequest(uint8_t* request, int requestSize) {
|
|
||||||
// Ensure we're connected before sending
|
|
||||||
if (socketFD == -1) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Connection lost. Attempting to reconnect...\n");
|
|
||||||
if (!connectServer()) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Reconnection failed. Cannot send request.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int bytesSent = write(socketFD, request, requestSize);
|
|
||||||
if (bytesSent <= 0) { // Detect broken connection during write
|
|
||||||
printf("MODBUS_TCP_CLIENT: Write failed, connection lost. Disconnecting...\n");
|
|
||||||
disconnectServer();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesSent == requestSize;
|
|
||||||
return bytesSent == requestSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::receiveResponse(uint8_t* response, int expectedSize) {
|
|
||||||
int totalBytesReceived = 0;
|
|
||||||
|
|
||||||
while (totalBytesReceived < expectedSize) {
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = timeoutMilliseconds / 1000; // Convert ms to seconds
|
|
||||||
timeout.tv_usec = (timeoutMilliseconds % 1000) * 1000; // Convert remaining ms to µs
|
|
||||||
|
|
||||||
fd_set read_fds;
|
|
||||||
FD_ZERO(&read_fds);
|
|
||||||
FD_SET(socketFD, &read_fds);
|
|
||||||
|
|
||||||
// Use select() to wait for data before reading
|
|
||||||
int ready = select(socketFD + 1, &read_fds, NULL, NULL, &timeout);
|
|
||||||
if (ready == 0) { // Timeout case
|
|
||||||
printf("MODBUS_TCP_CLIENT: Timeout waiting for MODBUS response. Disconnecting...\n");
|
|
||||||
disconnectServer(); // Close socket and reset socketFD
|
|
||||||
return false;
|
|
||||||
} else if (ready < 0) { // Select failed
|
|
||||||
printf("MODBUS_TCP_CLIENT: Select failed. Disconnecting...\n");
|
|
||||||
disconnectServer(); // Close socket and reset socketFD
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read available data
|
|
||||||
int bytesReceived = read(socketFD, response + totalBytesReceived, expectedSize - totalBytesReceived);
|
|
||||||
if (bytesReceived <= 0) { // Connection lost or no data received
|
|
||||||
printf("MODBUS_TCP_CLIENT: Connection lost. Disconnecting...\n");
|
|
||||||
disconnectServer(); // Close socket and reset socketFD
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalBytesReceived += bytesReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::buildReadRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t startAddr, uint16_t quantity) {
|
|
||||||
transactionID++;
|
|
||||||
|
|
||||||
// Transaction ID
|
|
||||||
buffer[0] = transactionID >> 8;
|
|
||||||
buffer[1] = transactionID & 0xFF;
|
|
||||||
// Protocol ID, always 00 00
|
|
||||||
buffer[2] = 0x00;
|
|
||||||
buffer[3] = 0x00;
|
|
||||||
// Length (remaining bytes after Unit ID)
|
|
||||||
buffer[4] = 0x00;
|
|
||||||
buffer[5] = 0x06;
|
|
||||||
// Unit ID (Slave Address)
|
|
||||||
buffer[6] = 0x01;
|
|
||||||
// Function code
|
|
||||||
buffer[7] = static_cast<uint8_t>(functionCode);
|
|
||||||
// Start Address
|
|
||||||
buffer[8] = startAddr >> 8;
|
|
||||||
buffer[9] = startAddr & 0xFF;
|
|
||||||
// Quantity (How many coils to read)
|
|
||||||
buffer[10] = quantity >> 8;
|
|
||||||
buffer[11] = quantity & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::buildWriteSingleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t value) {
|
|
||||||
transactionID++;
|
|
||||||
|
|
||||||
buffer[0] = transactionID >> 8;
|
|
||||||
buffer[1] = transactionID & 0xFF;
|
|
||||||
buffer[2] = 0x00;
|
|
||||||
buffer[3] = 0x00;
|
|
||||||
buffer[4] = 0x00;
|
|
||||||
buffer[5] = 0x06;
|
|
||||||
buffer[6] = 0x01;
|
|
||||||
buffer[7] = static_cast<uint8_t>(functionCode);
|
|
||||||
buffer[8] = address >> 8;
|
|
||||||
buffer[9] = address & 0xFF;
|
|
||||||
buffer[10] = value >> 8;
|
|
||||||
buffer[11] = value & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::buildWriteMultipleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t count, const void* values, uint8_t byteCount) {
|
|
||||||
transactionID++;
|
|
||||||
|
|
||||||
// MODBUS TCP Header
|
|
||||||
buffer[0] = transactionID >> 8;
|
|
||||||
buffer[1] = transactionID & 0xFF;
|
|
||||||
buffer[2] = 0x00; // Protocol ID (always 0x0000)
|
|
||||||
buffer[3] = 0x00;
|
|
||||||
buffer[4] = 0x00; // Length (remaining bytes after Unit ID)
|
|
||||||
buffer[5] = 7 + byteCount;
|
|
||||||
buffer[6] = 0x01; // Unit ID
|
|
||||||
buffer[7] = static_cast<uint8_t>(functionCode); // Function Code (0x0F for coils, 0x10 for registers)
|
|
||||||
buffer[8] = address >> 8; // Start address high byte
|
|
||||||
buffer[9] = address & 0xFF; // Start address low byte
|
|
||||||
buffer[10] = count >> 8; // Quantity high byte
|
|
||||||
buffer[11] = count & 0xFF; // Quantity low byte
|
|
||||||
buffer[12] = byteCount; // Byte count
|
|
||||||
|
|
||||||
// Copy data payload manually (instead of memcpy)
|
|
||||||
const uint8_t* data = (const uint8_t*)values;
|
|
||||||
for (uint8_t i = 0; i < byteCount; i++) {
|
|
||||||
buffer[13 + i] = data[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readCoil(int address, bool &coilState) {
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_COIL, address, 1);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
uint8_t response[10]; // Expecting 10 bytes
|
|
||||||
if (!receiveResponse(response, 10)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure function code matches the request (allowing for server behavior)
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_COIL), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract coil state (only first bit is used)
|
|
||||||
coilState = (response[9] & 0x01) != 0; // Adjusted index based on 10-byte response
|
|
||||||
return ModbusError::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readMultipleCoils(int address, int count, bool coilStates[]) {
|
|
||||||
if (count < 1 || count > 2000) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-2000 allowed)\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_COIL, address, count);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
// Expected response size: Fixed header (9) + variable byte count
|
|
||||||
int byteCount = (count + 7) / 8; // 1 byte per 8 coils
|
|
||||||
int expectedSize = 9 + byteCount;
|
|
||||||
|
|
||||||
uint8_t response[256]; // Ensure buffer is large enough
|
|
||||||
if (!receiveResponse(response, expectedSize)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the function code matches
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_COIL), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read coil values
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
int byteIndex = 9 + (i / 8); // Data starts at index 9
|
|
||||||
int bitIndex = i % 8;
|
|
||||||
coilStates[i] = (response[byteIndex] >> bitIndex) & 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readDiscreteInput(int address, bool &discreteInput) {
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_DISCRETE_INPUT, address, 1);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
uint8_t response[10]; // Expected response size
|
|
||||||
if (!receiveResponse(response, 10)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure function code matches the request
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract single discrete input state
|
|
||||||
discreteInput = (response[9] & 0x01) != 0;
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readMultipleDiscreteInputs(int address, int count, bool discreteInputs[]) {
|
|
||||||
if (count < 1 || count > 2000) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid discrete input count (1-2000 allowed)\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_DISCRETE_INPUT, address, count);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
// Expected response size: Fixed header (9) + variable byte count
|
|
||||||
int byteCount = (count + 7) / 8; // 1 byte per 8 inputs
|
|
||||||
int expectedSize = 9 + byteCount;
|
|
||||||
|
|
||||||
uint8_t response[256]; // Ensure buffer is large enough
|
|
||||||
if (!receiveResponse(response, expectedSize)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the function code matches
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read discrete input values
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
int byteIndex = 9 + (i / 8); // Data starts at index 9
|
|
||||||
int bitIndex = i % 8;
|
|
||||||
discreteInputs[i] = (response[byteIndex] >> bitIndex) & 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readHoldingRegister(int address, uint16_t &holdingRegister) {
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_HOLDING_REGISTER, address, 1);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
uint8_t response[11]; // Expected response size for reading 1 register
|
|
||||||
if (!receiveResponse(response, 11)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure function code matches the request
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract holding register value (Big-endian format)
|
|
||||||
holdingRegister = (response[9] << 8) | response[10];
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readMultipleHoldingRegisters(int address, int count, uint16_t holdingRegisters[]) {
|
|
||||||
if (count < 1 || count > 125) { // MODBUS limits reading up to 125 registers per request
|
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid holding register count (1-125 allowed)\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_HOLDING_REGISTER, address, count);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
// Expected response size: 9-byte header + 2 * count registers
|
|
||||||
int expectedSize = 9 + (count * 2);
|
|
||||||
uint8_t response[256]; // Ensure buffer is large enough
|
|
||||||
|
|
||||||
if (!receiveResponse(response, expectedSize)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure function code matches the request
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract register values (each register is 2 bytes, big-endian)
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
holdingRegisters[i] = (response[9 + (i * 2)] << 8) | response[10 + (i * 2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readInputRegister(int address, uint16_t &inputRegister) {
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_INPUT_REGISTER, address, 1);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
uint8_t response[11]; // Expected response size for reading 1 register
|
|
||||||
if (!receiveResponse(response, 11)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure function code matches the request
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract input register value (Big-endian format)
|
|
||||||
inputRegister = (response[9] << 8) | response[10];
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readMultipleInputRegisters(int address, int count, uint16_t inputRegisters[]) {
|
|
||||||
if (count < 1 || count > 125) { // MODBUS limits reading up to 125 registers per request
|
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid input register count (1-125 allowed)\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t request[12];
|
|
||||||
buildReadRequest(request, ModbusFunction::READ_INPUT_REGISTER, address, count);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
// Expected response size: 9-byte header + 2 * count registers
|
|
||||||
int expectedSize = 9 + (count * 2);
|
|
||||||
uint8_t response[256]; // Ensure buffer is large enough
|
|
||||||
|
|
||||||
if (!receiveResponse(response, expectedSize)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle MODBUS exception responses (0x80 + function code)
|
|
||||||
if (response[7] & 0x80) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
|
||||||
return ModbusError::EXCEPTION_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure function code matches the request
|
|
||||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
|
||||||
static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER), response[7]);
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract register values (each register is 2 bytes, big-endian)
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
inputRegisters[i] = (response[9 + (i * 2)] << 8) | response[10 + (i * 2)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeCoil(int address, bool value) {
|
|
||||||
uint8_t request[12];
|
|
||||||
buildWriteSingleRequest(request, ModbusFunction::WRITE_SINGLE_COIL, address, value ? 0xFF00 : 0x0000);
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
// Receive response
|
|
||||||
uint8_t response[12];
|
|
||||||
if (!receiveResponse(response, 12)) {
|
|
||||||
return ModbusError::TIMEOUT; // No response received
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if response matches request (MODBUS TCP should echo back the same request)
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
if (request[i] != response[i]) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bool values[]) {
|
|
||||||
if (count < 1 || count > 1968) { // MODBUS limit: max 1968 coils per request
|
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-1968 allowed)\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int byteCount = (count + 7) / 8; // Each byte holds 8 coils
|
|
||||||
uint8_t coilData[byteCount];
|
|
||||||
|
|
||||||
// Initialize to 0 (since we may not use all bits)
|
|
||||||
for (int i = 0; i < byteCount; i++) {
|
|
||||||
coilData[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pack coil data into bytes
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (values[i]) {
|
|
||||||
coilData[i / 8] |= (1 << (i % 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t request[13 + byteCount];
|
|
||||||
buildWriteMultipleRequest(request, ModbusFunction::WRITE_MULTIPLE_COILS, address, count, coilData, byteCount);
|
|
||||||
|
|
||||||
sendRequest(request, 13 + byteCount);
|
|
||||||
|
|
||||||
// The expected response is always **12 bytes**
|
|
||||||
uint8_t response[12];
|
|
||||||
if (!receiveResponse(response, 12)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the response matches the **first 10 bytes**, except for byte 5 (message length byte)
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
if (i == 5) continue; // Skip byte 5 (message length field)
|
|
||||||
|
|
||||||
if (request[i] != response[i]) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeHoldingRegister(int address, uint16_t value) {
|
|
||||||
uint8_t request[12];
|
|
||||||
buildWriteSingleRequest(request, ModbusFunction::WRITE_SINGLE_HOLDING_REGISTER, address, value);
|
|
||||||
|
|
||||||
sendRequest(request, 12);
|
|
||||||
|
|
||||||
// Expected response size = 12 bytes (full echo of the request)
|
|
||||||
uint8_t response[12];
|
|
||||||
if (!receiveResponse(response, 12)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure response matches request exactly (full 12 bytes)
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
if (request[i] != response[i]) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]) {
|
|
||||||
if (count < 1 || count > 123) { // MODBUS limit: max 123 registers per request
|
|
||||||
printf("MODBUS_TCP_CLIENT: Invalid register count (1-123 allowed)\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int byteCount = count * 2; // Each register is 2 bytes
|
|
||||||
uint8_t registerData[byteCount];
|
|
||||||
|
|
||||||
// Convert register values to byte array (big-endian format)
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
registerData[i * 2] = values[i] >> 8; // High byte
|
|
||||||
registerData[i * 2 + 1] = values[i] & 0xFF; // Low byte
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t request[13 + byteCount];
|
|
||||||
buildWriteMultipleRequest(request, ModbusFunction::WRITE_MULTIPLE_HOLDING_REGISTERS, address, count, registerData, byteCount);
|
|
||||||
|
|
||||||
sendRequest(request, 13 + byteCount);
|
|
||||||
|
|
||||||
// Expected response size = 12 bytes (first 10 bytes + 2 bytes for number of registers written)
|
|
||||||
uint8_t response[12];
|
|
||||||
if (!receiveResponse(response, 12)) {
|
|
||||||
return ModbusError::TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure response matches request (except for byte 5)
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
if (i == 5) continue; // Skip byte 5 (message length field)
|
|
||||||
|
|
||||||
if (request[i] != response[i]) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
|
||||||
return ModbusError::INVALID_RESPONSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModbusError::NONE; // Success
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::readAll() {
|
|
||||||
/*
|
|
||||||
Reads every coil, discrete input, input register, and holding register
|
|
||||||
assuming that they start at address 0
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (coilsRead == nullptr && discreteInputs == nullptr &&
|
|
||||||
inputRegisters == nullptr && holdingRegistersRead == nullptr) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: readAll() called, but wrong constructor was used.\n");
|
|
||||||
return ModbusError::INVALID_REQUEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError error = ModbusError::NONE;
|
|
||||||
if (coilsRead != nullptr) {
|
|
||||||
error = readMultipleCoils(startCoils, numCoils, coilsRead);
|
|
||||||
if (error != ModbusError::NONE) return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discreteInputs != nullptr) {
|
|
||||||
error = readMultipleDiscreteInputs(startDiscreteInputs, numDiscreteInputs, discreteInputs);
|
|
||||||
if (error != ModbusError::NONE) return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputRegisters != nullptr) {
|
|
||||||
error = readMultipleInputRegisters(startInputRegisters, numInputRegisters, inputRegisters);
|
|
||||||
if (error != ModbusError::NONE) return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (holdingRegistersRead != nullptr) {
|
|
||||||
error = readMultipleHoldingRegisters(startHoldingRegisters, numHoldingRegisters, holdingRegistersRead);
|
|
||||||
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError ModbusTCPClient::writeAll() {
|
|
||||||
/*
|
|
||||||
Reads every coil and holding register assuming that they start at address 0
|
|
||||||
*/
|
|
||||||
if (coilsWrite == nullptr && holdingRegistersWrite) {
|
|
||||||
printf("MODBUS_TCP_CLIENT: writeAll() called, but wrong constructor was used.\n");
|
|
||||||
return ModbusError::INVALID_REQUEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModbusError error = ModbusError::NONE;
|
|
||||||
if (coilsWrite != nullptr) {
|
|
||||||
error = writeMultipleCoils(startCoils, numCoils, coilsWrite);
|
|
||||||
if (error != ModbusError::NONE) return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (holdingRegistersWrite != nullptr) {
|
|
||||||
error = writeMultipleHoldingRegisters(startHoldingRegisters, numHoldingRegisters, holdingRegistersWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Setters for writing values (preferred to be used)
|
|
||||||
void ModbusTCPClient::setCoil(int address, bool value) {
|
|
||||||
if (address >= 0 && address < numCoils) {
|
|
||||||
coilsWrite[address] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModbusTCPClient::setHoldingRegister(int address, uint16_t value) {
|
|
||||||
if (address >= 0 && address < numHoldingRegisters) {
|
|
||||||
holdingRegistersWrite[address] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getters (preferred to be used as long as readAll is being called)
|
|
||||||
bool ModbusTCPClient::getCoil(int address) const {
|
|
||||||
return (address >= 0 && address < numCoils) ? coilsRead[address] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::getDesiredCoil(int address) const {
|
|
||||||
return (address >= 0 && address < numCoils) ? coilsWrite[address] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModbusTCPClient::getDiscreteInput(int address) const {
|
|
||||||
return (address >= 0 && address < numDiscreteInputs) ? discreteInputs[address] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ModbusTCPClient::getHoldingRegister(int address) const {
|
|
||||||
return (address >= 0 && address < numHoldingRegisters) ? holdingRegistersRead[address] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ModbusTCPClient::getDesiredHoldingRegister(int address) const {
|
|
||||||
return (address >= 0 && address < numHoldingRegisters) ? holdingRegistersWrite[address] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ModbusTCPClient::getInputRegister(int address) const {
|
|
||||||
return (address >= 0 && address < numInputRegisters) ? inputRegisters[address] : 0;
|
|
||||||
}
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
#ifndef MODBUS_TCP_CLIENT_H
|
|
||||||
#define MODBUS_TCP_CLIENT_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
// Enum class for MODBUS function codes
|
|
||||||
enum class ModbusFunction : uint8_t {
|
|
||||||
READ_COIL = 0x01,
|
|
||||||
READ_DISCRETE_INPUT = 0x02,
|
|
||||||
READ_HOLDING_REGISTER = 0x03,
|
|
||||||
READ_INPUT_REGISTER = 0x04,
|
|
||||||
WRITE_SINGLE_COIL = 0x05,
|
|
||||||
WRITE_SINGLE_HOLDING_REGISTER = 0x06,
|
|
||||||
WRITE_MULTIPLE_COILS = 0x0F,
|
|
||||||
WRITE_MULTIPLE_HOLDING_REGISTERS = 0x10
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ModbusError {
|
|
||||||
NONE = 0, // No error
|
|
||||||
TIMEOUT, // No response from server
|
|
||||||
INVALID_RESPONSE, // Response does not match request
|
|
||||||
CONNECTION_LOST, // Connection issue
|
|
||||||
EXCEPTION_RESPONSE, // MODBUS Exception response (error code)
|
|
||||||
INVALID_REQUEST, // User tries doing something they shouldn't
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ModbusTCPClient {
|
|
||||||
public:
|
|
||||||
ModbusTCPClient(const char* ip, int port); // Extra constructor that CANNOT use readAll() or writeAll()
|
|
||||||
ModbusTCPClient(const char* ip, int port, int numCoils, int numDI, int numIR, int numHR,
|
|
||||||
int startCoils = 0, int startDI = 0, int startIR = 0, int startHR = 0);
|
|
||||||
|
|
||||||
~ModbusTCPClient();
|
|
||||||
|
|
||||||
// Set the start address of each type. Either use this after creating the object or put them in the constructor
|
|
||||||
void setStartAddresses(int startCoils, int startDI, int startIR, int startHR);
|
|
||||||
|
|
||||||
bool connectServer();
|
|
||||||
void disconnectServer();
|
|
||||||
bool isConnected() const;
|
|
||||||
|
|
||||||
// Manually disconnectServer and return reconnectServer()
|
|
||||||
bool reconnectServer();
|
|
||||||
|
|
||||||
// Set the timeout for receiving responses
|
|
||||||
void setTimeout(int milliseconds);
|
|
||||||
|
|
||||||
// Setters (preferred to be used when calling writeAll())
|
|
||||||
void setCoil(int address, bool value);
|
|
||||||
void setHoldingRegister(int address, uint16_t value);
|
|
||||||
|
|
||||||
// Getters (preferred to be used when calling readAll())
|
|
||||||
bool getCoil(int address) const;
|
|
||||||
bool getDesiredCoil(int address) const; // Retrieves the "to be written" value
|
|
||||||
bool getDiscreteInput(int address) const;
|
|
||||||
uint16_t getHoldingRegister(int address) const;
|
|
||||||
uint16_t getDesiredHoldingRegister(int address) const; // Retrieves the "to be written" value
|
|
||||||
uint16_t getInputRegister(int address) const;
|
|
||||||
|
|
||||||
ModbusError readAll(); // Reads every coil, DI, IR, and HR
|
|
||||||
ModbusError writeAll(); // Writes every coil and HR
|
|
||||||
|
|
||||||
// Manual MODBUS TCP actions (not preferred to be called by user)
|
|
||||||
ModbusError readCoil(int address, bool &coilState);
|
|
||||||
ModbusError readMultipleCoils(int address, int count, bool coilStates[]);
|
|
||||||
|
|
||||||
ModbusError readDiscreteInput(int address, bool &discreteInput);
|
|
||||||
ModbusError readMultipleDiscreteInputs(int address, int count, bool discreteInputs[]);
|
|
||||||
|
|
||||||
ModbusError readHoldingRegister(int address, uint16_t &holdingRegister);
|
|
||||||
ModbusError readMultipleHoldingRegisters(int address, int count, uint16_t holdingRegisters[]);
|
|
||||||
|
|
||||||
ModbusError readInputRegister(int address, uint16_t &inputRegister);
|
|
||||||
ModbusError readMultipleInputRegisters(int address, int count, uint16_t inputRegisters[]);
|
|
||||||
|
|
||||||
ModbusError writeCoil(int address, bool value);
|
|
||||||
ModbusError writeMultipleCoils(int address, int count, const bool values[]);
|
|
||||||
|
|
||||||
ModbusError writeHoldingRegister(int address, uint16_t value);
|
|
||||||
ModbusError writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// TCP settings
|
|
||||||
const char* serverIP;
|
|
||||||
int serverPort;
|
|
||||||
int socketFD;
|
|
||||||
uint16_t transactionID;
|
|
||||||
int timeoutMilliseconds = 2000; // Default 2 second timeout on receiving responses
|
|
||||||
|
|
||||||
// Storing MODBUS register information
|
|
||||||
int numCoils, numDiscreteInputs, numInputRegisters, numHoldingRegisters;
|
|
||||||
int startCoils, startDiscreteInputs, startInputRegisters, startHoldingRegisters; // The start address of each type of register
|
|
||||||
|
|
||||||
bool* coilsRead; // Stores the actual state of coils on the MODBUS server
|
|
||||||
bool* coilsWrite; // Stores the desired state of coils to be written
|
|
||||||
bool* discreteInputs; // Only read from the MODBUS server (no writes)
|
|
||||||
|
|
||||||
uint16_t* inputRegisters; // Only read from the MODBUS server
|
|
||||||
uint16_t* holdingRegistersRead; // Stores actual values from the MODBUS server
|
|
||||||
uint16_t* holdingRegistersWrite; // Stores desired values to write
|
|
||||||
|
|
||||||
bool sendRequest(uint8_t* request, int requestSize);
|
|
||||||
bool receiveResponse(uint8_t* response, int expectedSize);
|
|
||||||
|
|
||||||
void buildReadRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t startAddr, uint16_t quantity);
|
|
||||||
void buildWriteSingleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t value);
|
|
||||||
void buildWriteMultipleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t count, const void* values, uint8_t byteCount);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MODBUS_TCP_CLIENT_H
|
|
||||||
Binary file not shown.
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef __customcode_jkx3iHsM9OOrSN3xw6c8aB_h__
|
||||||
|
#define __customcode_jkx3iHsM9OOrSN3xw6c8aB_h__
|
||||||
|
|
||||||
|
/* Include files */
|
||||||
|
#include "mex.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "tmwtypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper definitions for DLL support */
|
||||||
|
#if defined _WIN32
|
||||||
|
#define DLL_EXPORT_CC __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define DLL_EXPORT_CC __attribute__ ((visibility ("default")))
|
||||||
|
#else
|
||||||
|
#define DLL_EXPORT_CC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
/* Custom Code from Simulation Target dialog */
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "modbus_tcp_client.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Function Declarations */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#define customcode_jkx3iHsM9OOrSN3xw6c8aB_initializer()
|
||||||
|
|
||||||
|
#define customcode_jkx3iHsM9OOrSN3xw6c8aB_terminator()
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,283 @@
|
|||||||
|
#ifndef MULTIWORD_TYPES_H
|
||||||
|
#define MULTIWORD_TYPES_H
|
||||||
|
#include "rtwtypes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MultiWord supporting definitions
|
||||||
|
*/
|
||||||
|
typedef long long longlong_T;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MultiWord types
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[2];
|
||||||
|
} int128m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int128m_T re;
|
||||||
|
int128m_T im;
|
||||||
|
} cint128m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[2];
|
||||||
|
} uint128m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint128m_T re;
|
||||||
|
uint128m_T im;
|
||||||
|
} cuint128m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[3];
|
||||||
|
} int192m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int192m_T re;
|
||||||
|
int192m_T im;
|
||||||
|
} cint192m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[3];
|
||||||
|
} uint192m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint192m_T re;
|
||||||
|
uint192m_T im;
|
||||||
|
} cuint192m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[4];
|
||||||
|
} int256m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int256m_T re;
|
||||||
|
int256m_T im;
|
||||||
|
} cint256m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[4];
|
||||||
|
} uint256m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint256m_T re;
|
||||||
|
uint256m_T im;
|
||||||
|
} cuint256m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[5];
|
||||||
|
} int320m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int320m_T re;
|
||||||
|
int320m_T im;
|
||||||
|
} cint320m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[5];
|
||||||
|
} uint320m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint320m_T re;
|
||||||
|
uint320m_T im;
|
||||||
|
} cuint320m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[6];
|
||||||
|
} int384m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int384m_T re;
|
||||||
|
int384m_T im;
|
||||||
|
} cint384m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[6];
|
||||||
|
} uint384m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint384m_T re;
|
||||||
|
uint384m_T im;
|
||||||
|
} cuint384m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[7];
|
||||||
|
} int448m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int448m_T re;
|
||||||
|
int448m_T im;
|
||||||
|
} cint448m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[7];
|
||||||
|
} uint448m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint448m_T re;
|
||||||
|
uint448m_T im;
|
||||||
|
} cuint448m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[8];
|
||||||
|
} int512m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int512m_T re;
|
||||||
|
int512m_T im;
|
||||||
|
} cint512m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[8];
|
||||||
|
} uint512m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint512m_T re;
|
||||||
|
uint512m_T im;
|
||||||
|
} cuint512m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[9];
|
||||||
|
} int576m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int576m_T re;
|
||||||
|
int576m_T im;
|
||||||
|
} cint576m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[9];
|
||||||
|
} uint576m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint576m_T re;
|
||||||
|
uint576m_T im;
|
||||||
|
} cuint576m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[10];
|
||||||
|
} int640m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int640m_T re;
|
||||||
|
int640m_T im;
|
||||||
|
} cint640m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[10];
|
||||||
|
} uint640m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint640m_T re;
|
||||||
|
uint640m_T im;
|
||||||
|
} cuint640m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[11];
|
||||||
|
} int704m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int704m_T re;
|
||||||
|
int704m_T im;
|
||||||
|
} cint704m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[11];
|
||||||
|
} uint704m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint704m_T re;
|
||||||
|
uint704m_T im;
|
||||||
|
} cuint704m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[12];
|
||||||
|
} int768m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int768m_T re;
|
||||||
|
int768m_T im;
|
||||||
|
} cint768m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[12];
|
||||||
|
} uint768m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint768m_T re;
|
||||||
|
uint768m_T im;
|
||||||
|
} cuint768m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[13];
|
||||||
|
} int832m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int832m_T re;
|
||||||
|
int832m_T im;
|
||||||
|
} cint832m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[13];
|
||||||
|
} uint832m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint832m_T re;
|
||||||
|
uint832m_T im;
|
||||||
|
} cuint832m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[14];
|
||||||
|
} int896m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int896m_T re;
|
||||||
|
int896m_T im;
|
||||||
|
} cint896m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[14];
|
||||||
|
} uint896m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint896m_T re;
|
||||||
|
uint896m_T im;
|
||||||
|
} cuint896m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[15];
|
||||||
|
} int960m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int960m_T re;
|
||||||
|
int960m_T im;
|
||||||
|
} cint960m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[15];
|
||||||
|
} uint960m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint960m_T re;
|
||||||
|
uint960m_T im;
|
||||||
|
} cuint960m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[16];
|
||||||
|
} int1024m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int1024m_T re;
|
||||||
|
int1024m_T im;
|
||||||
|
} cint1024m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T chunks[16];
|
||||||
|
} uint1024m_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint1024m_T re;
|
||||||
|
uint1024m_T im;
|
||||||
|
} cuint1024m_T;
|
||||||
|
|
||||||
|
#endif /* MULTIWORD_TYPES_H */
|
||||||
Binary file not shown.
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef RTWTYPES_H
|
||||||
|
#define RTWTYPES_H
|
||||||
|
#include "tmwtypes.h"
|
||||||
|
#ifndef POINTER_T
|
||||||
|
#define POINTER_T
|
||||||
|
|
||||||
|
typedef void * pointer_T;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Logical type definitions */
|
||||||
|
#if (!defined(__cplusplus))
|
||||||
|
#ifndef false
|
||||||
|
#define false (0U)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef true
|
||||||
|
#define true (1U)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INT64_T
|
||||||
|
#define INT64_T
|
||||||
|
|
||||||
|
typedef long int64_T;
|
||||||
|
|
||||||
|
#define MAX_int64_T ((int64_T)(9223372036854775807L))
|
||||||
|
#define MIN_int64_T ((int64_T)(-9223372036854775807L-1L))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UINT64_T
|
||||||
|
#define UINT64_T
|
||||||
|
|
||||||
|
typedef unsigned long uint64_T;
|
||||||
|
|
||||||
|
#define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFUL))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* Additional complex number type definitions *
|
||||||
|
*===========================================================================*/
|
||||||
|
#ifndef CINT64_T
|
||||||
|
#define CINT64_T
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_T re;
|
||||||
|
int64_T im;
|
||||||
|
} cint64_T;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CUINT64_T
|
||||||
|
#define CUINT64_T
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_T re;
|
||||||
|
uint64_T im;
|
||||||
|
} cuint64_T;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* RTWTYPES_H */
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
|||||||
|
#include "customcode_jkx3iHsM9OOrSN3xw6c8aB.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Type Definitions */
|
||||||
|
|
||||||
|
/* Named Constants */
|
||||||
|
|
||||||
|
/* Variable Declarations */
|
||||||
|
|
||||||
|
/* Variable Definitions */
|
||||||
|
|
||||||
|
/* Function Declarations */
|
||||||
|
DLL_EXPORT_CC extern const char_T *get_dll_checksum_jkx3iHsM9OOrSN3xw6c8aB();
|
||||||
|
DLL_EXPORT_CC extern void *create_ModbusTCPClient_DTOtnS5jzeCt7wI4BrWszE_jkx3iHsM9OOrSN3xw6c8aB(const char_T *ip, int32_T port, int32_T numCoils, int32_T numDI, int32_T numIR, int32_T numHR, int32_T startCoils, int32_T startDI, int32_T startIR, int32_T startHR);
|
||||||
|
DLL_EXPORT_CC extern void *create_ModbusTCPClient_m6DHLsRJatb7jFhPa9sibF_jkx3iHsM9OOrSN3xw6c8aB(const char_T *ip, int32_T port);
|
||||||
|
DLL_EXPORT_CC extern void delete_ModbusTCPClient_IUI8Q2S0ulkAvLxLsx7k7_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern void ModbusTCPClient_setStartAddresses_WBPKyX5chtvoJpkQQz9yaE_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T startCoils, int32_T startDI, int32_T startIR, int32_T startHR);
|
||||||
|
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_connectServer_QWoAn8DsWluHwos1RJjgIB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern void ModbusTCPClient_disconnectServer_8RQB4Kyl2X5kNVGUlAlOgF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_isConnected_6gPjpu9NwavTxFjRzBfnHH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_reconnectServer_tmHQpYOBqsG4QOWlcN1JCG_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern void ModbusTCPClient_setTimeout_pKk7C4CiK7cGunjmXsoo9G_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T milliseconds);
|
||||||
|
DLL_EXPORT_CC extern void ModbusTCPClient_setCoil_uKV63H2F6Bk5GhMpqdzPnH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T value);
|
||||||
|
DLL_EXPORT_CC extern void ModbusTCPClient_setHoldingRegister_4XFxsavHXRTDHK2Ce0yJN_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T value);
|
||||||
|
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_getCoil_koLGZb1i8WN62u3e1PZwYH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||||
|
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_getDesiredCoil_4MZCcH6ezDGZg0uObXZUCC_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||||
|
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_getDiscreteInput_ae9HPljrPWD4BuZzmFBLEH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||||
|
DLL_EXPORT_CC extern uint16_T ModbusTCPClient_getHoldingRegister_mYLPn0wppPgH4bOhTiVvvF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||||
|
DLL_EXPORT_CC extern uint16_T ModbusTCPClient_getDesiredHoldingRegister_15FbNf22xvcBTZOmdfDtkC_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||||
|
DLL_EXPORT_CC extern uint16_T ModbusTCPClient_getInputRegister_ULtxwrYKJbrRxoQjkBCEs_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_getMultipleHoldingRegisters_dolsLHExIVVRdXIf6qYZmF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T startAddress, int32_T count, uint16_T *destination);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readAll_0LzP2HH0Zq4XkTmFCbG4o_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeAll_zaImFzR1o00mWpc4RczmN_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readCoil_zMFMzEaWMy4AM0fCGw6vkB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T *coilState);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleCoils_FsHZsYjrSrPY8P2Ay58lEB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, boolean_T *coilStates);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readDiscreteInput_hw3i2qSdn19YvGoOIzPSQF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T *discreteInput);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleDiscreteInputs_ejm6F8zFfmummwJiWr5WWE_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, boolean_T *discreteInputs);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readHoldingRegister_6gyuCNdZQDr6LxODE49ARC_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T *holdingRegister);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleHoldingRegisters_Nsd2PmYkYCsTdyTlOKb0KB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, uint16_T *holdingRegisters);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readInputRegister_LiIzv9TV0ONDt8VfLmy35G_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T *inputRegister);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleInputRegisters_two67DgbwFGoO6KyFi3I5B_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, uint16_T *inputRegisters);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeCoil_QoP3Zii3RZpABaPcesHRiB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T value);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeMultipleCoils_p5zcgcGPFH7wlbBhce5JYG_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, const boolean_T *values);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeHoldingRegister_mGVMywqtoVY5ZLnrtEy19G_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T value);
|
||||||
|
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeMultipleHoldingRegisters_ga2jca071NX41GYGjHLKzB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, const uint16_T *values);
|
||||||
|
|
||||||
|
/* Function Definitions */
|
||||||
|
DLL_EXPORT_CC const uint8_T *get_checksum_source_info(int32_T *size);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/ci/19700101 http://schema.mathworks.com/mf0/sl_modelref_info/R2024a http://schema.mathworks.com/mf0/slexec_mm_sto/R2024a_202305081229 http://schema.mathworks.com/mf0/sltp_mm/R2023a_202209151115">
|
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/ci/19700101 http://schema.mathworks.com/mf0/sl_modelref_info/R2024a http://schema.mathworks.com/mf0/slexec_mm_sto/R2024a_202305081229 http://schema.mathworks.com/mf0/sltp_mm/R2023a_202209151115">
|
||||||
<ModelRefInfoRepo.ModelRefInfoRoot type="ModelRefInfoRepo.ModelRefInfoRoot" uuid="8f646527-148b-4f42-bdcf-1b903ac56342">
|
<ModelRefInfoRepo.ModelRefInfoRoot type="ModelRefInfoRepo.ModelRefInfoRoot" uuid="11f5cea9-bf22-41ab-85c8-067958ac33d3">
|
||||||
<childModelRefInfo type="ModelRefInfoRepo.ChildModelRefInfo" uuid="7c651a86-5026-4c5e-9cb7-acebb2c56869">
|
<childModelRefInfo type="ModelRefInfoRepo.ChildModelRefInfo" uuid="20a7fd9e-726f-46b7-806c-40e167ccf8ba">
|
||||||
<modelName>uORB_MODBUS_TCP</modelName>
|
<modelName>uORB_MODBUS_TCP</modelName>
|
||||||
<modelPath>uORB_MODBUS_TCP</modelPath>
|
<modelPath>uORB_MODBUS_TCP</modelPath>
|
||||||
</childModelRefInfo>
|
</childModelRefInfo>
|
||||||
<compiledTFinal>10.0</compiledTFinal>
|
<compiledTFinal>10.0</compiledTFinal>
|
||||||
<dataSourceInfo type="ModelRefInfoRepo.DataSourceInfo" uuid="25f0742b-d008-457b-9aa8-d2b546462c75">
|
<dataSourceInfo type="ModelRefInfoRepo.DataSourceInfo" uuid="c5e1c170-5264-41da-bb91-5f0735d33d5a">
|
||||||
<dataSources type="ModelRefInfoRepo.SourceInfo" uuid="8e0336d3-048c-46e2-8f2c-a8929ef5bf10">
|
<dataSources type="ModelRefInfoRepo.SourceInfo" uuid="4003fcc4-1e43-4e5d-8cdf-fa6104070eb6">
|
||||||
<includeAllSections>true</includeAllSections>
|
<includeAllSections>true</includeAllSections>
|
||||||
<sourceName>base workspace</sourceName>
|
<sourceName>base workspace</sourceName>
|
||||||
<type>BaseWorkspace</type>
|
<type>BaseWorkspace</type>
|
||||||
@ -17,7 +17,11 @@
|
|||||||
<dataTransferInfos>AAFJTQAAAAAOAAAAOAAAAAYAAAAIAAAAAgAAAAAAAAAFAAAACAAAAAAAAAABAAAAAQAAAAAAAAAFAAQAAQAAAAEAAAAAAAAA</dataTransferInfos>
|
<dataTransferInfos>AAFJTQAAAAAOAAAAOAAAAAYAAAAIAAAAAgAAAAAAAAAFAAAACAAAAAAAAAABAAAAAQAAAAAAAAAFAAQAAQAAAAEAAAAAAAAA</dataTransferInfos>
|
||||||
<defaultsCMapping>{"Inports":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Outports":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","ParameterArguments":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","LocalParameters":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","GlobalParameters":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","InternalData":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","SharedLocalDataStores":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","GlobalDataStores":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Constants":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","DataTransfers":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","ModelData":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","InitializeTerminate":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Execution":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","SharedUtility":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}"}</defaultsCMapping>
|
<defaultsCMapping>{"Inports":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Outports":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","ParameterArguments":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","LocalParameters":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","GlobalParameters":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","InternalData":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","SharedLocalDataStores":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","GlobalDataStores":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Constants":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","DataTransfers":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","ModelData":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","InitializeTerminate":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Execution":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","SharedUtility":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}"}</defaultsCMapping>
|
||||||
<fastestNoncontSigFeedingDerivPorts>-1.0</fastestNoncontSigFeedingDerivPorts>
|
<fastestNoncontSigFeedingDerivPorts>-1.0</fastestNoncontSigFeedingDerivPorts>
|
||||||
<fundamentalSampleTimePeriod>5.0</fundamentalSampleTimePeriod>
|
<fundamentalSampleTimePeriod>.25</fundamentalSampleTimePeriod>
|
||||||
|
<globalVariables>px4_Bus_plc_coils_read</globalVariables>
|
||||||
|
<globalVariables>px4_Bus_plc_discrete_inputs</globalVariables>
|
||||||
|
<globalVariables>px4_Bus_plc_holding_registers_read</globalVariables>
|
||||||
|
<globalVariables>px4_Bus_plc_input_registers</globalVariables>
|
||||||
<hasBlockWithPeriodicDiscreteSampleTime>true</hasBlockWithPeriodicDiscreteSampleTime>
|
<hasBlockWithPeriodicDiscreteSampleTime>true</hasBlockWithPeriodicDiscreteSampleTime>
|
||||||
<hasBwsAccessed>true</hasBwsAccessed>
|
<hasBwsAccessed>true</hasBwsAccessed>
|
||||||
<isBdInSimModeForSimCodegenVariants>false</isBdInSimModeForSimCodegenVariants>
|
<isBdInSimModeForSimCodegenVariants>false</isBdInSimModeForSimCodegenVariants>
|
||||||
@ -29,59 +33,78 @@
|
|||||||
<runtimeNonFcnCallRateInfos type="ModelRefInfoRepo.RateInfo">
|
<runtimeNonFcnCallRateInfos type="ModelRefInfoRepo.RateInfo">
|
||||||
<compiled>true</compiled>
|
<compiled>true</compiled>
|
||||||
<nonFcnCallPartitionName>D1</nonFcnCallPartitionName>
|
<nonFcnCallPartitionName>D1</nonFcnCallPartitionName>
|
||||||
<period>5.0</period>
|
<period>.25</period>
|
||||||
<priority>40</priority>
|
<priority>40</priority>
|
||||||
<rateIdx>0</rateIdx>
|
<rateIdx>0</rateIdx>
|
||||||
</runtimeNonFcnCallRateInfos>
|
</runtimeNonFcnCallRateInfos>
|
||||||
|
<runtimeNonFcnCallRateInfos type="ModelRefInfoRepo.RateInfo">
|
||||||
|
<compiled>true</compiled>
|
||||||
|
<nonFcnCallPartitionName>D2</nonFcnCallPartitionName>
|
||||||
|
<period>5.0</period>
|
||||||
|
<priority>39</priority>
|
||||||
|
<rateIdx>1</rateIdx>
|
||||||
|
</runtimeNonFcnCallRateInfos>
|
||||||
<sampleTimeInheritanceRule>2</sampleTimeInheritanceRule>
|
<sampleTimeInheritanceRule>2</sampleTimeInheritanceRule>
|
||||||
<solverStatusFlags>335</solverStatusFlags>
|
<solverStatusFlags>335</solverStatusFlags>
|
||||||
<timingAndTaskingRegistry><?xml version="1.0"?>
|
<timingAndTaskingRegistry><?xml version="1.0"?>
|
||||||
<slexec_sto version="1.1" packageUris="http://schema.mathworks.com/mf0/slexec_mm_sto/R2024a_202305081229">
|
<slexec_sto version="1.1" packageUris="http://schema.mathworks.com/mf0/slexec_mm_sto/R2024a_202305081229">
|
||||||
<sto.Registry type="sto.Registry" uuid="ee73db1b-f182-40a7-b4b2-32cb5a9d4db8">
|
<sto.Registry type="sto.Registry" uuid="9f787942-3fbf-40bf-83d9-ca31d2944761">
|
||||||
<executionSpec>Undetermined</executionSpec>
|
<executionSpec>Undetermined</executionSpec>
|
||||||
<identifier>uORB_MODBUS_TCP</identifier>
|
<identifier>uORB_MODBUS_TCP</identifier>
|
||||||
<clockRegistry type="sto.ClockRegistry" uuid="ec9112c3-f7df-4d70-9e32-e8deed783d4b">
|
<clockRegistry type="sto.ClockRegistry" uuid="e3adf32f-9edb-41d2-8d65-2aa99a600d7d">
|
||||||
<clocks type="sto.Timer" uuid="2d74743a-7fa6-484f-840f-02b24087f560">
|
<clocks type="sto.Timer" uuid="3a0b736d-652a-409a-b254-5d476adf58b2">
|
||||||
<computedFundamentalDiscretePeriod>5.0</computedFundamentalDiscretePeriod>
|
<computedFundamentalDiscretePeriod>.25</computedFundamentalDiscretePeriod>
|
||||||
<fastestDiscreteRate type="sto.ClassicPeriodicDiscreteRate" uuid="29f1da5c-2a35-48ef-a7fe-a82629440e39"/>
|
<fastestDiscreteRate type="sto.ClassicPeriodicDiscreteRate" uuid="ba617304-1665-47a9-8567-cc2b033188ef"/>
|
||||||
<isDefaultTimer>true</isDefaultTimer>
|
<isDefaultTimer>true</isDefaultTimer>
|
||||||
<resolution>5.0</resolution>
|
<resolution>.25</resolution>
|
||||||
<timeAdvanceMode>FixedStep</timeAdvanceMode>
|
<timeAdvanceMode>FixedStep</timeAdvanceMode>
|
||||||
<identifier>uORB_MODBUS_TCP::defaultTimer</identifier>
|
<identifier>uORB_MODBUS_TCP::defaultTimer</identifier>
|
||||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="29f1da5c-2a35-48ef-a7fe-a82629440e39">
|
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="ba617304-1665-47a9-8567-cc2b033188ef">
|
||||||
<annotation>D1</annotation>
|
<annotation>D1</annotation>
|
||||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
<description>Discrete 1</description>
|
<description>Discrete 1</description>
|
||||||
<taskId>_task0</taskId>
|
<taskId>_task0</taskId>
|
||||||
<rateSpec type="sto.RateSpec" uuid="1368f082-b58c-4c67-b97a-0fb3024453e7">
|
<rateSpec type="sto.RateSpec" uuid="26cde9ad-fd89-4996-b202-d4b6c44daffc">
|
||||||
|
<period>.25</period>
|
||||||
|
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||||
|
</rateSpec>
|
||||||
|
</rates>
|
||||||
|
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="6f6b4dea-ac0b-4961-855e-736959b539d1">
|
||||||
|
<annotation>D2</annotation>
|
||||||
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
|
<colorIndex>1</colorIndex>
|
||||||
|
<description>Discrete 2</description>
|
||||||
|
<rateIdx>1</rateIdx>
|
||||||
|
<taskId>_task1</taskId>
|
||||||
|
<rateSpec type="sto.RateSpec" uuid="f257fe37-2af7-417a-b5c7-0428c312f42d">
|
||||||
<period>5.0</period>
|
<period>5.0</period>
|
||||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||||
</rateSpec>
|
</rateSpec>
|
||||||
</rates>
|
</rates>
|
||||||
<baseRate type="sto.ClassicPeriodicDiscreteRate" uuid="fc5d4684-395b-44c9-8cfa-430a2d34b8de">
|
<baseRate type="sto.ClassicPeriodicDiscreteRate" uuid="65b35d5e-227d-4911-bc52-2893aadaefbf">
|
||||||
<annotation>D1</annotation>
|
<annotation>D1</annotation>
|
||||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
<description>Discrete 1</description>
|
<description>Discrete 1</description>
|
||||||
<taskId>_task0</taskId>
|
<taskId>_task0</taskId>
|
||||||
<rateSpec type="sto.RateSpec" uuid="ae85af8c-7a93-4769-abad-dfb66bc50c8e">
|
<rateSpec type="sto.RateSpec" uuid="ff2d4d8a-96eb-48d4-9f8f-062960f9fb1d">
|
||||||
<period>5.0</period>
|
<period>.25</period>
|
||||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||||
</rateSpec>
|
</rateSpec>
|
||||||
</baseRate>
|
</baseRate>
|
||||||
</clocks>
|
</clocks>
|
||||||
<timeAdvanceMode>FixedStep</timeAdvanceMode>
|
<timeAdvanceMode>FixedStep</timeAdvanceMode>
|
||||||
</clockRegistry>
|
</clockRegistry>
|
||||||
<taskRegistry type="sto.TaskRegistry" uuid="052f32c4-2b96-4908-913e-03a4854d96c0">
|
<taskRegistry type="sto.TaskRegistry" uuid="b6adc007-26b8-402c-b01d-1e3d81bb5c20">
|
||||||
<rootTaskHierarchyElements type="sto.Task" uuid="8de7de87-835c-46ef-ad46-f88050f2605e">
|
<rootTaskHierarchyElements type="sto.Task" uuid="5edff6a2-d515-4f58-a3d8-c5326ec15f76">
|
||||||
<isExecutable>true</isExecutable>
|
<isExecutable>true</isExecutable>
|
||||||
<orderIndex>1</orderIndex>
|
<orderIndex>1</orderIndex>
|
||||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="287f9e9c-18e9-462d-bf56-5a7dc6aad9b7">
|
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="f55c6bcc-446d-42c6-90e7-ff6c2ff6f624">
|
||||||
<annotation>D1</annotation>
|
<annotation>D1</annotation>
|
||||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
<description>Discrete 1</description>
|
<description>Discrete 1</description>
|
||||||
<taskId>_task0</taskId>
|
<taskId>_task0</taskId>
|
||||||
<rateSpec type="sto.RateSpec" uuid="31b43a7e-4ce0-4be9-a684-8e88514ad3d8">
|
<rateSpec type="sto.RateSpec" uuid="d3854663-c664-46a3-a0a9-41f57f4994dd">
|
||||||
<period>5.0</period>
|
<period>.25</period>
|
||||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||||
</rateSpec>
|
</rateSpec>
|
||||||
</rates>
|
</rates>
|
||||||
@ -91,7 +114,33 @@
|
|||||||
<identifier>_task0</identifier>
|
<identifier>_task0</identifier>
|
||||||
<priority>40</priority>
|
<priority>40</priority>
|
||||||
</rootTaskHierarchyElements>
|
</rootTaskHierarchyElements>
|
||||||
<taskDependencyGraph type="sto.SerializedTaskConnectionList" uuid="6a78d61d-7a32-4285-b101-584200d36c5c">
|
<rootTaskHierarchyElements type="sto.Task" uuid="a86fefe7-45e4-423e-9db6-880c90fa3d37">
|
||||||
|
<isExecutable>true</isExecutable>
|
||||||
|
<orderIndex>2</orderIndex>
|
||||||
|
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="8d76a60f-fbc0-4d52-b0c5-783585f4eb4e">
|
||||||
|
<annotation>D2</annotation>
|
||||||
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
|
<colorIndex>1</colorIndex>
|
||||||
|
<description>Discrete 2</description>
|
||||||
|
<rateIdx>1</rateIdx>
|
||||||
|
<taskId>_task1</taskId>
|
||||||
|
<rateSpec type="sto.RateSpec" uuid="7e68009f-8a4a-4dac-9abb-5a4cbf16a75c">
|
||||||
|
<period>5.0</period>
|
||||||
|
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||||
|
</rateSpec>
|
||||||
|
</rates>
|
||||||
|
<schedulingClockId>uORB_MODBUS_TCP::defaultTimer</schedulingClockId>
|
||||||
|
<tNum>1</tNum>
|
||||||
|
<timeKeeperClockId>uORB_MODBUS_TCP::defaultTimer</timeKeeperClockId>
|
||||||
|
<elementType>Task</elementType>
|
||||||
|
<identifier>_task1</identifier>
|
||||||
|
<priority>39</priority>
|
||||||
|
</rootTaskHierarchyElements>
|
||||||
|
<taskDependencyGraph type="sto.SerializedTaskConnectionList" uuid="d51d07bc-b865-4d1b-bd8f-102c79ccc172">
|
||||||
|
<clockIdentifier>uORB_MODBUS_TCP::defaultTimer</clockIdentifier>
|
||||||
|
<taskIdentifier>_task1</taskIdentifier>
|
||||||
|
</taskDependencyGraph>
|
||||||
|
<taskDependencyGraph type="sto.SerializedTaskConnectionList" uuid="711a613b-96b6-4f2f-bbfe-1a5d260148ac">
|
||||||
<clockIdentifier>uORB_MODBUS_TCP::defaultTimer</clockIdentifier>
|
<clockIdentifier>uORB_MODBUS_TCP::defaultTimer</clockIdentifier>
|
||||||
<taskIdentifier>_task0</taskIdentifier>
|
<taskIdentifier>_task0</taskIdentifier>
|
||||||
</taskDependencyGraph>
|
</taskDependencyGraph>
|
||||||
@ -100,20 +149,22 @@
|
|||||||
</sto.Registry>
|
</sto.Registry>
|
||||||
</slexec_sto></timingAndTaskingRegistry>
|
</slexec_sto></timingAndTaskingRegistry>
|
||||||
<zeroInternalMemoryAtStartupUnchecked>true</zeroInternalMemoryAtStartupUnchecked>
|
<zeroInternalMemoryAtStartupUnchecked>true</zeroInternalMemoryAtStartupUnchecked>
|
||||||
<FMUBlockMap type="ModelRefInfoRepo.FMUBlockInfo" uuid="b78c3852-febd-4438-a3c4-ba931993565b"/>
|
<FMUBlockMap type="ModelRefInfoRepo.FMUBlockInfo" uuid="981c6145-983b-408d-b0f1-66d4d59e61bd"/>
|
||||||
<codeGenInfo type="ModelRefInfoRepo.CodeGenInformation" uuid="7b955e3c-022c-4677-b8a9-5a34881d940a"/>
|
<codeGenInfo type="ModelRefInfoRepo.CodeGenInformation" uuid="81098c80-e40c-4c3b-ba26-ce2b20c73848"/>
|
||||||
<compiledVariantInfos type="ModelRefInfoRepo.CompiledVariantInfoMap" uuid="709fdb14-b8b3-46bb-9cc1-e5b855385f4e"/>
|
<compiledVariantInfos type="ModelRefInfoRepo.CompiledVariantInfoMap" uuid="988faa22-55fc-4f06-9327-f94f07e57c00"/>
|
||||||
<configSettingsForConsistencyChecks type="ModelRefInfoRepo.ConfigSettingsForConsistencyChecks" uuid="fe654506-60ec-46dc-be72-6db6f70d77f4">
|
<configSettingsForConsistencyChecks type="ModelRefInfoRepo.ConfigSettingsForConsistencyChecks" uuid="ebc3161f-26a9-4b8c-ba43-4532a7f046ee">
|
||||||
<consistentOutportInitialization>true</consistentOutportInitialization>
|
<consistentOutportInitialization>true</consistentOutportInitialization>
|
||||||
<fixedStepSize>5.0</fixedStepSize>
|
<fixedStepSize>.25</fixedStepSize>
|
||||||
<frameDiagnosticSetting>2</frameDiagnosticSetting>
|
<frameDiagnosticSetting>2</frameDiagnosticSetting>
|
||||||
<hasHybridSampleTime>true</hasHybridSampleTime>
|
<hasHybridSampleTime>true</hasHybridSampleTime>
|
||||||
|
<isRateGrouped>true</isRateGrouped>
|
||||||
<optimizedInitCode>true</optimizedInitCode>
|
<optimizedInitCode>true</optimizedInitCode>
|
||||||
<signalLoggingSaveFormat>2</signalLoggingSaveFormat>
|
<signalLoggingSaveFormat>2</signalLoggingSaveFormat>
|
||||||
<simSIMDOptimization>1</simSIMDOptimization>
|
<simSIMDOptimization>1</simSIMDOptimization>
|
||||||
|
<solverMode>SOLVER_MODE_MULTITASKING</solverMode>
|
||||||
<solverName>FixedStepDiscrete</solverName>
|
<solverName>FixedStepDiscrete</solverName>
|
||||||
<solverType>SOLVER_TYPE_FIXEDSTEP</solverType>
|
<solverType>SOLVER_TYPE_FIXEDSTEP</solverType>
|
||||||
<hardwareSettings type="ModelRefInfoRepo.HardwareSettings" uuid="148971a5-1ef8-4886-8ea5-2a5c767e1eca">
|
<hardwareSettings type="ModelRefInfoRepo.HardwareSettings" uuid="bcefbbaa-5f50-491b-aa4f-b0027735af00">
|
||||||
<prodBitPerChar>8</prodBitPerChar>
|
<prodBitPerChar>8</prodBitPerChar>
|
||||||
<prodBitPerDouble>64</prodBitPerDouble>
|
<prodBitPerDouble>64</prodBitPerDouble>
|
||||||
<prodBitPerFloat>32</prodBitPerFloat>
|
<prodBitPerFloat>32</prodBitPerFloat>
|
||||||
@ -132,34 +183,35 @@
|
|||||||
<prodWordSize>32</prodWordSize>
|
<prodWordSize>32</prodWordSize>
|
||||||
</hardwareSettings>
|
</hardwareSettings>
|
||||||
</configSettingsForConsistencyChecks>
|
</configSettingsForConsistencyChecks>
|
||||||
<controllableInputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="ec0551ad-1a96-4d56-9856-f3704f7b2c67"/>
|
<controllableInputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="00777ed3-9b83-4205-9df1-9c63207c8b32"/>
|
||||||
<controllableOutputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="7a67cd19-1051-4cad-ad1f-7d6cf77fc3ac"/>
|
<controllableOutputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="75ff445e-a4bf-4bb5-bb10-1e29540bc9a2"/>
|
||||||
<dataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="438f73bd-1c23-42f8-81b6-0cfe9392c804"/>
|
<dataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="29dc6b09-d5cb-4280-81ef-8b32487ec875"/>
|
||||||
<expFcnUnconnectedDataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="b6970967-995e-4489-8214-c87f28f9a2d2"/>
|
<expFcnUnconnectedDataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="042d7f00-00ba-4bd0-b0d3-e795640ddff8"/>
|
||||||
<interfaceParameterInfo type="ModelRefInfoRepo.InterfaceParameterInfo" uuid="af6f3444-fe96-491b-8aa1-cd25b76e1cc5"/>
|
<interfaceParameterInfo type="ModelRefInfoRepo.InterfaceParameterInfo" uuid="6ace8d3c-49f7-40d5-82f7-93466352fc19"/>
|
||||||
<messageInfo type="ModelRefInfoRepo.MessageInformation" uuid="f408063d-0f9a-4cf7-9bd9-23468c11595f"/>
|
<messageInfo type="ModelRefInfoRepo.MessageInformation" uuid="586ee838-920e-4f37-a8f5-cb14a8473327"/>
|
||||||
<methodInfo type="ModelRefInfoRepo.MethodExistenceInfo" uuid="d4945a20-1132-4e2f-bafb-baadb0367111"/>
|
<methodInfo type="ModelRefInfoRepo.MethodExistenceInfo" uuid="8341f440-358c-4086-8c0b-75eff483cdef">
|
||||||
<periodicEventPortUnsupportedBlockInfo type="ModelRefInfoRepo.PeriodicEventPortUnsupportedBlockInfo" uuid="873d196f-089c-4580-b702-7c7b703e93b7"/>
|
<hasTerminateMethod>true</hasTerminateMethod>
|
||||||
<portGroupsRequireSameRate type="ModelRefInfoRepo.PortGroupsRequireSameRate" uuid="fa0abc97-6be3-468c-81ff-48f326095818">
|
</methodInfo>
|
||||||
<DSMPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="4df51b3a-64c5-4052-9891-f538b30df737"/>
|
<periodicEventPortUnsupportedBlockInfo type="ModelRefInfoRepo.PeriodicEventPortUnsupportedBlockInfo" uuid="8fd011f1-feb4-43a7-9dcc-3bafbb76b6e8"/>
|
||||||
<GlobalDSMPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="b859e8d4-8f6e-46db-99e9-525cec7de320"/>
|
<portGroupsRequireSameRate type="ModelRefInfoRepo.PortGroupsRequireSameRate" uuid="fa458fff-85e6-462e-89ff-b1f375c0a4fa">
|
||||||
<mergedPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="5e607a43-12a1-4dff-8081-717abd030776"/>
|
<DSMPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="386c1438-eb1b-4763-8256-e73e4f9399ce"/>
|
||||||
|
<GlobalDSMPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="a9c9a3fc-949d-4c0d-9826-61749e429496"/>
|
||||||
|
<mergedPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="074194fb-6427-4db9-95a7-14d86e9fcd9f"/>
|
||||||
</portGroupsRequireSameRate>
|
</portGroupsRequireSameRate>
|
||||||
<rateBasedMdlGlobalDSMRateSpec type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="19f34c02-c41d-4a06-b0b4-8b40a821a007"/>
|
<rateBasedMdlGlobalDSMRateSpec type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="554fa760-8e30-4445-adb6-9ac9ee9c6cd5"/>
|
||||||
<rateSpecOfGlobalDSMAccessedByDescExpFcnMdlMap type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="45484e10-296f-4fb2-9888-8efc6a0a0759"/>
|
<rateSpecOfGlobalDSMAccessedByDescExpFcnMdlMap type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="e98c7b33-62d6-48d1-87e7-fe44780e8d49"/>
|
||||||
<rootBlockDiagramInterface type="ci.Model" uuid="1efa62d5-e252-4708-a49b-d383b4db946f">
|
<rootBlockDiagramInterface type="ci.Model" uuid="12261508-8e65-4ff5-8eac-e1f47b47814f">
|
||||||
<p_RootComponentInterface type="ci.ComponentInterface" uuid="f3987313-e44d-4276-b713-814de3442198">
|
<p_RootComponentInterface type="ci.ComponentInterface" uuid="f75dbd08-8409-4f75-b7b7-8d20ad28a353">
|
||||||
<p_Name>uORB_MODBUS_TCP</p_Name>
|
<p_Name>uORB_MODBUS_TCP</p_Name>
|
||||||
<p_Type>ROOT</p_Type>
|
<p_Type>ROOT</p_Type>
|
||||||
</p_RootComponentInterface>
|
</p_RootComponentInterface>
|
||||||
</rootBlockDiagramInterface>
|
</rootBlockDiagramInterface>
|
||||||
<simulinkFunctions type="ModelRefInfoRepo.SimulinkFunctions" uuid="6e092575-a0c4-4956-9e38-a54720508fe7">
|
<simulinkFunctions type="ModelRefInfoRepo.SimulinkFunctions" uuid="a445c89f-0276-4914-90ae-cc80358a9793">
|
||||||
<compSimulinkFunctionCatalog></compSimulinkFunctionCatalog>
|
<compSimulinkFunctionCatalog></compSimulinkFunctionCatalog>
|
||||||
</simulinkFunctions>
|
</simulinkFunctions>
|
||||||
<sltpContext type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1">
|
<sltpContext type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1">
|
||||||
<unusedTaskIds>2</unusedTaskIds>
|
|
||||||
<unusedTaskIds>4</unusedTaskIds>
|
|
||||||
<unusedTaskIds>3</unusedTaskIds>
|
<unusedTaskIds>3</unusedTaskIds>
|
||||||
|
<unusedTaskIds>2</unusedTaskIds>
|
||||||
<defaultEventBehavior type="sltp.mm.core.EventBehavior" uuid="21e3b347-5d31-4104-934b-203b90595926"/>
|
<defaultEventBehavior type="sltp.mm.core.EventBehavior" uuid="21e3b347-5d31-4104-934b-203b90595926"/>
|
||||||
<editorState type="sltp.mm.core.EditorState" uuid="07d98215-aad0-45df-84e8-46192d73c28f">
|
<editorState type="sltp.mm.core.EditorState" uuid="07d98215-aad0-45df-84e8-46192d73c28f">
|
||||||
<isSynchronized>true</isSynchronized>
|
<isSynchronized>true</isSynchronized>
|
||||||
@ -171,49 +223,77 @@
|
|||||||
<name>Default</name>
|
<name>Default</name>
|
||||||
<priority>-2147483648</priority>
|
<priority>-2147483648</priority>
|
||||||
<subgraph type="sltp.mm.core.Graph" uuid="3c284f03-9522-4f9e-b770-1cc523c8d4c7">
|
<subgraph type="sltp.mm.core.Graph" uuid="3c284f03-9522-4f9e-b770-1cc523c8d4c7">
|
||||||
|
<tasks type="sltp.mm.core.Task" uuid="e991ebe0-03e4-494a-934d-c2710a125f88">
|
||||||
|
<context type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1"/>
|
||||||
|
<explicit>false</explicit>
|
||||||
|
<id>4</id>
|
||||||
|
<isTimed>true</isTimed>
|
||||||
|
<name>D1</name>
|
||||||
|
<priority>40</priority>
|
||||||
|
<rates type="sltp.mm.core.Rate" uuid="d782d467-7cac-45ed-8c62-7c13d9bbe2dd">
|
||||||
|
<annotation>D1</annotation>
|
||||||
|
<color>-12240129</color>
|
||||||
|
<hasBlocks>true</hasBlocks>
|
||||||
|
<identifier>ClassicPeriodicDiscrete0.250</identifier>
|
||||||
|
<rateIndex>0</rateIndex>
|
||||||
|
<rateSpec type="sltp.mm.core.RateSpec">
|
||||||
|
<period>.25</period>
|
||||||
|
</rateSpec>
|
||||||
|
<sti>0</sti>
|
||||||
|
</rates>
|
||||||
|
</tasks>
|
||||||
<tasks type="sltp.mm.core.Task" uuid="dc5bb398-72a8-4378-9caf-1d7a75ccb53c">
|
<tasks type="sltp.mm.core.Task" uuid="dc5bb398-72a8-4378-9caf-1d7a75ccb53c">
|
||||||
<context type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1"/>
|
<context type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1"/>
|
||||||
<explicit>false</explicit>
|
<explicit>false</explicit>
|
||||||
<id>1</id>
|
<id>1</id>
|
||||||
<isTimed>true</isTimed>
|
<isTimed>true</isTimed>
|
||||||
<name>D1</name>
|
<name>D2</name>
|
||||||
<priority>40</priority>
|
<priority>39</priority>
|
||||||
<rates type="sltp.mm.core.Rate" uuid="03620e11-eb05-4414-bdcb-7c2cf9edc125">
|
<rates type="sltp.mm.core.Rate" uuid="03620e11-eb05-4414-bdcb-7c2cf9edc125">
|
||||||
<annotation>D1</annotation>
|
<annotation>D2</annotation>
|
||||||
<color>-12240129</color>
|
<color>986198527</color>
|
||||||
<hasBlocks>true</hasBlocks>
|
<hasBlocks>true</hasBlocks>
|
||||||
<identifier>ClassicPeriodicDiscrete50</identifier>
|
<identifier>ClassicPeriodicDiscrete50</identifier>
|
||||||
<rateIndex>0</rateIndex>
|
<rateIndex>1</rateIndex>
|
||||||
<rateSpec type="sltp.mm.core.RateSpec">
|
<rateSpec type="sltp.mm.core.RateSpec">
|
||||||
<period>5.0</period>
|
<period>5.0</period>
|
||||||
</rateSpec>
|
</rateSpec>
|
||||||
<sti>0</sti>
|
<sti>1</sti>
|
||||||
</rates>
|
</rates>
|
||||||
</tasks>
|
</tasks>
|
||||||
</subgraph>
|
</subgraph>
|
||||||
</rootTask>
|
</rootTask>
|
||||||
</sltpContext>
|
</sltpContext>
|
||||||
<stateWriterToOwnerMap type="ModelRefInfoRepo.StateWriterInfo" uuid="7f963979-9bcb-4a12-a87e-7df772451a89"/>
|
<stateWriterToOwnerMap type="ModelRefInfoRepo.StateWriterInfo" uuid="27003578-7b2d-4c90-aee7-fe7cb04dd50d"/>
|
||||||
<stoClientDataRegistry type="sto.ClientDataRegistry" uuid="a1f49343-a294-473a-a178-26618b4668f8">
|
<stoClientDataRegistry type="sto.ClientDataRegistry" uuid="b666e450-35bb-4dd8-b7f4-ccfb90f1962c">
|
||||||
<dataSets type="sto.ClientClockNamedDataSet" uuid="d0159836-75ae-4680-bf92-b48a16f424bb">
|
<dataSets type="sto.ClientClockNamedDataSet" uuid="3439df2d-bbdd-4e43-9bf3-7404c5ffe8a0">
|
||||||
<tag>sltpEvents</tag>
|
<tag>sltpEvents</tag>
|
||||||
</dataSets>
|
</dataSets>
|
||||||
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="5d8d7d5b-38ce-4410-86e0-45e0f3cbb56b">
|
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="ff48cb56-2c3f-462e-ba5f-1624780fae24">
|
||||||
<tag>sltpTaskGroups</tag>
|
<tag>sltpTaskGroups</tag>
|
||||||
</dataSets>
|
</dataSets>
|
||||||
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="ca090357-8c2d-4706-bef0-51cdea588c97">
|
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="8e3be1df-6fa9-4289-9165-b2e620bf0adf">
|
||||||
<dSet type="ModelRefInfoRepo.SltpTaskData" uuid="dde5ee80-ff9e-4fcd-8481-a11df1dc59ed"/>
|
<dSet type="ModelRefInfoRepo.SltpTaskData" uuid="5c6cd961-bad7-473b-afcb-505519e8c5be"/>
|
||||||
<tSet type="ModelRefInfoRepo.SltpTaskData" uuid="dde5ee80-ff9e-4fcd-8481-a11df1dc59ed">
|
<dSet type="ModelRefInfoRepo.SltpTaskData" uuid="5289e2d2-d218-4b66-b92f-5754852a9c90"/>
|
||||||
|
<tSet type="ModelRefInfoRepo.SltpTaskData" uuid="5c6cd961-bad7-473b-afcb-505519e8c5be">
|
||||||
<dataName>D1</dataName>
|
<dataName>D1</dataName>
|
||||||
<linkedSet type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="ca090357-8c2d-4706-bef0-51cdea588c97"/>
|
<linkedSet type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="8e3be1df-6fa9-4289-9165-b2e620bf0adf"/>
|
||||||
<id type="sto.TaskHierarchyElementId">
|
<id type="sto.TaskHierarchyElementId">
|
||||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
<id>_task0</id>
|
<id>_task0</id>
|
||||||
</id>
|
</id>
|
||||||
</tSet>
|
</tSet>
|
||||||
|
<tSet type="ModelRefInfoRepo.SltpTaskData" uuid="5289e2d2-d218-4b66-b92f-5754852a9c90">
|
||||||
|
<dataName>D2</dataName>
|
||||||
|
<linkedSet type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="8e3be1df-6fa9-4289-9165-b2e620bf0adf"/>
|
||||||
|
<id type="sto.TaskHierarchyElementId">
|
||||||
|
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||||
|
<id>_task1</id>
|
||||||
|
</id>
|
||||||
|
</tSet>
|
||||||
<tag>sltpTasks</tag>
|
<tag>sltpTasks</tag>
|
||||||
</dataSets>
|
</dataSets>
|
||||||
</stoClientDataRegistry>
|
</stoClientDataRegistry>
|
||||||
<varTsUIDMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="a16da2ea-bdff-4f8d-84df-e1e6fa8d37f7"/>
|
<varTsUIDMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="9faef9fa-1bd4-43a3-bee9-6be26afe201d"/>
|
||||||
</ModelRefInfoRepo.ModelRefInfoRoot>
|
</ModelRefInfoRepo.ModelRefInfoRoot>
|
||||||
</MF0>
|
</MF0>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/SlCache/19700101">
|
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/SlCache/19700101">
|
||||||
<slcache.FileAttributes type="slcache.FileAttributes" uuid="714b24d4-7c5b-48b5-b852-087cf102ecde">
|
<slcache.FileAttributes type="slcache.FileAttributes" uuid="c674998f-0be5-4035-8ad2-943c5087b773">
|
||||||
<checksum>DdrRgVnyR6kegWj1mpzaDcyS+Rh4VBoYEPYCL7/LAGEIf+p+iTuTZYWKYUM1yL59ppS4QwFUE2pBT336Wo0z0Q==</checksum>
|
<checksum>/s11ahv8mqi9vbwi2UlouCYjA9mjT/SmcREmK0z6aZ3EQci35TC+5lA8FKJ8gHVO/ti5sHt+uyYmU1Xb7DYBzg==</checksum>
|
||||||
</slcache.FileAttributes>
|
</slcache.FileAttributes>
|
||||||
</MF0>
|
</MF0>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,16 +5,19 @@ set(MAVLINK_LIBRARY_DIR "${CMAKE_BINARY_DIR}/mavlink")
|
|||||||
set(MAVLINK_DIALECT_UAVIONIX "uAvionix")
|
set(MAVLINK_DIALECT_UAVIONIX "uAvionix")
|
||||||
|
|
||||||
add_definitions(
|
add_definitions(
|
||||||
-DMODEL=uORB_MODBUS_TCP -DNUMST=1 -DNCSTATES=0 -DHAVESTDIO -DMODEL_HAS_DYNAMICALLY_LOADED_SFCNS=0 -DCLASSIC_INTERFACE=0 -DALLOCATIONFCN=0 -DTID01EQ=0 -DTERMFCN=1 -DONESTEPFCN=1 -DMAT_FILE=0 -DMULTI_INSTANCE_CODE=0 -DINTEGER_CODE=0 -DMT=0 -DPX4 -DFMUv6x -DNULL=0 -DMW_PX4_NUTTX_BUILD -DEXTMODE_DISABLETESTING -DEXTMODE_DISABLEPRINTF -DEXTMODE_DISABLE_ARGS_PROCESSING=1 -D__linux__ -DXCP_PLATFORM_LINUX_NO_PIE_SUPPORT -DSTACK_SIZE=64 -D__MW_TARGET_USE_HARDWARE_RESOURCES_H__ -DRT )
|
-DMODEL=uORB_MODBUS_TCP -DNUMST=2 -DNCSTATES=0 -DHAVESTDIO -DMODEL_HAS_DYNAMICALLY_LOADED_SFCNS=0 -DCLASSIC_INTERFACE=0 -DALLOCATIONFCN=0 -DTID01EQ=0 -DTERMFCN=1 -DONESTEPFCN=1 -DMAT_FILE=0 -DMULTI_INSTANCE_CODE=0 -DINTEGER_CODE=0 -DMT=1 -DPX4 -DFMUv6x -DNULL=0 -DMW_PX4_NUTTX_BUILD -DEXTMODE_DISABLETESTING -DEXTMODE_DISABLEPRINTF -DEXTMODE_DISABLE_ARGS_PROCESSING=1 -D__linux__ -DXCP_PLATFORM_LINUX_NO_PIE_SUPPORT -DSTACK_SIZE=64 -D__MW_TARGET_USE_HARDWARE_RESOURCES_H__ -DRT )
|
||||||
|
|
||||||
px4_add_module(
|
px4_add_module(
|
||||||
MODULE modules__px4_simulink_app
|
MODULE modules__px4_simulink_app
|
||||||
MAIN px4_simulink_app
|
MAIN px4_simulink_app
|
||||||
STACK_MAIN 2000
|
STACK_MAIN 2000
|
||||||
SRCS
|
SRCS
|
||||||
|
MW_uORB_Read.cpp
|
||||||
|
MW_uORB_Write.cpp
|
||||||
|
modbus_tcp_client.cpp
|
||||||
ert_main.cpp
|
ert_main.cpp
|
||||||
uORB_MODBUS_TCP.cpp
|
uORB_MODBUS_TCP.cpp
|
||||||
modbus_tcp_client.cpp
|
uORB_MODBUS_TCP_data.cpp
|
||||||
MW_PX4_TaskControl.cpp
|
MW_PX4_TaskControl.cpp
|
||||||
nuttxinitialize.cpp
|
nuttxinitialize.cpp
|
||||||
COMPILE_FLAGS
|
COMPILE_FLAGS
|
||||||
@ -27,14 +30,15 @@ SRCS
|
|||||||
${MAVLINK_LIBRARY_DIR}
|
${MAVLINK_LIBRARY_DIR}
|
||||||
${MAVLINK_LIBRARY_DIR}/${CONFIG_MAVLINK_DIALECT}
|
${MAVLINK_LIBRARY_DIR}/${CONFIG_MAVLINK_DIALECT}
|
||||||
${MAVLINK_LIBRARY_DIR}/${MAVLINK_DIALECT_UAVIONIX}
|
${MAVLINK_LIBRARY_DIR}/${MAVLINK_DIALECT_UAVIONIX}
|
||||||
/home/judson/GSE-Miscellaneous/Pixhawk_and_GSE/MATLAB/uORB_MODBUS_TCP
|
/home/judson/Pixhawk/MATLAB/uORB_MODBUS_TCP
|
||||||
/home/judson/GSE-Miscellaneous/Pixhawk_and_GSE/MATLAB/uORB_MODBUS_TCP/uORB_MODBUS_TCP_ert_rtw
|
/home/judson/Documents/MATLAB/SupportPackages/R2024a/toolbox/target/supportpackages/px4/include
|
||||||
/usr/local/MATLAB/R2024a/extern/include
|
/home/judson/Pixhawk/MATLAB
|
||||||
/usr/local/MATLAB/R2024a/simulink/include
|
/home/judson/Pixhawk/MATLAB/uORB_MODBUS_TCP/uORB_MODBUS_TCP_ert_rtw
|
||||||
/usr/local/MATLAB/R2024a/rtw/c/src
|
/home/judson/MATLAB/extern/include
|
||||||
/usr/local/MATLAB/R2024a/rtw/c/src/ext_mode/common
|
/home/judson/MATLAB/simulink/include
|
||||||
/usr/local/MATLAB/R2024a/rtw/c/ert
|
/home/judson/MATLAB/rtw/c/src
|
||||||
/root/Documents/MATLAB/SupportPackages/R2024a/toolbox/target/supportpackages/px4/include
|
/home/judson/MATLAB/rtw/c/src/ext_mode/common
|
||||||
|
/home/judson/MATLAB/rtw/c/ert
|
||||||
)
|
)
|
||||||
|
|
||||||
get_target_property(PX4_SL_APP_COMPILE_FLAGS modules__px4_simulink_app COMPILE_OPTIONS)
|
get_target_property(PX4_SL_APP_COMPILE_FLAGS modules__px4_simulink_app COMPILE_OPTIONS)
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
#ifndef _MW_CUSTOM_RTOS_HEADER_H_
|
#ifndef _MW_CUSTOM_RTOS_HEADER_H_
|
||||||
#define _MW_CUSTOM_RTOS_HEADER_H_
|
#define _MW_CUSTOM_RTOS_HEADER_H_
|
||||||
#define MW_BASERATE_PRIORITY 250
|
#define MW_BASERATE_PRIORITY 250
|
||||||
#define MW_BASERATE_PERIOD 5.0
|
#define MW_BASERATE_PERIOD 0.25
|
||||||
#define MW_NUMBER_SUBRATES 0
|
#define MW_NUMBER_SUBRATES 1
|
||||||
#define MW_NUMBER_APERIODIC_TASKS 0
|
#define MW_NUMBER_APERIODIC_TASKS 0
|
||||||
#define MW_IS_CONCURRENT 0
|
#define MW_IS_CONCURRENT 0
|
||||||
#define MW_NUMBER_TIMER_DRIVEN_TASKS 0
|
#define MW_NUMBER_TIMER_DRIVEN_TASKS 0
|
||||||
|
#define MW_HAS_MULTIPLE_RATES
|
||||||
|
|
||||||
extern void exitFcn(int sig);
|
extern void exitFcn(int sig);
|
||||||
extern void *terminateTask(void *arg);
|
extern void *terminateTask(void *arg);
|
||||||
|
|||||||
@ -1,6 +1,14 @@
|
|||||||
#ifndef _MW_UORB_BUSSTRUCT_CONVERSION_H_
|
#ifndef _MW_UORB_BUSSTRUCT_CONVERSION_H_
|
||||||
#define _MW_UORB_BUSSTRUCT_CONVERSION_H_
|
#define _MW_UORB_BUSSTRUCT_CONVERSION_H_
|
||||||
|
|
||||||
|
#include <uORB/topics/plc_coils_read.h>
|
||||||
|
#include <uORB/topics/plc_discrete_inputs.h>
|
||||||
|
#include <uORB/topics/plc_holding_registers_read.h>
|
||||||
|
#include <uORB/topics/plc_input_registers.h>
|
||||||
|
|
||||||
|
typedef struct plc_coils_read_s px4_Bus_plc_coils_read ;
|
||||||
|
typedef struct plc_discrete_inputs_s px4_Bus_plc_discrete_inputs ;
|
||||||
|
typedef struct plc_holding_registers_read_s px4_Bus_plc_holding_registers_read ;
|
||||||
|
typedef struct plc_input_registers_s px4_Bus_plc_input_registers ;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
@ -36,22 +36,63 @@ volatile boolean_T stopRequested = false;
|
|||||||
volatile boolean_T runModel = true;
|
volatile boolean_T runModel = true;
|
||||||
px4_sem_t stopSem;
|
px4_sem_t stopSem;
|
||||||
px4_sem_t baserateTaskSem;
|
px4_sem_t baserateTaskSem;
|
||||||
|
px4_sem_t subrateTaskSem[1];
|
||||||
|
int taskId[1];
|
||||||
pthread_t schedulerThread;
|
pthread_t schedulerThread;
|
||||||
pthread_t baseRateThread;
|
pthread_t baseRateThread;
|
||||||
void *threadJoinStatus;
|
void *threadJoinStatus;
|
||||||
int terminatingmodel = 0;
|
int terminatingmodel = 0;
|
||||||
|
pthread_t subRateThread[1];
|
||||||
|
int subratePriority[1];
|
||||||
|
void *subrateTask(void *arg)
|
||||||
|
{
|
||||||
|
int tid = *((int *) arg);
|
||||||
|
int subRateId;
|
||||||
|
subRateId = tid + 1;
|
||||||
|
while (runModel) {
|
||||||
|
px4_sem_wait(&subrateTaskSem[tid]);
|
||||||
|
if (terminatingmodel)
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef MW_RTOS_DEBUG
|
||||||
|
|
||||||
|
printf(" -subrate task %d semaphore received\n", subRateId);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_step(subRateId);
|
||||||
|
|
||||||
|
// Get model outputs here
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit((void *)0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void *baseRateTask(void *arg)
|
void *baseRateTask(void *arg)
|
||||||
{
|
{
|
||||||
runModel = (rtmGetErrorStatus(uORB_MODBUS_TCP_M) == (nullptr));
|
runModel = (rtmGetErrorStatus(uORB_MODBUS_TCP_M) == (nullptr));
|
||||||
while (runModel) {
|
while (runModel) {
|
||||||
px4_sem_wait(&baserateTaskSem);
|
px4_sem_wait(&baserateTaskSem);
|
||||||
uORB_MODBUS_TCP_step();
|
|
||||||
|
#ifdef MW_RTOS_DEBUG
|
||||||
|
|
||||||
|
printf("*base rate task semaphore received\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rtmStepTask(uORB_MODBUS_TCP_M, 1)
|
||||||
|
) {
|
||||||
|
px4_sem_post(&subrateTaskSem[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_step(0);
|
||||||
|
|
||||||
// Get model outputs here
|
// Get model outputs here
|
||||||
stopRequested = !((rtmGetErrorStatus(uORB_MODBUS_TCP_M) == (nullptr)));
|
stopRequested = !((rtmGetErrorStatus(uORB_MODBUS_TCP_M) == (nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
runModel = 0;
|
|
||||||
terminateTask(arg);
|
terminateTask(arg);
|
||||||
pthread_exit((void *)0);
|
pthread_exit((void *)0);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -70,6 +111,20 @@ void *terminateTask(void *arg)
|
|||||||
terminatingmodel = 1;
|
terminatingmodel = 1;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Signal all periodic tasks to complete
|
||||||
|
for (i=0; i<1; i++) {
|
||||||
|
CHECK_STATUS(px4_sem_post(&subrateTaskSem[i]), 0, "px4_sem_post");
|
||||||
|
CHECK_STATUS(px4_sem_destroy(&subrateTaskSem[i]), 0, "px4_sem_destroy");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all periodic tasks to complete
|
||||||
|
for (i=0; i<1; i++) {
|
||||||
|
CHECK_STATUS(pthread_join(subRateThread[i], &threadJoinStatus), 0,
|
||||||
|
"pthread_join");
|
||||||
|
}
|
||||||
|
|
||||||
runModel = 0;
|
runModel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +138,7 @@ void *terminateTask(void *arg)
|
|||||||
|
|
||||||
int px4_simulink_app_task_main (int argc, char *argv[])
|
int px4_simulink_app_task_main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
subratePriority[0] = 249;
|
||||||
px4_simulink_app_control_MAVLink();
|
px4_simulink_app_control_MAVLink();
|
||||||
rtmSetErrorStatus(uORB_MODBUS_TCP_M, 0);
|
rtmSetErrorStatus(uORB_MODBUS_TCP_M, 0);
|
||||||
|
|
||||||
@ -90,7 +146,7 @@ int px4_simulink_app_task_main (int argc, char *argv[])
|
|||||||
uORB_MODBUS_TCP_initialize();
|
uORB_MODBUS_TCP_initialize();
|
||||||
|
|
||||||
// Call RTOS Initialization function
|
// Call RTOS Initialization function
|
||||||
nuttxRTOSInit(5.0, 0);
|
nuttxRTOSInit(0.25, 1);
|
||||||
|
|
||||||
// Wait for stop semaphore
|
// Wait for stop semaphore
|
||||||
px4_sem_wait(&stopSem);
|
px4_sem_wait(&stopSem);
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
Simulink Coder project for uORB_MODBUS_TCP using . MATLAB root = /usr/local/MATLAB/R2024a. SimStruct date: 12-Jan-2024 04:16:21
|
Simulink Coder project for uORB_MODBUS_TCP using . MATLAB root = /home/judson/MATLAB. SimStruct date: 12-Jan-2024 04:16:21
|
||||||
This file is generated by Simulink Coder for use by the make utility
|
This file is generated by Simulink Coder for use by the make utility
|
||||||
to determine when to rebuild objects when the name of the current Simulink Coder project changes.
|
to determine when to rebuild objects when the name of the current Simulink Coder project changes.
|
||||||
The rtwinfomat located at: ../slprj/ert/uORB_MODBUS_TCP/tmwinternal/binfo.mat
|
The rtwinfomat located at: ../slprj/ert/uORB_MODBUS_TCP/tmwinternal/binfo.mat
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
|
|||||||
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/SlCache/19700101">
|
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/SlCache/19700101">
|
||||||
<slcache.FileAttributes type="slcache.FileAttributes" uuid="363fac90-3453-454e-bbc2-a7e8306b5f8a">
|
<slcache.FileAttributes type="slcache.FileAttributes" uuid="f9dfac28-b929-4d57-b9c8-0fd474c23e73">
|
||||||
<checksum>DdrRgVnyR6kegWj1mpzaDcyS+Rh4VBoYEPYCL7/LAGEIf+p+iTuTZYWKYUM1yL59ppS4QwFUE2pBT336Wo0z0Q==</checksum>
|
<checksum>5yKZbaLdWAwwyNBmOxcGcB7eucJzsPxwRZ02y1HQ/zqjVzzjpGumt3HlxZz33ZPrLqkO8UQWCZNG+QwONwRlVw==</checksum>
|
||||||
</slcache.FileAttributes>
|
</slcache.FileAttributes>
|
||||||
</MF0>
|
</MF0>
|
||||||
Binary file not shown.
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
@ -17,68 +17,584 @@
|
|||||||
// Validation result: Not run
|
// Validation result: Not run
|
||||||
//
|
//
|
||||||
#include "uORB_MODBUS_TCP.h"
|
#include "uORB_MODBUS_TCP.h"
|
||||||
|
#include "rtwtypes.h"
|
||||||
|
|
||||||
// Block signals (default storage)
|
// Block signals (default storage)
|
||||||
B_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_B;
|
B_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_B;
|
||||||
|
|
||||||
|
// Block states (default storage)
|
||||||
|
DW_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_DW;
|
||||||
|
|
||||||
// Real-time model
|
// Real-time model
|
||||||
RT_MODEL_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_M_{ };
|
RT_MODEL_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_M_{ };
|
||||||
|
|
||||||
RT_MODEL_uORB_MODBUS_TCP_T *const uORB_MODBUS_TCP_M{ &uORB_MODBUS_TCP_M_ };
|
RT_MODEL_uORB_MODBUS_TCP_T *const uORB_MODBUS_TCP_M{ &uORB_MODBUS_TCP_M_ };
|
||||||
|
|
||||||
// Model step function
|
static void rate_monotonic_scheduler(void);
|
||||||
void uORB_MODBUS_TCP_step(void)
|
|
||||||
|
//
|
||||||
|
// Set which subrates need to run this base step (base rate always runs).
|
||||||
|
// This function must be called prior to calling the model step function
|
||||||
|
// in order to remember which rates need to run this base step. The
|
||||||
|
// buffering of events allows for overlapping preemption.
|
||||||
|
//
|
||||||
|
void uORB_MODBUS_TCP_SetEventsForThisBaseStep(boolean_T *eventFlags)
|
||||||
{
|
{
|
||||||
// CFunction: '<Root>/C Function3'
|
// Task runs when its counter is zero, computed via rtmStepTask macro
|
||||||
|
eventFlags[1] = ((boolean_T)rtmStepTask(uORB_MODBUS_TCP_M, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// This function updates active task flag for each subrate
|
||||||
|
// and rate transition flags for tasks that exchange data.
|
||||||
|
// The function assumes rate-monotonic multitasking scheduler.
|
||||||
|
// The function must be called at model base rate so that
|
||||||
|
// the generated code self-manages all its subrates and rate
|
||||||
|
// transition flags.
|
||||||
|
//
|
||||||
|
static void rate_monotonic_scheduler(void)
|
||||||
|
{
|
||||||
|
// Compute which subrates run during the next base time step. Subrates
|
||||||
|
// are an integer multiple of the base rate counter. Therefore, the subtask
|
||||||
|
// counter is reset when it reaches its limit (zero means run).
|
||||||
|
|
||||||
|
(uORB_MODBUS_TCP_M->Timing.TaskCounters.TID[1])++;
|
||||||
|
if ((uORB_MODBUS_TCP_M->Timing.TaskCounters.TID[1]) > 19) {// Sample time: [5.0s, 0.0s]
|
||||||
|
uORB_MODBUS_TCP_M->Timing.TaskCounters.TID[1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Model step function for TID0
|
||||||
|
void uORB_MODBUS_TCP_step0(void) // Sample time: [0.25s, 0.0s]
|
||||||
|
{
|
||||||
|
int32_T i;
|
||||||
|
|
||||||
|
{ // Sample time: [0.25s, 0.0s]
|
||||||
|
rate_monotonic_scheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CFunction: '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
{
|
{
|
||||||
static ModbusTCPClient modbus("192.168.0.249", 5020, 10, 10, 10, 10);
|
// Rename variables following the new convention.
|
||||||
|
const int num_DI_to_read = 10;
|
||||||
|
const int num_IR_to_read = 10;
|
||||||
|
const int num_CO_to_read = 10;
|
||||||
|
const int num_HR_to_read = 10;
|
||||||
|
const int expected_uorb_DI = 128;
|
||||||
|
const int expected_uorb_IR = 128;
|
||||||
|
const int expected_uorb_CO = 128;
|
||||||
|
const int expected_uorb_HR = 128;
|
||||||
|
|
||||||
|
// Create the Modbus client with renamed parameters.
|
||||||
|
static ModbusTCPClient modbus("192.168.0.190",
|
||||||
|
5020,
|
||||||
|
num_CO_to_read,
|
||||||
|
num_DI_to_read,
|
||||||
|
num_IR_to_read,
|
||||||
|
num_HR_to_read);
|
||||||
|
|
||||||
|
// Prepare buffers for holding values before assigning them to the output arrays.
|
||||||
|
bool DI_array_buffer[num_DI_to_read] = { 0 };
|
||||||
|
|
||||||
|
uint16_t IR_array_buffer[num_IR_to_read] = { 0 };
|
||||||
|
|
||||||
|
bool CO_array_buffer[num_CO_to_read] = { 0 };
|
||||||
|
|
||||||
|
uint16_t HR_array_buffer[num_HR_to_read] = { 0 };
|
||||||
|
|
||||||
|
// Connect to the Modbus server if not already connected.
|
||||||
if (!modbus.isConnected()) {
|
if (!modbus.isConnected()) {
|
||||||
modbus.setTimeout(1000);
|
modbus.setTimeout(3000); // Set timeout in milliseconds
|
||||||
if (!modbus.connectServer()) {
|
if (!modbus.connectServer()) {
|
||||||
printf("Failed to connect to MODBUS server!\n");
|
printf("Failed to connect to MODBUS server in!\n");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int num_reads = 1000;
|
if (modbus.readAll() != ModbusError::NONE) {
|
||||||
uint16_t last_value = 0;
|
printf("Error calling modbus.readAll()\n");
|
||||||
uint16_t holdingRegisters[10] = { 0 };
|
|
||||||
|
|
||||||
float sum_differences = 0.0;
|
|
||||||
|
|
||||||
// Initial read to populate last_value
|
|
||||||
modbus.readMultipleHoldingRegisters(0, 10, holdingRegisters);
|
|
||||||
last_value = holdingRegisters[0];
|
|
||||||
|
|
||||||
// Loop 1000 times
|
|
||||||
for (int i = 0; i < num_reads; ++i) {
|
|
||||||
modbus.readMultipleHoldingRegisters(0, 10, holdingRegisters);
|
|
||||||
uint16_t current_value = holdingRegisters[0];
|
|
||||||
|
|
||||||
// Handle 16-bit rollover
|
|
||||||
uint16_t diff = (current_value >= last_value)
|
|
||||||
? (current_value - last_value)
|
|
||||||
: (current_value + (65536 - last_value));
|
|
||||||
sum_differences += (float)diff;
|
|
||||||
last_value = current_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Average the differences
|
// --- Holding Registers (HR) ---
|
||||||
float avg_diff = sum_differences / num_reads;
|
// Read a subset of HR registers into our buffer.
|
||||||
printf("Average time difference between reads (ms): %.2f\n", avg_diff);
|
ModbusError HR_error = modbus.getMultipleHoldingRegisters(0, num_HR_to_read,
|
||||||
|
HR_array_buffer);
|
||||||
|
if (HR_error != ModbusError::NONE) {
|
||||||
|
printf("Failed to read HR registers: error code %d\n", static_cast<int>
|
||||||
|
(HR_error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign HR buffer values to the output array.
|
||||||
|
for (int i = 0; i < expected_uorb_HR; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o4[i] = (i < num_HR_to_read) ?
|
||||||
|
HR_array_buffer[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Input Registers (IR) ---
|
||||||
|
// Read a subset of IR registers into our buffer.
|
||||||
|
ModbusError IR_error = modbus.getMultipleInputRegisters(0, num_IR_to_read,
|
||||||
|
IR_array_buffer);
|
||||||
|
if (IR_error != ModbusError::NONE) {
|
||||||
|
printf("Failed to read IR registers: error code %d\n", static_cast<int>
|
||||||
|
(IR_error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign IR buffer values to the output array.
|
||||||
|
for (int i = 0; i < expected_uorb_IR; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o2[i] = (i < num_IR_to_read) ?
|
||||||
|
IR_array_buffer[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Discrete Inputs (DI) ---
|
||||||
|
// Read a subset of DI registers into our buffer.
|
||||||
|
ModbusError DI_error = modbus.getMultipleDiscreteInputs(0, num_DI_to_read,
|
||||||
|
DI_array_buffer);
|
||||||
|
if (DI_error != ModbusError::NONE) {
|
||||||
|
printf("Failed to read DI registers: error code %d\n", static_cast<int>
|
||||||
|
(DI_error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign DI buffer values to the output array.
|
||||||
|
for (int i = 0; i < expected_uorb_DI; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o1[i] = (i < num_DI_to_read) ?
|
||||||
|
DI_array_buffer[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Coils (CO) ---
|
||||||
|
// Read a subset of CO registers (coils) into our buffer.
|
||||||
|
ModbusError CO_error = modbus.getMultipleCoils(0, num_CO_to_read,
|
||||||
|
CO_array_buffer);
|
||||||
|
if (CO_error != ModbusError::NONE) {
|
||||||
|
printf("Failed to read CO registers: error code %d\n", static_cast<int>
|
||||||
|
(CO_error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign CO buffer values to the output array.
|
||||||
|
for (int i = 0; i < expected_uorb_CO; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o3[i] = (i < num_CO_to_read) ?
|
||||||
|
CO_array_buffer[i] : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment' incorporates:
|
||||||
|
// Constant: '<S1>/Constant'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment = uORB_MODBUS_TCP_P.Constant_Value;
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment' incorporates:
|
||||||
|
// CFunction: '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment.register_array_read[i] =
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o4[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MATLABSystem: '<S9>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment'
|
||||||
|
|
||||||
|
uORB_write_step(uORB_MODBUS_TCP_DW.obj_m.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_m.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment);
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment1' incorporates:
|
||||||
|
// Constant: '<S2>/Constant'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment1 = uORB_MODBUS_TCP_P.Constant_Value_m;
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment1' incorporates:
|
||||||
|
// CFunction: '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment1.coil_array_read[i] =
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o3[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MATLABSystem: '<S10>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment1'
|
||||||
|
|
||||||
|
uORB_write_step(uORB_MODBUS_TCP_DW.obj_g.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_g.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment1);
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment2' incorporates:
|
||||||
|
// Constant: '<S3>/Constant'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment2 = uORB_MODBUS_TCP_P.Constant_Value_f;
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment2' incorporates:
|
||||||
|
// CFunction: '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment2.register_array[i] =
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o2[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MATLABSystem: '<S11>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment2'
|
||||||
|
|
||||||
|
uORB_write_step(uORB_MODBUS_TCP_DW.obj_a.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_a.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment2);
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment3' incorporates:
|
||||||
|
// Constant: '<S4>/Constant'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment3 = uORB_MODBUS_TCP_P.Constant_Value_d;
|
||||||
|
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment3' incorporates:
|
||||||
|
// CFunction: '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
uORB_MODBUS_TCP_B.BusAssignment3.input_array[i] =
|
||||||
|
uORB_MODBUS_TCP_B.PLCMODBUSTCPReadAll_o1[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MATLABSystem: '<S12>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment3'
|
||||||
|
|
||||||
|
uORB_write_step(uORB_MODBUS_TCP_DW.obj_f.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_f.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Model step function for TID1
|
||||||
|
void uORB_MODBUS_TCP_step1(void) // Sample time: [5.0s, 0.0s]
|
||||||
|
{
|
||||||
|
boolean_T b_varargout_1;
|
||||||
|
|
||||||
|
// MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
b_varargout_1 = uORB_read_step(uORB_MODBUS_TCP_DW.obj.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj.eventStructObj, &uORB_MODBUS_TCP_B.r3, false, 1.0);
|
||||||
|
|
||||||
|
// MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o1 = b_varargout_1;
|
||||||
|
|
||||||
|
// MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o2_j = uORB_MODBUS_TCP_B.r3;
|
||||||
|
|
||||||
|
// Outputs for Enabled SubSystem: '<S8>/Enabled Subsystem' incorporates:
|
||||||
|
// EnablePort: '<S16>/Enable'
|
||||||
|
|
||||||
|
if (uORB_MODBUS_TCP_B.SourceBlock_o1) {
|
||||||
|
// SignalConversion generated from: '<S16>/In1' incorporates:
|
||||||
|
// MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1_b = uORB_MODBUS_TCP_B.SourceBlock_o2_j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Outputs for SubSystem: '<S8>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
b_varargout_1 = uORB_read_step(uORB_MODBUS_TCP_DW.obj_e.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_e.eventStructObj, &uORB_MODBUS_TCP_B.r1, false, 1.0);
|
||||||
|
|
||||||
|
// MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o1_g = b_varargout_1;
|
||||||
|
|
||||||
|
// MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o2 = uORB_MODBUS_TCP_B.r1;
|
||||||
|
|
||||||
|
// Outputs for Enabled SubSystem: '<S7>/Enabled Subsystem' incorporates:
|
||||||
|
// EnablePort: '<S15>/Enable'
|
||||||
|
|
||||||
|
if (uORB_MODBUS_TCP_B.SourceBlock_o1_g) {
|
||||||
|
// SignalConversion generated from: '<S15>/In1' incorporates:
|
||||||
|
// MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1 = uORB_MODBUS_TCP_B.SourceBlock_o2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Outputs for SubSystem: '<S7>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
b_varargout_1 = uORB_read_step(uORB_MODBUS_TCP_DW.obj_j.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_j.eventStructObj, &uORB_MODBUS_TCP_B.r2, false, 1.0);
|
||||||
|
|
||||||
|
// MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o1_l = b_varargout_1;
|
||||||
|
|
||||||
|
// MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o2_d = uORB_MODBUS_TCP_B.r2;
|
||||||
|
|
||||||
|
// Outputs for Enabled SubSystem: '<S6>/Enabled Subsystem' incorporates:
|
||||||
|
// EnablePort: '<S14>/Enable'
|
||||||
|
|
||||||
|
if (uORB_MODBUS_TCP_B.SourceBlock_o1_l) {
|
||||||
|
// SignalConversion generated from: '<S14>/In1' incorporates:
|
||||||
|
// MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1_m = uORB_MODBUS_TCP_B.SourceBlock_o2_d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Outputs for SubSystem: '<S6>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// MATLABSystem: '<S5>/SourceBlock'
|
||||||
|
b_varargout_1 = uORB_read_step(uORB_MODBUS_TCP_DW.obj_d.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_d.eventStructObj, &uORB_MODBUS_TCP_B.r, false, 1.0);
|
||||||
|
|
||||||
|
// MATLABSystem: '<S5>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o1_c = b_varargout_1;
|
||||||
|
|
||||||
|
// MATLABSystem: '<S5>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_B.SourceBlock_o2_l = uORB_MODBUS_TCP_B.r;
|
||||||
|
|
||||||
|
// Outputs for Enabled SubSystem: '<S5>/Enabled Subsystem' incorporates:
|
||||||
|
// EnablePort: '<S13>/Enable'
|
||||||
|
|
||||||
|
if (uORB_MODBUS_TCP_B.SourceBlock_o1_c) {
|
||||||
|
// SignalConversion generated from: '<S13>/In1' incorporates:
|
||||||
|
// MATLABSystem: '<S5>/SourceBlock'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1_e = uORB_MODBUS_TCP_B.SourceBlock_o2_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Outputs for SubSystem: '<S5>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// CFunction: '<Root>/Print All PLC Values'
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// Print table header
|
||||||
|
printf("%-5s %-5s %-5s %-5s %-5s\n", "Idx", "CO", "DI", "IR", "HR");
|
||||||
|
|
||||||
|
// Print the first 10 rows
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
// Print index, then CO, DI as 1 (true) or 0 (false), then IR and HR values.
|
||||||
|
printf("%-5d %-5d %-5d %-5u %-5u\n",
|
||||||
|
i,
|
||||||
|
uORB_MODBUS_TCP_B.In1_m.coil_array_read[i] ? 1 : 0,
|
||||||
|
uORB_MODBUS_TCP_B.In1_b.input_array[i] ? 1 : 0,
|
||||||
|
uORB_MODBUS_TCP_B.In1.register_array[i],
|
||||||
|
uORB_MODBUS_TCP_B.In1_e.register_array_read[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this function only if you need to maintain compatibility with an existing static main program.
|
||||||
|
void uORB_MODBUS_TCP_step(int_T tid)
|
||||||
|
{
|
||||||
|
switch (tid) {
|
||||||
|
case 0 :
|
||||||
|
uORB_MODBUS_TCP_step0();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1 :
|
||||||
|
uORB_MODBUS_TCP_step1();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Model initialize function
|
// Model initialize function
|
||||||
void uORB_MODBUS_TCP_initialize(void)
|
void uORB_MODBUS_TCP_initialize(void)
|
||||||
{
|
{
|
||||||
// (no initialization code required)
|
// SystemInitialize for Enabled SubSystem: '<S5>/Enabled Subsystem'
|
||||||
|
// SystemInitialize for SignalConversion generated from: '<S13>/In1' incorporates:
|
||||||
|
// Outport: '<S13>/Out1'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1_e = uORB_MODBUS_TCP_P.Out1_Y0;
|
||||||
|
|
||||||
|
// End of SystemInitialize for SubSystem: '<S5>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// SystemInitialize for Enabled SubSystem: '<S6>/Enabled Subsystem'
|
||||||
|
// SystemInitialize for SignalConversion generated from: '<S14>/In1' incorporates:
|
||||||
|
// Outport: '<S14>/Out1'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1_m = uORB_MODBUS_TCP_P.Out1_Y0_g;
|
||||||
|
|
||||||
|
// End of SystemInitialize for SubSystem: '<S6>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// SystemInitialize for Enabled SubSystem: '<S7>/Enabled Subsystem'
|
||||||
|
// SystemInitialize for SignalConversion generated from: '<S15>/In1' incorporates:
|
||||||
|
// Outport: '<S15>/Out1'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1 = uORB_MODBUS_TCP_P.Out1_Y0_h;
|
||||||
|
|
||||||
|
// End of SystemInitialize for SubSystem: '<S7>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// SystemInitialize for Enabled SubSystem: '<S8>/Enabled Subsystem'
|
||||||
|
// SystemInitialize for SignalConversion generated from: '<S16>/In1' incorporates:
|
||||||
|
// Outport: '<S16>/Out1'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_B.In1_b = uORB_MODBUS_TCP_P.Out1_Y0_l;
|
||||||
|
|
||||||
|
// End of SystemInitialize for SubSystem: '<S8>/Enabled Subsystem'
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S9>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_DW.obj_m.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_nn = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_m.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_m.orbMetadataObj = ORB_ID(plc_holding_registers_read);
|
||||||
|
uORB_write_initialize(uORB_MODBUS_TCP_DW.obj_m.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_m.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment, 1);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_m.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S10>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment1'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_DW.obj_g.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_i = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_g.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_g.orbMetadataObj = ORB_ID(plc_coils_read);
|
||||||
|
uORB_write_initialize(uORB_MODBUS_TCP_DW.obj_g.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_g.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment1, 1);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_g.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S11>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment2'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_DW.obj_a.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_n = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_a.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_a.orbMetadataObj = ORB_ID(plc_input_registers);
|
||||||
|
uORB_write_initialize(uORB_MODBUS_TCP_DW.obj_a.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_a.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment2, 1);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_a.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S12>/SinkBlock' incorporates:
|
||||||
|
// BusAssignment: '<Root>/Bus Assignment3'
|
||||||
|
|
||||||
|
uORB_MODBUS_TCP_DW.obj_f.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_f.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_f.orbMetadataObj = ORB_ID(plc_discrete_inputs);
|
||||||
|
uORB_write_initialize(uORB_MODBUS_TCP_DW.obj_f.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_f.orbAdvertiseObj,
|
||||||
|
&uORB_MODBUS_TCP_B.BusAssignment3, 1);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_f.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_DW.obj.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_e = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj.orbMetadataObj = ORB_ID(plc_discrete_inputs);
|
||||||
|
uORB_read_initialize(uORB_MODBUS_TCP_DW.obj.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj.eventStructObj);
|
||||||
|
uORB_MODBUS_TCP_DW.obj.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_DW.obj_e.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_b = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_e.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_e.orbMetadataObj = ORB_ID(plc_input_registers);
|
||||||
|
uORB_read_initialize(uORB_MODBUS_TCP_DW.obj_e.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_e.eventStructObj);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_e.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_DW.obj_j.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_bt = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_j.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_j.orbMetadataObj = ORB_ID(plc_coils_read);
|
||||||
|
uORB_read_initialize(uORB_MODBUS_TCP_DW.obj_j.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_j.eventStructObj);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_j.isSetupComplete = true;
|
||||||
|
|
||||||
|
// Start for MATLABSystem: '<S5>/SourceBlock'
|
||||||
|
uORB_MODBUS_TCP_DW.obj_d.matlabCodegenIsDeleted = false;
|
||||||
|
uORB_MODBUS_TCP_DW.objisempty_a = true;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_d.isInitialized = 1;
|
||||||
|
uORB_MODBUS_TCP_DW.obj_d.orbMetadataObj = ORB_ID(plc_holding_registers_read);
|
||||||
|
uORB_read_initialize(uORB_MODBUS_TCP_DW.obj_d.orbMetadataObj,
|
||||||
|
&uORB_MODBUS_TCP_DW.obj_d.eventStructObj);
|
||||||
|
uORB_MODBUS_TCP_DW.obj_d.isSetupComplete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Model terminate function
|
// Model terminate function
|
||||||
void uORB_MODBUS_TCP_terminate(void)
|
void uORB_MODBUS_TCP_terminate(void)
|
||||||
{
|
{
|
||||||
// (no terminate code required)
|
// Terminate for MATLABSystem: '<S9>/SinkBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_m.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_m.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_m.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_m.isSetupComplete) {
|
||||||
|
uORB_write_terminate(&uORB_MODBUS_TCP_DW.obj_m.orbAdvertiseObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S9>/SinkBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S10>/SinkBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_g.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_g.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_g.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_g.isSetupComplete) {
|
||||||
|
uORB_write_terminate(&uORB_MODBUS_TCP_DW.obj_g.orbAdvertiseObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S10>/SinkBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S11>/SinkBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_a.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_a.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_a.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_a.isSetupComplete) {
|
||||||
|
uORB_write_terminate(&uORB_MODBUS_TCP_DW.obj_a.orbAdvertiseObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S11>/SinkBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S12>/SinkBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_f.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_f.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_f.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_f.isSetupComplete) {
|
||||||
|
uORB_write_terminate(&uORB_MODBUS_TCP_DW.obj_f.orbAdvertiseObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S12>/SinkBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj.isSetupComplete) {
|
||||||
|
uORB_read_terminate(&uORB_MODBUS_TCP_DW.obj.eventStructObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S8>/SourceBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_e.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_e.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_e.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_e.isSetupComplete) {
|
||||||
|
uORB_read_terminate(&uORB_MODBUS_TCP_DW.obj_e.eventStructObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S7>/SourceBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_j.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_j.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_j.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_j.isSetupComplete) {
|
||||||
|
uORB_read_terminate(&uORB_MODBUS_TCP_DW.obj_j.eventStructObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S6>/SourceBlock'
|
||||||
|
|
||||||
|
// Terminate for MATLABSystem: '<S5>/SourceBlock'
|
||||||
|
if (!uORB_MODBUS_TCP_DW.obj_d.matlabCodegenIsDeleted) {
|
||||||
|
uORB_MODBUS_TCP_DW.obj_d.matlabCodegenIsDeleted = true;
|
||||||
|
if ((uORB_MODBUS_TCP_DW.obj_d.isInitialized == 1) &&
|
||||||
|
uORB_MODBUS_TCP_DW.obj_d.isSetupComplete) {
|
||||||
|
uORB_read_terminate(&uORB_MODBUS_TCP_DW.obj_d.eventStructObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of Terminate for MATLABSystem: '<S5>/SourceBlock'
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
@ -18,8 +18,16 @@
|
|||||||
//
|
//
|
||||||
#ifndef uORB_MODBUS_TCP_h_
|
#ifndef uORB_MODBUS_TCP_h_
|
||||||
#define uORB_MODBUS_TCP_h_
|
#define uORB_MODBUS_TCP_h_
|
||||||
|
#include <poll.h>
|
||||||
|
#include <uORB/uORB.h>
|
||||||
#include "rtwtypes.h"
|
#include "rtwtypes.h"
|
||||||
|
#include "MW_uORB_Read.h"
|
||||||
|
#include "MW_uORB_Write.h"
|
||||||
#include "uORB_MODBUS_TCP_types.h"
|
#include "uORB_MODBUS_TCP_types.h"
|
||||||
|
#include <uORB/topics/plc_holding_registers_read.h>
|
||||||
|
#include <uORB/topics/plc_input_registers.h>
|
||||||
|
#include <uORB/topics/plc_coils_read.h>
|
||||||
|
#include <uORB/topics/plc_discrete_inputs.h>
|
||||||
#include "modbus_tcp_client.h"
|
#include "modbus_tcp_client.h"
|
||||||
|
|
||||||
// Macros for accessing real-time model data structure
|
// Macros for accessing real-time model data structure
|
||||||
@ -31,6 +39,14 @@
|
|||||||
#define rtmSetErrorStatus(rtm, val) ((rtm)->errorStatus = (val))
|
#define rtmSetErrorStatus(rtm, val) ((rtm)->errorStatus = (val))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef rtmStepTask
|
||||||
|
#define rtmStepTask(rtm, idx) ((rtm)->Timing.TaskCounters.TID[(idx)] == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef rtmTaskCounter
|
||||||
|
#define rtmTaskCounter(rtm, idx) ((rtm)->Timing.TaskCounters.TID[(idx)])
|
||||||
|
#endif
|
||||||
|
|
||||||
// user code (top of header file)
|
// user code (top of header file)
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -40,18 +56,127 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "modbus_tcp_client.h"
|
|
||||||
|
|
||||||
// Block signals (default storage)
|
// Block signals (default storage)
|
||||||
struct B_uORB_MODBUS_TCP_T {
|
struct B_uORB_MODBUS_TCP_T {
|
||||||
real32_T CFunction3; // '<Root>/C Function3'
|
px4_Bus_plc_holding_registers_read BusAssignment;// '<Root>/Bus Assignment'
|
||||||
|
px4_Bus_plc_holding_registers_read SourceBlock_o2_l;// '<S5>/SourceBlock'
|
||||||
|
px4_Bus_plc_holding_registers_read In1_e;// '<S13>/In1'
|
||||||
|
px4_Bus_plc_holding_registers_read r;
|
||||||
|
px4_Bus_plc_input_registers BusAssignment2;// '<Root>/Bus Assignment2'
|
||||||
|
px4_Bus_plc_input_registers SourceBlock_o2;// '<S7>/SourceBlock'
|
||||||
|
px4_Bus_plc_input_registers In1; // '<S15>/In1'
|
||||||
|
px4_Bus_plc_input_registers r1;
|
||||||
|
px4_Bus_plc_coils_read BusAssignment1;// '<Root>/Bus Assignment1'
|
||||||
|
px4_Bus_plc_coils_read SourceBlock_o2_d;// '<S6>/SourceBlock'
|
||||||
|
px4_Bus_plc_coils_read In1_m; // '<S14>/In1'
|
||||||
|
uint16_T PLCMODBUSTCPReadAll_o2[128];// '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
uint16_T PLCMODBUSTCPReadAll_o4[128];// '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
px4_Bus_plc_coils_read r2;
|
||||||
|
px4_Bus_plc_discrete_inputs BusAssignment3;// '<Root>/Bus Assignment3'
|
||||||
|
px4_Bus_plc_discrete_inputs SourceBlock_o2_j;// '<S8>/SourceBlock'
|
||||||
|
px4_Bus_plc_discrete_inputs In1_b; // '<S16>/In1'
|
||||||
|
px4_Bus_plc_discrete_inputs r3;
|
||||||
|
boolean_T PLCMODBUSTCPReadAll_o1[128];// '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
boolean_T PLCMODBUSTCPReadAll_o3[128];// '<Root>/PLC MODBUS TCP ReadAll'
|
||||||
|
boolean_T SourceBlock_o1; // '<S8>/SourceBlock'
|
||||||
|
boolean_T SourceBlock_o1_g; // '<S7>/SourceBlock'
|
||||||
|
boolean_T SourceBlock_o1_l; // '<S6>/SourceBlock'
|
||||||
|
boolean_T SourceBlock_o1_c; // '<S5>/SourceBlock'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Block states (default storage) for system '<Root>'
|
||||||
|
struct DW_uORB_MODBUS_TCP_T {
|
||||||
|
px4_internal_block_Subscriber_T obj; // '<S8>/SourceBlock'
|
||||||
|
px4_internal_block_Subscriber_T obj_e;// '<S7>/SourceBlock'
|
||||||
|
px4_internal_block_Subscriber_T obj_j;// '<S6>/SourceBlock'
|
||||||
|
px4_internal_block_Subscriber_T obj_d;// '<S5>/SourceBlock'
|
||||||
|
px4_internal_block_Publisher__T obj_f;// '<S12>/SinkBlock'
|
||||||
|
px4_internal_block_Publisher__T obj_a;// '<S11>/SinkBlock'
|
||||||
|
px4_internal_block_Publisher__T obj_g;// '<S10>/SinkBlock'
|
||||||
|
px4_internal_block_Publisher__T obj_m;// '<S9>/SinkBlock'
|
||||||
|
boolean_T objisempty; // '<S12>/SinkBlock'
|
||||||
|
boolean_T objisempty_n; // '<S11>/SinkBlock'
|
||||||
|
boolean_T objisempty_i; // '<S10>/SinkBlock'
|
||||||
|
boolean_T objisempty_nn; // '<S9>/SinkBlock'
|
||||||
|
boolean_T objisempty_e; // '<S8>/SourceBlock'
|
||||||
|
boolean_T objisempty_b; // '<S7>/SourceBlock'
|
||||||
|
boolean_T objisempty_bt; // '<S6>/SourceBlock'
|
||||||
|
boolean_T objisempty_a; // '<S5>/SourceBlock'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameters (default storage)
|
||||||
|
struct P_uORB_MODBUS_TCP_T_ {
|
||||||
|
px4_Bus_plc_holding_registers_read Out1_Y0;// Computed Parameter: Out1_Y0
|
||||||
|
// Referenced by: '<S13>/Out1'
|
||||||
|
|
||||||
|
px4_Bus_plc_holding_registers_read Constant_Value;// Computed Parameter: Constant_Value
|
||||||
|
// Referenced by: '<S1>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_holding_registers_read Constant_Value_o;// Computed Parameter: Constant_Value_o
|
||||||
|
// Referenced by: '<S5>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_input_registers Out1_Y0_h;// Computed Parameter: Out1_Y0_h
|
||||||
|
// Referenced by: '<S15>/Out1'
|
||||||
|
|
||||||
|
px4_Bus_plc_input_registers Constant_Value_f;// Computed Parameter: Constant_Value_f
|
||||||
|
// Referenced by: '<S3>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_input_registers Constant_Value_om;// Computed Parameter: Constant_Value_om
|
||||||
|
// Referenced by: '<S7>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_coils_read Out1_Y0_g; // Computed Parameter: Out1_Y0_g
|
||||||
|
// Referenced by: '<S14>/Out1'
|
||||||
|
|
||||||
|
px4_Bus_plc_coils_read Constant_Value_m;// Computed Parameter: Constant_Value_m
|
||||||
|
// Referenced by: '<S2>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_coils_read Constant_Value_k;// Computed Parameter: Constant_Value_k
|
||||||
|
// Referenced by: '<S6>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_discrete_inputs Out1_Y0_l;// Computed Parameter: Out1_Y0_l
|
||||||
|
// Referenced by: '<S16>/Out1'
|
||||||
|
|
||||||
|
px4_Bus_plc_discrete_inputs Constant_Value_d;// Computed Parameter: Constant_Value_d
|
||||||
|
// Referenced by: '<S4>/Constant'
|
||||||
|
|
||||||
|
px4_Bus_plc_discrete_inputs Constant_Value_mf;// Computed Parameter: Constant_Value_mf
|
||||||
|
// Referenced by: '<S8>/Constant'
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Real-time Model Data Structure
|
// Real-time Model Data Structure
|
||||||
struct tag_RTM_uORB_MODBUS_TCP_T {
|
struct tag_RTM_uORB_MODBUS_TCP_T {
|
||||||
const char_T * volatile errorStatus;
|
const char_T * volatile errorStatus;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Timing:
|
||||||
|
// The following substructure contains information regarding
|
||||||
|
// the timing information for the model.
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
uint8_T TID[2];
|
||||||
|
} TaskCounters;
|
||||||
|
} Timing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Block parameters (default storage)
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern P_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_P;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// Block signals (default storage)
|
// Block signals (default storage)
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
@ -68,6 +193,25 @@ extern "C"
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Block states (default storage)
|
||||||
|
extern struct DW_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_DW;
|
||||||
|
|
||||||
|
// External function called from main
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void uORB_MODBUS_TCP_SetEventsForThisBaseStep(boolean_T *eventFlags);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -77,7 +221,9 @@ extern "C"
|
|||||||
|
|
||||||
// Model entry point functions
|
// Model entry point functions
|
||||||
extern void uORB_MODBUS_TCP_initialize(void);
|
extern void uORB_MODBUS_TCP_initialize(void);
|
||||||
extern void uORB_MODBUS_TCP_step(void);
|
extern void uORB_MODBUS_TCP_step0(void);
|
||||||
|
extern void uORB_MODBUS_TCP_step1(void);
|
||||||
|
extern void uORB_MODBUS_TCP_step(int_T tid);
|
||||||
extern void uORB_MODBUS_TCP_terminate(void);
|
extern void uORB_MODBUS_TCP_terminate(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -120,6 +266,22 @@ extern volatile boolean_T runModel;
|
|||||||
// Here is the system hierarchy for this model
|
// Here is the system hierarchy for this model
|
||||||
//
|
//
|
||||||
// '<Root>' : 'uORB_MODBUS_TCP'
|
// '<Root>' : 'uORB_MODBUS_TCP'
|
||||||
|
// '<S1>' : 'uORB_MODBUS_TCP/PX4 uORB Message'
|
||||||
|
// '<S2>' : 'uORB_MODBUS_TCP/PX4 uORB Message1'
|
||||||
|
// '<S3>' : 'uORB_MODBUS_TCP/PX4 uORB Message2'
|
||||||
|
// '<S4>' : 'uORB_MODBUS_TCP/PX4 uORB Message3'
|
||||||
|
// '<S5>' : 'uORB_MODBUS_TCP/PX4 uORB Read'
|
||||||
|
// '<S6>' : 'uORB_MODBUS_TCP/PX4 uORB Read1'
|
||||||
|
// '<S7>' : 'uORB_MODBUS_TCP/PX4 uORB Read2'
|
||||||
|
// '<S8>' : 'uORB_MODBUS_TCP/PX4 uORB Read3'
|
||||||
|
// '<S9>' : 'uORB_MODBUS_TCP/PX4 uORB Write1'
|
||||||
|
// '<S10>' : 'uORB_MODBUS_TCP/PX4 uORB Write2'
|
||||||
|
// '<S11>' : 'uORB_MODBUS_TCP/PX4 uORB Write3'
|
||||||
|
// '<S12>' : 'uORB_MODBUS_TCP/PX4 uORB Write4'
|
||||||
|
// '<S13>' : 'uORB_MODBUS_TCP/PX4 uORB Read/Enabled Subsystem'
|
||||||
|
// '<S14>' : 'uORB_MODBUS_TCP/PX4 uORB Read1/Enabled Subsystem'
|
||||||
|
// '<S15>' : 'uORB_MODBUS_TCP/PX4 uORB Read2/Enabled Subsystem'
|
||||||
|
// '<S16>' : 'uORB_MODBUS_TCP/PX4 uORB Read3/Enabled Subsystem'
|
||||||
|
|
||||||
|
|
||||||
//-
|
//-
|
||||||
|
|||||||
@ -0,0 +1,268 @@
|
|||||||
|
//
|
||||||
|
// Academic License - for use in teaching, academic research, and meeting
|
||||||
|
// course requirements at degree granting institutions only. Not for
|
||||||
|
// government, commercial, or other organizational use.
|
||||||
|
//
|
||||||
|
// File: uORB_MODBUS_TCP_data.cpp
|
||||||
|
//
|
||||||
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
|
//
|
||||||
|
// Model version : 1.22
|
||||||
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
|
//
|
||||||
|
// Target selection: ert.tlc
|
||||||
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
|
// Code generation objectives: Unspecified
|
||||||
|
// Validation result: Not run
|
||||||
|
//
|
||||||
|
#include "uORB_MODBUS_TCP.h"
|
||||||
|
|
||||||
|
// Block parameters (default storage)
|
||||||
|
P_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_P{
|
||||||
|
// Computed Parameter: Out1_Y0
|
||||||
|
// Referenced by: '<S13>/Out1'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||||
|
// register_array_read
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value
|
||||||
|
// Referenced by: '<S1>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||||
|
// register_array_read
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_o
|
||||||
|
// Referenced by: '<S5>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||||
|
// register_array_read
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Out1_Y0_h
|
||||||
|
// Referenced by: '<S15>/Out1'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||||
|
// register_array
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_f
|
||||||
|
// Referenced by: '<S3>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||||
|
// register_array
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_om
|
||||||
|
// Referenced by: '<S7>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||||
|
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||||
|
// register_array
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Out1_Y0_g
|
||||||
|
// Referenced by: '<S14>/Out1'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false }
|
||||||
|
// coil_array_read
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_m
|
||||||
|
// Referenced by: '<S2>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false }
|
||||||
|
// coil_array_read
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_k
|
||||||
|
// Referenced by: '<S6>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false }
|
||||||
|
// coil_array_read
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Out1_Y0_l
|
||||||
|
// Referenced by: '<S16>/Out1'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false }
|
||||||
|
// input_array
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_d
|
||||||
|
// Referenced by: '<S4>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false }
|
||||||
|
// input_array
|
||||||
|
},
|
||||||
|
|
||||||
|
// Computed Parameter: Constant_Value_mf
|
||||||
|
// Referenced by: '<S8>/Constant'
|
||||||
|
|
||||||
|
{
|
||||||
|
(0ULL), // timestamp
|
||||||
|
|
||||||
|
{
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
false, false, false, false, false, false, false, false }
|
||||||
|
// input_array
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// File trailer for generated code.
|
||||||
|
//
|
||||||
|
// [EOF]
|
||||||
|
//
|
||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||||
//
|
//
|
||||||
// Model version : 1.16
|
// Model version : 1.22
|
||||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||||
// C/C++ source code generated on : Sat Mar 22 17:15:30 2025
|
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||||
//
|
//
|
||||||
// Target selection: ert.tlc
|
// Target selection: ert.tlc
|
||||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||||
@ -18,6 +18,52 @@
|
|||||||
//
|
//
|
||||||
#ifndef uORB_MODBUS_TCP_types_h_
|
#ifndef uORB_MODBUS_TCP_types_h_
|
||||||
#define uORB_MODBUS_TCP_types_h_
|
#define uORB_MODBUS_TCP_types_h_
|
||||||
|
#include "rtwtypes.h"
|
||||||
|
#include <uORB/topics/plc_holding_registers_read.h>
|
||||||
|
#include <uORB/topics/plc_coils_read.h>
|
||||||
|
#include <uORB/topics/plc_input_registers.h>
|
||||||
|
#include <uORB/topics/plc_discrete_inputs.h>
|
||||||
|
#ifndef struct_e_px4_internal_block_SampleTi_T
|
||||||
|
#define struct_e_px4_internal_block_SampleTi_T
|
||||||
|
|
||||||
|
struct e_px4_internal_block_SampleTi_T
|
||||||
|
{
|
||||||
|
int32_T __dummy;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // struct_e_px4_internal_block_SampleTi_T
|
||||||
|
|
||||||
|
#ifndef struct_px4_internal_block_Subscriber_T
|
||||||
|
#define struct_px4_internal_block_Subscriber_T
|
||||||
|
|
||||||
|
struct px4_internal_block_Subscriber_T
|
||||||
|
{
|
||||||
|
boolean_T matlabCodegenIsDeleted;
|
||||||
|
int32_T isInitialized;
|
||||||
|
boolean_T isSetupComplete;
|
||||||
|
e_px4_internal_block_SampleTi_T SampleTimeHandler;
|
||||||
|
pollfd_t eventStructObj;
|
||||||
|
orb_metadata_t * orbMetadataObj;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // struct_px4_internal_block_Subscriber_T
|
||||||
|
|
||||||
|
#ifndef struct_px4_internal_block_Publisher__T
|
||||||
|
#define struct_px4_internal_block_Publisher__T
|
||||||
|
|
||||||
|
struct px4_internal_block_Publisher__T
|
||||||
|
{
|
||||||
|
boolean_T matlabCodegenIsDeleted;
|
||||||
|
int32_T isInitialized;
|
||||||
|
boolean_T isSetupComplete;
|
||||||
|
orb_advert_t orbAdvertiseObj;
|
||||||
|
orb_metadata_t * orbMetadataObj;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // struct_px4_internal_block_Publisher__T
|
||||||
|
|
||||||
|
// Parameters (default storage)
|
||||||
|
typedef struct P_uORB_MODBUS_TCP_T_ P_uORB_MODBUS_TCP_T;
|
||||||
|
|
||||||
// Forward declaration for rtModel
|
// Forward declaration for rtModel
|
||||||
typedef struct tag_RTM_uORB_MODBUS_TCP_T RT_MODEL_uORB_MODBUS_TCP_T;
|
typedef struct tag_RTM_uORB_MODBUS_TCP_T RT_MODEL_uORB_MODBUS_TCP_T;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user