Updated simulink models and modbus_tcp code to most recent version

This commit is contained in:
judsonupchurch 2025-06-14 14:53:24 -05:00
parent c3e0677ce4
commit e82bbf20de
44 changed files with 7325 additions and 1101 deletions

View File

@ -1,5 +1,4 @@
#include "modbus_tcp_client.h"
#include <sys/select.h>
// --- Helper: Compute maximum read response size based on configured counts.
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) {
// Allocate internal storage for automatic readAll()/writeAll() mode.
coilsRead = new bool[numCoils]();
coilsWrite = new bool[numCoils]();
discreteInputs = new bool[numDI]();
inputRegisters = new uint16_t[numIR]();
holdingRegistersRead = new uint16_t[numHR]();
holdingRegistersWrite = new uint16_t[numHR]();
coilsRead = (numCoils > 0) ? new bool[numCoils]() : nullptr;
coilsWrite = (numCoils > 0) ? new bool[numCoils]() : nullptr;
discreteInputs = (numDI > 0) ? new bool[numDI]() : nullptr;
inputRegisters = (numIR > 0) ? new uint16_t[numIR]() : nullptr;
holdingRegistersRead = (numHR > 0) ? new uint16_t[numHR]() : nullptr;
holdingRegistersWrite = (numHR > 0) ? new uint16_t[numHR]() : nullptr;
// Allocate shared communication buffers.
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];
commResponseBuffer = new uint8_t[commResponseBufferSize];
// Initialize the socket mutex.
pthread_mutex_init(&socketMutex, NULL);
// Initialize the socket mutex with a recursive attribute.
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)
@ -66,8 +70,12 @@ ModbusTCPClient::ModbusTCPClient(const char* ip, int port)
commRequestBuffer = new uint8_t[commRequestBufferSize];
commResponseBuffer = new uint8_t[commResponseBufferSize];
// Initialize the socket mutex.
pthread_mutex_init(&socketMutex, NULL);
// Initialize the socket mutex with a recursive attribute.
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() {
@ -93,46 +101,134 @@ void ModbusTCPClient::setStartAddresses(int startCoils, int startDI, int startIR
}
// --- 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() {
pthread_mutex_lock(&socketMutex);
// If already connected, return true.
if (socketFD != -1) {
pthread_mutex_unlock(&socketMutex);
return true;
}
for (int attempts = 0; attempts < 5; attempts++) {
// Create a new socket.
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;
}
// 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;
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) {
int res = connect(socketFD, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (res < 0) {
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);
pthread_mutex_unlock(&socketMutex);
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;
}
// If connection failed, disconnect and wait before retrying.
printf("MODBUS_TCP_CLIENT: Connection failed, retrying...\n");
pthread_mutex_unlock(&socketMutex);
disconnectServer();
usleep(100000);
usleep(timeoutMilliseconds * 1000);
}
pthread_mutex_unlock(&socketMutex);
return false;
}
void ModbusTCPClient::disconnectServer() {
pthread_mutex_lock(&socketMutex);
////pthread_mutex_lock(&socketMutex);
if (socketFD != -1) {
shutdown(socketFD, SHUT_RDWR);
close(socketFD);
socketFD = -1;
printf("MODBUS_TCP_CLIENT: Disconnected from server\n");
}
pthread_mutex_unlock(&socketMutex);
//thread_mutex_unlock(&socketMutex);
}
bool ModbusTCPClient::isConnected() const {
@ -150,7 +246,7 @@ void ModbusTCPClient::setTimeout(int milliseconds) {
}
bool ModbusTCPClient::sendRequest(uint8_t* request, int requestSize) {
if (socketFD == -1) {
if (!isConnected()) {
printf("MODBUS_TCP_CLIENT: Not connected. Cannot send request.\n");
return false;
}
@ -182,6 +278,11 @@ bool ModbusTCPClient::receiveResponse(uint8_t* response, int expectedSize) {
disconnectServer();
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);
if (bytesReceived <= 0) {
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 ---
ModbusError ModbusTCPClient::readCoil(int address, bool &coilState) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_COIL, address, 1);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Expect 10 bytes: header (9 bytes) + 1 byte data
int expectedSize = 9 + 1;
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Handle MODBUS exception responses (0x80 + function code)
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
// Ensure the function code in the response matches the request.
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// Set the internal coil state from the response
coilState = (commResponseBuffer[9] & 0x01) != 0;
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
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");
return ModbusError::INVALID_RESPONSE;
}
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_COIL, address, count);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Expected response size: fixed header (9 bytes) + variable byte count.
int byteCount = (count + 7) / 8; // 1 byte per 8 coils
int expectedSize = 9 + byteCount;
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Handle MODBUS exception responses (0x80 + function code)
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
// Ensure the function code in the response matches the request.
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// 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;
coilStates[i] = (commResponseBuffer[byteIndex] >> bitIndex) & 0x01;
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::readDiscreteInput(int address, bool &discreteInput) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
// Build a request for one discrete input (quantity = 1)
buildReadRequest(commRequestBuffer, ModbusFunction::READ_DISCRETE_INPUT, address, 1);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Expect 10 bytes: header (9 bytes) + 1 byte data
int expectedSize = 9 + 1;
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Check for MODBUS exception response
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
// Validate function code
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// Extract the discrete input state (first bit of the data byte at index 9)
discreteInput = (commResponseBuffer[9] & 0x01) != 0;
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
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");
return ModbusError::INVALID_RESPONSE;
}
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_DISCRETE_INPUT, address, count);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Expected response: 9-byte header + ceil(count/8) bytes of data
int byteCount = (count + 7) / 8;
int expectedSize = 9 + byteCount;
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// 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;
discreteInputsArray[i] = (commResponseBuffer[byteIndex] >> bitIndex) & 0x01;
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::readHoldingRegister(int address, uint16_t &holdingRegister) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_HOLDING_REGISTER, address, 1);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// For one register, expect 9-byte header + 2 bytes data = 11 bytes total
int expectedSize = 9 + 2;
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// Extract the register value (big-endian: data at indices 9 and 10)
holdingRegister = (commResponseBuffer[9] << 8) | commResponseBuffer[10];
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
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");
return ModbusError::INVALID_RESPONSE;
}
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_HOLDING_REGISTER, address, count);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// For multiple registers: expected size = 9 + (count * 2)
int expectedSize = 9 + (count * 2);
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// Extract each register value (each register is 2 bytes, big-endian)
for (int i = 0; i < count; i++) {
holdingRegistersArray[i] = (commResponseBuffer[9 + (i * 2)] << 8) | commResponseBuffer[10 + (i * 2)];
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::readInputRegister(int address, uint16_t &inputRegister) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_INPUT_REGISTER, address, 1);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// For one input register: expected size = 9 + 2 = 11 bytes
int expectedSize = 9 + 2;
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
inputRegister = (commResponseBuffer[9] << 8) | commResponseBuffer[10];
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
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");
return ModbusError::INVALID_RESPONSE;
}
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
buildReadRequest(commRequestBuffer, ModbusFunction::READ_INPUT_REGISTER, address, count);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// For multiple registers: expected size = 9 + (count * 2)
int expectedSize = 9 + (count * 2);
if (!receiveResponse(commResponseBuffer, expectedSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
if (commResponseBuffer[7] & 0x80) {
printf("MODBUS_TCP_CLIENT: Exception Code %02X\n", commResponseBuffer[8]);
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::EXCEPTION_RESPONSE;
}
if (commResponseBuffer[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
// Extract each register value (each register is 2 bytes, big-endian)
for (int i = 0; i < count; i++) {
inputRegistersArray[i] = (commResponseBuffer[9 + (i * 2)] << 8) | commResponseBuffer[10 + (i * 2)];
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
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);
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
if (!receiveResponse(commResponseBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
for (int i = 0; i < 12; i++) {
if (commRequestBuffer[i] != commResponseBuffer[i]) {
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::INVALID_RESPONSE;
}
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bool values[]) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
if (count < 1 || count > 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;
}
@ -572,14 +673,14 @@ ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bo
buildWriteMultipleRequest(commRequestBuffer, ModbusFunction::WRITE_MULTIPLE_COILS, address, count, coilData, byteCount);
// Send the request.
if (!sendRequest(commRequestBuffer, requestSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// The expected response size for a write multiple coils request is always 12 bytes.
int expectedResponseSize = 12;
if (!receiveResponse(commResponseBuffer, expectedResponseSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
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 (commRequestBuffer[i] != commResponseBuffer[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;
}
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::writeHoldingRegister(int address, uint16_t value) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
// Build the write single holding register request.
buildWriteSingleRequest(commRequestBuffer, ModbusFunction::WRITE_SINGLE_HOLDING_REGISTER, address, value);
// Send the 12-byte request.
if (!sendRequest(commRequestBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Expect a full 12-byte echo response.
if (!receiveResponse(commResponseBuffer, 12)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// Validate that the entire 12-byte response matches the request.
for (int i = 0; i < 12; i++) {
if (commRequestBuffer[i] != commResponseBuffer[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;
}
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]) {
pthread_mutex_lock(&socketMutex);
//pthread_mutex_lock(&socketMutex);
if (count < 1 || count > 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;
}
// 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);
// Send the request.
if (!sendRequest(commRequestBuffer, requestSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// The expected response size for a write multiple holding registers request is 12 bytes.
int expectedResponseSize = 12;
if (!receiveResponse(commResponseBuffer, expectedResponseSize)) {
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::TIMEOUT;
}
// 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 (commRequestBuffer[i] != commResponseBuffer[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;
}
}
pthread_mutex_unlock(&socketMutex);
//pthread_mutex_unlock(&socketMutex);
return ModbusError::NONE;
}
ModbusError ModbusTCPClient::readAll() {
// 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;
if (coilsRead) {
error = readMultipleCoils(startCoils, numCoils, coilsRead);
@ -688,6 +797,13 @@ ModbusError ModbusTCPClient::readAll() {
}
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;
if (coilsWrite) {
error = writeMultipleCoils(startCoils, numCoils, coilsWrite);
@ -736,3 +852,79 @@ uint16_t ModbusTCPClient::getDesiredHoldingRegister(int address) const {
uint16_t ModbusTCPClient::getInputRegister(int address) const {
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;
}

View File

@ -4,8 +4,10 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <pthread.h> // Use mutexes
// Enum class for MODBUS function codes
@ -54,12 +56,18 @@ public:
// Getters and setters for data values (if using the automatic mode).
void setCoil(int address, bool value);
void setHoldingRegister(int address, uint16_t value);
bool getDiscreteInput(int address) const;
bool getCoil(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 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.
ModbusError readAll();

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -1,13 +1,13 @@
<?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">
<ModelRefInfoRepo.ModelRefInfoRoot type="ModelRefInfoRepo.ModelRefInfoRoot" uuid="8f646527-148b-4f42-bdcf-1b903ac56342">
<childModelRefInfo type="ModelRefInfoRepo.ChildModelRefInfo" uuid="7c651a86-5026-4c5e-9cb7-acebb2c56869">
<ModelRefInfoRepo.ModelRefInfoRoot type="ModelRefInfoRepo.ModelRefInfoRoot" uuid="11f5cea9-bf22-41ab-85c8-067958ac33d3">
<childModelRefInfo type="ModelRefInfoRepo.ChildModelRefInfo" uuid="20a7fd9e-726f-46b7-806c-40e167ccf8ba">
<modelName>uORB_MODBUS_TCP</modelName>
<modelPath>uORB_MODBUS_TCP</modelPath>
</childModelRefInfo>
<compiledTFinal>10.0</compiledTFinal>
<dataSourceInfo type="ModelRefInfoRepo.DataSourceInfo" uuid="25f0742b-d008-457b-9aa8-d2b546462c75">
<dataSources type="ModelRefInfoRepo.SourceInfo" uuid="8e0336d3-048c-46e2-8f2c-a8929ef5bf10">
<dataSourceInfo type="ModelRefInfoRepo.DataSourceInfo" uuid="c5e1c170-5264-41da-bb91-5f0735d33d5a">
<dataSources type="ModelRefInfoRepo.SourceInfo" uuid="4003fcc4-1e43-4e5d-8cdf-fa6104070eb6">
<includeAllSections>true</includeAllSections>
<sourceName>base workspace</sourceName>
<type>BaseWorkspace</type>
@ -17,7 +17,11 @@
<dataTransferInfos>AAFJTQAAAAAOAAAAOAAAAAYAAAAIAAAAAgAAAAAAAAAFAAAACAAAAAAAAAABAAAAAQAAAAAAAAAFAAQAAQAAAAEAAAAAAAAA</dataTransferInfos>
<defaultsCMapping>{&quot;Inports&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;Outports&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;ParameterArguments&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;LocalParameters&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;GlobalParameters&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;InternalData&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;SharedLocalDataStores&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;GlobalDataStores&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;Constants&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;DataTransfers&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;ModelData&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;InitializeTerminate&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;Execution&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;,&quot;SharedUtility&quot;:&quot;{\&quot;Name\&quot;:\&quot;Default\&quot;,\&quot;Checksum\&quot;:\&quot;Default\&quot;,\&quot;PerInstancePropertiesChecksum\&quot;:\&quot;\&quot;,\&quot;MemorySectionName\&quot;:\&quot;None\&quot;,\&quot;MemorySectionChecksum\&quot;:\&quot;None\&quot;}&quot;}</defaultsCMapping>
<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>
<hasBwsAccessed>true</hasBwsAccessed>
<isBdInSimModeForSimCodegenVariants>false</isBdInSimModeForSimCodegenVariants>
@ -29,59 +33,78 @@
<runtimeNonFcnCallRateInfos type="ModelRefInfoRepo.RateInfo">
<compiled>true</compiled>
<nonFcnCallPartitionName>D1</nonFcnCallPartitionName>
<period>5.0</period>
<period>.25</period>
<priority>40</priority>
<rateIdx>0</rateIdx>
</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>
<solverStatusFlags>335</solverStatusFlags>
<timingAndTaskingRegistry>&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;slexec_sto version=&quot;1.1&quot; packageUris=&quot;http://schema.mathworks.com/mf0/slexec_mm_sto/R2024a_202305081229&quot;&gt;
&lt;sto.Registry type=&quot;sto.Registry&quot; uuid=&quot;ee73db1b-f182-40a7-b4b2-32cb5a9d4db8&quot;&gt;
&lt;sto.Registry type=&quot;sto.Registry&quot; uuid=&quot;9f787942-3fbf-40bf-83d9-ca31d2944761&quot;&gt;
&lt;executionSpec&gt;Undetermined&lt;/executionSpec&gt;
&lt;identifier&gt;uORB_MODBUS_TCP&lt;/identifier&gt;
&lt;clockRegistry type=&quot;sto.ClockRegistry&quot; uuid=&quot;ec9112c3-f7df-4d70-9e32-e8deed783d4b&quot;&gt;
&lt;clocks type=&quot;sto.Timer&quot; uuid=&quot;2d74743a-7fa6-484f-840f-02b24087f560&quot;&gt;
&lt;computedFundamentalDiscretePeriod&gt;5.0&lt;/computedFundamentalDiscretePeriod&gt;
&lt;fastestDiscreteRate type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;29f1da5c-2a35-48ef-a7fe-a82629440e39&quot;/&gt;
&lt;clockRegistry type=&quot;sto.ClockRegistry&quot; uuid=&quot;e3adf32f-9edb-41d2-8d65-2aa99a600d7d&quot;&gt;
&lt;clocks type=&quot;sto.Timer&quot; uuid=&quot;3a0b736d-652a-409a-b254-5d476adf58b2&quot;&gt;
&lt;computedFundamentalDiscretePeriod&gt;.25&lt;/computedFundamentalDiscretePeriod&gt;
&lt;fastestDiscreteRate type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;ba617304-1665-47a9-8567-cc2b033188ef&quot;/&gt;
&lt;isDefaultTimer&gt;true&lt;/isDefaultTimer&gt;
&lt;resolution&gt;5.0&lt;/resolution&gt;
&lt;resolution&gt;.25&lt;/resolution&gt;
&lt;timeAdvanceMode&gt;FixedStep&lt;/timeAdvanceMode&gt;
&lt;identifier&gt;uORB_MODBUS_TCP::defaultTimer&lt;/identifier&gt;
&lt;rates type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;29f1da5c-2a35-48ef-a7fe-a82629440e39&quot;&gt;
&lt;rates type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;ba617304-1665-47a9-8567-cc2b033188ef&quot;&gt;
&lt;annotation&gt;D1&lt;/annotation&gt;
&lt;clockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockId&gt;
&lt;description&gt;Discrete 1&lt;/description&gt;
&lt;taskId&gt;_task0&lt;/taskId&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;1368f082-b58c-4c67-b97a-0fb3024453e7&quot;&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;26cde9ad-fd89-4996-b202-d4b6c44daffc&quot;&gt;
&lt;period&gt;.25&lt;/period&gt;
&lt;rateType&gt;ClassicPeriodicDiscrete&lt;/rateType&gt;
&lt;/rateSpec&gt;
&lt;/rates&gt;
&lt;rates type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;6f6b4dea-ac0b-4961-855e-736959b539d1&quot;&gt;
&lt;annotation&gt;D2&lt;/annotation&gt;
&lt;clockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockId&gt;
&lt;colorIndex&gt;1&lt;/colorIndex&gt;
&lt;description&gt;Discrete 2&lt;/description&gt;
&lt;rateIdx&gt;1&lt;/rateIdx&gt;
&lt;taskId&gt;_task1&lt;/taskId&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;f257fe37-2af7-417a-b5c7-0428c312f42d&quot;&gt;
&lt;period&gt;5.0&lt;/period&gt;
&lt;rateType&gt;ClassicPeriodicDiscrete&lt;/rateType&gt;
&lt;/rateSpec&gt;
&lt;/rates&gt;
&lt;baseRate type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;fc5d4684-395b-44c9-8cfa-430a2d34b8de&quot;&gt;
&lt;baseRate type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;65b35d5e-227d-4911-bc52-2893aadaefbf&quot;&gt;
&lt;annotation&gt;D1&lt;/annotation&gt;
&lt;clockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockId&gt;
&lt;description&gt;Discrete 1&lt;/description&gt;
&lt;taskId&gt;_task0&lt;/taskId&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;ae85af8c-7a93-4769-abad-dfb66bc50c8e&quot;&gt;
&lt;period&gt;5.0&lt;/period&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;ff2d4d8a-96eb-48d4-9f8f-062960f9fb1d&quot;&gt;
&lt;period&gt;.25&lt;/period&gt;
&lt;rateType&gt;ClassicPeriodicDiscrete&lt;/rateType&gt;
&lt;/rateSpec&gt;
&lt;/baseRate&gt;
&lt;/clocks&gt;
&lt;timeAdvanceMode&gt;FixedStep&lt;/timeAdvanceMode&gt;
&lt;/clockRegistry&gt;
&lt;taskRegistry type=&quot;sto.TaskRegistry&quot; uuid=&quot;052f32c4-2b96-4908-913e-03a4854d96c0&quot;&gt;
&lt;rootTaskHierarchyElements type=&quot;sto.Task&quot; uuid=&quot;8de7de87-835c-46ef-ad46-f88050f2605e&quot;&gt;
&lt;taskRegistry type=&quot;sto.TaskRegistry&quot; uuid=&quot;b6adc007-26b8-402c-b01d-1e3d81bb5c20&quot;&gt;
&lt;rootTaskHierarchyElements type=&quot;sto.Task&quot; uuid=&quot;5edff6a2-d515-4f58-a3d8-c5326ec15f76&quot;&gt;
&lt;isExecutable&gt;true&lt;/isExecutable&gt;
&lt;orderIndex&gt;1&lt;/orderIndex&gt;
&lt;rates type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;287f9e9c-18e9-462d-bf56-5a7dc6aad9b7&quot;&gt;
&lt;rates type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;f55c6bcc-446d-42c6-90e7-ff6c2ff6f624&quot;&gt;
&lt;annotation&gt;D1&lt;/annotation&gt;
&lt;clockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockId&gt;
&lt;description&gt;Discrete 1&lt;/description&gt;
&lt;taskId&gt;_task0&lt;/taskId&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;31b43a7e-4ce0-4be9-a684-8e88514ad3d8&quot;&gt;
&lt;period&gt;5.0&lt;/period&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;d3854663-c664-46a3-a0a9-41f57f4994dd&quot;&gt;
&lt;period&gt;.25&lt;/period&gt;
&lt;rateType&gt;ClassicPeriodicDiscrete&lt;/rateType&gt;
&lt;/rateSpec&gt;
&lt;/rates&gt;
@ -91,7 +114,33 @@
&lt;identifier&gt;_task0&lt;/identifier&gt;
&lt;priority&gt;40&lt;/priority&gt;
&lt;/rootTaskHierarchyElements&gt;
&lt;taskDependencyGraph type=&quot;sto.SerializedTaskConnectionList&quot; uuid=&quot;6a78d61d-7a32-4285-b101-584200d36c5c&quot;&gt;
&lt;rootTaskHierarchyElements type=&quot;sto.Task&quot; uuid=&quot;a86fefe7-45e4-423e-9db6-880c90fa3d37&quot;&gt;
&lt;isExecutable&gt;true&lt;/isExecutable&gt;
&lt;orderIndex&gt;2&lt;/orderIndex&gt;
&lt;rates type=&quot;sto.ClassicPeriodicDiscreteRate&quot; uuid=&quot;8d76a60f-fbc0-4d52-b0c5-783585f4eb4e&quot;&gt;
&lt;annotation&gt;D2&lt;/annotation&gt;
&lt;clockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockId&gt;
&lt;colorIndex&gt;1&lt;/colorIndex&gt;
&lt;description&gt;Discrete 2&lt;/description&gt;
&lt;rateIdx&gt;1&lt;/rateIdx&gt;
&lt;taskId&gt;_task1&lt;/taskId&gt;
&lt;rateSpec type=&quot;sto.RateSpec&quot; uuid=&quot;7e68009f-8a4a-4dac-9abb-5a4cbf16a75c&quot;&gt;
&lt;period&gt;5.0&lt;/period&gt;
&lt;rateType&gt;ClassicPeriodicDiscrete&lt;/rateType&gt;
&lt;/rateSpec&gt;
&lt;/rates&gt;
&lt;schedulingClockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/schedulingClockId&gt;
&lt;tNum&gt;1&lt;/tNum&gt;
&lt;timeKeeperClockId&gt;uORB_MODBUS_TCP::defaultTimer&lt;/timeKeeperClockId&gt;
&lt;elementType&gt;Task&lt;/elementType&gt;
&lt;identifier&gt;_task1&lt;/identifier&gt;
&lt;priority&gt;39&lt;/priority&gt;
&lt;/rootTaskHierarchyElements&gt;
&lt;taskDependencyGraph type=&quot;sto.SerializedTaskConnectionList&quot; uuid=&quot;d51d07bc-b865-4d1b-bd8f-102c79ccc172&quot;&gt;
&lt;clockIdentifier&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockIdentifier&gt;
&lt;taskIdentifier&gt;_task1&lt;/taskIdentifier&gt;
&lt;/taskDependencyGraph&gt;
&lt;taskDependencyGraph type=&quot;sto.SerializedTaskConnectionList&quot; uuid=&quot;711a613b-96b6-4f2f-bbfe-1a5d260148ac&quot;&gt;
&lt;clockIdentifier&gt;uORB_MODBUS_TCP::defaultTimer&lt;/clockIdentifier&gt;
&lt;taskIdentifier&gt;_task0&lt;/taskIdentifier&gt;
&lt;/taskDependencyGraph&gt;
@ -100,20 +149,22 @@
&lt;/sto.Registry&gt;
&lt;/slexec_sto&gt;</timingAndTaskingRegistry>
<zeroInternalMemoryAtStartupUnchecked>true</zeroInternalMemoryAtStartupUnchecked>
<FMUBlockMap type="ModelRefInfoRepo.FMUBlockInfo" uuid="b78c3852-febd-4438-a3c4-ba931993565b"/>
<codeGenInfo type="ModelRefInfoRepo.CodeGenInformation" uuid="7b955e3c-022c-4677-b8a9-5a34881d940a"/>
<compiledVariantInfos type="ModelRefInfoRepo.CompiledVariantInfoMap" uuid="709fdb14-b8b3-46bb-9cc1-e5b855385f4e"/>
<configSettingsForConsistencyChecks type="ModelRefInfoRepo.ConfigSettingsForConsistencyChecks" uuid="fe654506-60ec-46dc-be72-6db6f70d77f4">
<FMUBlockMap type="ModelRefInfoRepo.FMUBlockInfo" uuid="981c6145-983b-408d-b0f1-66d4d59e61bd"/>
<codeGenInfo type="ModelRefInfoRepo.CodeGenInformation" uuid="81098c80-e40c-4c3b-ba26-ce2b20c73848"/>
<compiledVariantInfos type="ModelRefInfoRepo.CompiledVariantInfoMap" uuid="988faa22-55fc-4f06-9327-f94f07e57c00"/>
<configSettingsForConsistencyChecks type="ModelRefInfoRepo.ConfigSettingsForConsistencyChecks" uuid="ebc3161f-26a9-4b8c-ba43-4532a7f046ee">
<consistentOutportInitialization>true</consistentOutportInitialization>
<fixedStepSize>5.0</fixedStepSize>
<fixedStepSize>.25</fixedStepSize>
<frameDiagnosticSetting>2</frameDiagnosticSetting>
<hasHybridSampleTime>true</hasHybridSampleTime>
<isRateGrouped>true</isRateGrouped>
<optimizedInitCode>true</optimizedInitCode>
<signalLoggingSaveFormat>2</signalLoggingSaveFormat>
<simSIMDOptimization>1</simSIMDOptimization>
<solverMode>SOLVER_MODE_MULTITASKING</solverMode>
<solverName>FixedStepDiscrete</solverName>
<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>
<prodBitPerDouble>64</prodBitPerDouble>
<prodBitPerFloat>32</prodBitPerFloat>
@ -132,34 +183,35 @@
<prodWordSize>32</prodWordSize>
</hardwareSettings>
</configSettingsForConsistencyChecks>
<controllableInputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="ec0551ad-1a96-4d56-9856-f3704f7b2c67"/>
<controllableOutputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="7a67cd19-1051-4cad-ad1f-7d6cf77fc3ac"/>
<dataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="438f73bd-1c23-42f8-81b6-0cfe9392c804"/>
<expFcnUnconnectedDataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="b6970967-995e-4489-8214-c87f28f9a2d2"/>
<interfaceParameterInfo type="ModelRefInfoRepo.InterfaceParameterInfo" uuid="af6f3444-fe96-491b-8aa1-cd25b76e1cc5"/>
<messageInfo type="ModelRefInfoRepo.MessageInformation" uuid="f408063d-0f9a-4cf7-9bd9-23468c11595f"/>
<methodInfo type="ModelRefInfoRepo.MethodExistenceInfo" uuid="d4945a20-1132-4e2f-bafb-baadb0367111"/>
<periodicEventPortUnsupportedBlockInfo type="ModelRefInfoRepo.PeriodicEventPortUnsupportedBlockInfo" uuid="873d196f-089c-4580-b702-7c7b703e93b7"/>
<portGroupsRequireSameRate type="ModelRefInfoRepo.PortGroupsRequireSameRate" uuid="fa0abc97-6be3-468c-81ff-48f326095818">
<DSMPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="4df51b3a-64c5-4052-9891-f538b30df737"/>
<GlobalDSMPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="b859e8d4-8f6e-46db-99e9-525cec7de320"/>
<mergedPortGroups type="ModelRefInfoRepo.NameToPortGroupIdxVectMap" uuid="5e607a43-12a1-4dff-8081-717abd030776"/>
<controllableInputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="00777ed3-9b83-4205-9df1-9c63207c8b32"/>
<controllableOutputRatesMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="75ff445e-a4bf-4bb5-bb10-1e29540bc9a2"/>
<dataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="29dc6b09-d5cb-4280-81ef-8b32487ec875"/>
<expFcnUnconnectedDataPortGroup type="ModelRefInfoRepo.DataPortGroup" uuid="042d7f00-00ba-4bd0-b0d3-e795640ddff8"/>
<interfaceParameterInfo type="ModelRefInfoRepo.InterfaceParameterInfo" uuid="6ace8d3c-49f7-40d5-82f7-93466352fc19"/>
<messageInfo type="ModelRefInfoRepo.MessageInformation" uuid="586ee838-920e-4f37-a8f5-cb14a8473327"/>
<methodInfo type="ModelRefInfoRepo.MethodExistenceInfo" uuid="8341f440-358c-4086-8c0b-75eff483cdef">
<hasTerminateMethod>true</hasTerminateMethod>
</methodInfo>
<periodicEventPortUnsupportedBlockInfo type="ModelRefInfoRepo.PeriodicEventPortUnsupportedBlockInfo" uuid="8fd011f1-feb4-43a7-9dcc-3bafbb76b6e8"/>
<portGroupsRequireSameRate type="ModelRefInfoRepo.PortGroupsRequireSameRate" uuid="fa458fff-85e6-462e-89ff-b1f375c0a4fa">
<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>
<rateBasedMdlGlobalDSMRateSpec type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="19f34c02-c41d-4a06-b0b4-8b40a821a007"/>
<rateSpecOfGlobalDSMAccessedByDescExpFcnMdlMap type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="45484e10-296f-4fb2-9888-8efc6a0a0759"/>
<rootBlockDiagramInterface type="ci.Model" uuid="1efa62d5-e252-4708-a49b-d383b4db946f">
<p_RootComponentInterface type="ci.ComponentInterface" uuid="f3987313-e44d-4276-b713-814de3442198">
<rateBasedMdlGlobalDSMRateSpec type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="554fa760-8e30-4445-adb6-9ac9ee9c6cd5"/>
<rateSpecOfGlobalDSMAccessedByDescExpFcnMdlMap type="ModelRefInfoRepo.GlobalDSMRateSpecMap" uuid="e98c7b33-62d6-48d1-87e7-fe44780e8d49"/>
<rootBlockDiagramInterface type="ci.Model" uuid="12261508-8e65-4ff5-8eac-e1f47b47814f">
<p_RootComponentInterface type="ci.ComponentInterface" uuid="f75dbd08-8409-4f75-b7b7-8d20ad28a353">
<p_Name>uORB_MODBUS_TCP</p_Name>
<p_Type>ROOT</p_Type>
</p_RootComponentInterface>
</rootBlockDiagramInterface>
<simulinkFunctions type="ModelRefInfoRepo.SimulinkFunctions" uuid="6e092575-a0c4-4956-9e38-a54720508fe7">
<simulinkFunctions type="ModelRefInfoRepo.SimulinkFunctions" uuid="a445c89f-0276-4914-90ae-cc80358a9793">
<compSimulinkFunctionCatalog></compSimulinkFunctionCatalog>
</simulinkFunctions>
<sltpContext type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1">
<unusedTaskIds>2</unusedTaskIds>
<unusedTaskIds>4</unusedTaskIds>
<unusedTaskIds>3</unusedTaskIds>
<unusedTaskIds>2</unusedTaskIds>
<defaultEventBehavior type="sltp.mm.core.EventBehavior" uuid="21e3b347-5d31-4104-934b-203b90595926"/>
<editorState type="sltp.mm.core.EditorState" uuid="07d98215-aad0-45df-84e8-46192d73c28f">
<isSynchronized>true</isSynchronized>
@ -171,49 +223,77 @@
<name>Default</name>
<priority>-2147483648</priority>
<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">
<context type="sltp.mm.core.Context" uuid="15bade9e-32a2-424a-a2ab-8fee2723b6f1"/>
<explicit>false</explicit>
<id>1</id>
<isTimed>true</isTimed>
<name>D1</name>
<priority>40</priority>
<name>D2</name>
<priority>39</priority>
<rates type="sltp.mm.core.Rate" uuid="03620e11-eb05-4414-bdcb-7c2cf9edc125">
<annotation>D1</annotation>
<color>-12240129</color>
<annotation>D2</annotation>
<color>986198527</color>
<hasBlocks>true</hasBlocks>
<identifier>ClassicPeriodicDiscrete50</identifier>
<rateIndex>0</rateIndex>
<rateIndex>1</rateIndex>
<rateSpec type="sltp.mm.core.RateSpec">
<period>5.0</period>
</rateSpec>
<sti>0</sti>
<sti>1</sti>
</rates>
</tasks>
</subgraph>
</rootTask>
</sltpContext>
<stateWriterToOwnerMap type="ModelRefInfoRepo.StateWriterInfo" uuid="7f963979-9bcb-4a12-a87e-7df772451a89"/>
<stoClientDataRegistry type="sto.ClientDataRegistry" uuid="a1f49343-a294-473a-a178-26618b4668f8">
<dataSets type="sto.ClientClockNamedDataSet" uuid="d0159836-75ae-4680-bf92-b48a16f424bb">
<stateWriterToOwnerMap type="ModelRefInfoRepo.StateWriterInfo" uuid="27003578-7b2d-4c90-aee7-fe7cb04dd50d"/>
<stoClientDataRegistry type="sto.ClientDataRegistry" uuid="b666e450-35bb-4dd8-b7f4-ccfb90f1962c">
<dataSets type="sto.ClientClockNamedDataSet" uuid="3439df2d-bbdd-4e43-9bf3-7404c5ffe8a0">
<tag>sltpEvents</tag>
</dataSets>
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="5d8d7d5b-38ce-4410-86e0-45e0f3cbb56b">
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="ff48cb56-2c3f-462e-ba5f-1624780fae24">
<tag>sltpTaskGroups</tag>
</dataSets>
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="ca090357-8c2d-4706-bef0-51cdea588c97">
<dSet type="ModelRefInfoRepo.SltpTaskData" uuid="dde5ee80-ff9e-4fcd-8481-a11df1dc59ed"/>
<tSet type="ModelRefInfoRepo.SltpTaskData" uuid="dde5ee80-ff9e-4fcd-8481-a11df1dc59ed">
<dataSets type="sto.ClientTaskHierarchyElementNamedDataSet" uuid="8e3be1df-6fa9-4289-9165-b2e620bf0adf">
<dSet type="ModelRefInfoRepo.SltpTaskData" uuid="5c6cd961-bad7-473b-afcb-505519e8c5be"/>
<dSet type="ModelRefInfoRepo.SltpTaskData" uuid="5289e2d2-d218-4b66-b92f-5754852a9c90"/>
<tSet type="ModelRefInfoRepo.SltpTaskData" uuid="5c6cd961-bad7-473b-afcb-505519e8c5be">
<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">
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
<id>_task0</id>
</id>
</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>
</dataSets>
</stoClientDataRegistry>
<varTsUIDMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="a16da2ea-bdff-4f8d-84df-e1e6fa8d37f7"/>
<varTsUIDMap type="ModelRefInfoRepo.VarTsUIDMap" uuid="9faef9fa-1bd4-43a3-bee9-6be26afe201d"/>
</ModelRefInfoRepo.ModelRefInfoRoot>
</MF0>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/SlCache/19700101">
<slcache.FileAttributes type="slcache.FileAttributes" uuid="714b24d4-7c5b-48b5-b852-087cf102ecde">
<checksum>DdrRgVnyR6kegWj1mpzaDcyS+Rh4VBoYEPYCL7/LAGEIf+p+iTuTZYWKYUM1yL59ppS4QwFUE2pBT336Wo0z0Q==</checksum>
<slcache.FileAttributes type="slcache.FileAttributes" uuid="c674998f-0be5-4035-8ad2-943c5087b773">
<checksum>/s11ahv8mqi9vbwi2UlouCYjA9mjT/SmcREmK0z6aZ3EQci35TC+5lA8FKJ8gHVO/ti5sHt+uyYmU1Xb7DYBzg==</checksum>
</slcache.FileAttributes>
</MF0>

View File

@ -5,16 +5,19 @@ set(MAVLINK_LIBRARY_DIR "${CMAKE_BINARY_DIR}/mavlink")
set(MAVLINK_DIALECT_UAVIONIX "uAvionix")
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(
MODULE modules__px4_simulink_app
MAIN px4_simulink_app
STACK_MAIN 2000
SRCS
MW_uORB_Read.cpp
MW_uORB_Write.cpp
modbus_tcp_client.cpp
ert_main.cpp
uORB_MODBUS_TCP.cpp
modbus_tcp_client.cpp
uORB_MODBUS_TCP_data.cpp
MW_PX4_TaskControl.cpp
nuttxinitialize.cpp
COMPILE_FLAGS
@ -27,14 +30,15 @@ SRCS
${MAVLINK_LIBRARY_DIR}
${MAVLINK_LIBRARY_DIR}/${CONFIG_MAVLINK_DIALECT}
${MAVLINK_LIBRARY_DIR}/${MAVLINK_DIALECT_UAVIONIX}
/home/judson/GSE-Miscellaneous/Pixhawk_and_GSE/MATLAB/uORB_MODBUS_TCP
/home/judson/GSE-Miscellaneous/Pixhawk_and_GSE/MATLAB/uORB_MODBUS_TCP/uORB_MODBUS_TCP_ert_rtw
/usr/local/MATLAB/R2024a/extern/include
/usr/local/MATLAB/R2024a/simulink/include
/usr/local/MATLAB/R2024a/rtw/c/src
/usr/local/MATLAB/R2024a/rtw/c/src/ext_mode/common
/usr/local/MATLAB/R2024a/rtw/c/ert
/root/Documents/MATLAB/SupportPackages/R2024a/toolbox/target/supportpackages/px4/include
/home/judson/Pixhawk/MATLAB/uORB_MODBUS_TCP
/home/judson/Documents/MATLAB/SupportPackages/R2024a/toolbox/target/supportpackages/px4/include
/home/judson/Pixhawk/MATLAB
/home/judson/Pixhawk/MATLAB/uORB_MODBUS_TCP/uORB_MODBUS_TCP_ert_rtw
/home/judson/MATLAB/extern/include
/home/judson/MATLAB/simulink/include
/home/judson/MATLAB/rtw/c/src
/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)

View File

@ -1,11 +1,12 @@
#ifndef _MW_CUSTOM_RTOS_HEADER_H_
#define _MW_CUSTOM_RTOS_HEADER_H_
#define MW_BASERATE_PRIORITY 250
#define MW_BASERATE_PERIOD 5.0
#define MW_NUMBER_SUBRATES 0
#define MW_BASERATE_PERIOD 0.25
#define MW_NUMBER_SUBRATES 1
#define MW_NUMBER_APERIODIC_TASKS 0
#define MW_IS_CONCURRENT 0
#define MW_NUMBER_TIMER_DRIVEN_TASKS 0
#define MW_HAS_MULTIPLE_RATES
extern void exitFcn(int sig);
extern void *terminateTask(void *arg);

View File

@ -1,6 +1,14 @@
#ifndef _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

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex
@ -36,22 +36,63 @@ volatile boolean_T stopRequested = false;
volatile boolean_T runModel = true;
px4_sem_t stopSem;
px4_sem_t baserateTaskSem;
px4_sem_t subrateTaskSem[1];
int taskId[1];
pthread_t schedulerThread;
pthread_t baseRateThread;
void *threadJoinStatus;
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)
{
runModel = (rtmGetErrorStatus(uORB_MODBUS_TCP_M) == (nullptr));
while (runModel) {
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
stopRequested = !((rtmGetErrorStatus(uORB_MODBUS_TCP_M) == (nullptr)));
}
runModel = 0;
terminateTask(arg);
pthread_exit((void *)0);
return NULL;
@ -70,6 +111,20 @@ void *terminateTask(void *arg)
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;
}
@ -83,6 +138,7 @@ void *terminateTask(void *arg)
int px4_simulink_app_task_main (int argc, char *argv[])
{
subratePriority[0] = 249;
px4_simulink_app_control_MAVLink();
rtmSetErrorStatus(uORB_MODBUS_TCP_M, 0);
@ -90,7 +146,7 @@ int px4_simulink_app_task_main (int argc, char *argv[])
uORB_MODBUS_TCP_initialize();
// Call RTOS Initialization function
nuttxRTOSInit(5.0, 0);
nuttxRTOSInit(0.25, 1);
// Wait for stop semaphore
px4_sem_wait(&stopSem);

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex

View File

@ -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
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

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<MF0 version="1.1" packageUris="http://schema.mathworks.com/mf0/SlCache/19700101">
<slcache.FileAttributes type="slcache.FileAttributes" uuid="363fac90-3453-454e-bbc2-a7e8306b5f8a">
<checksum>DdrRgVnyR6kegWj1mpzaDcyS+Rh4VBoYEPYCL7/LAGEIf+p+iTuTZYWKYUM1yL59ppS4QwFUE2pBT336Wo0z0Q==</checksum>
<slcache.FileAttributes type="slcache.FileAttributes" uuid="f9dfac28-b929-4d57-b9c8-0fd474c23e73">
<checksum>5yKZbaLdWAwwyNBmOxcGcB7eucJzsPxwRZ02y1HQ/zqjVzzjpGumt3HlxZz33ZPrLqkO8UQWCZNG+QwONwRlVw==</checksum>
</slcache.FileAttributes>
</MF0>

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex
@ -17,68 +17,584 @@
// Validation result: Not run
//
#include "uORB_MODBUS_TCP.h"
#include "rtwtypes.h"
// Block signals (default storage)
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
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_ };
// Model step function
void uORB_MODBUS_TCP_step(void)
static void rate_monotonic_scheduler(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)
{
static ModbusTCPClient modbus("192.168.0.249", 5020, 10, 10, 10, 10);
// 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'
{
// 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()) {
modbus.setTimeout(1000);
modbus.setTimeout(3000); // Set timeout in milliseconds
if (!modbus.connectServer()) {
printf("Failed to connect to MODBUS server!\n");
return;
printf("Failed to connect to MODBUS server in!\n");
}
}
const int num_reads = 1000;
uint16_t last_value = 0;
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;
if (modbus.readAll() != ModbusError::NONE) {
printf("Error calling modbus.readAll()\n");
}
// Average the differences
float avg_diff = sum_differences / num_reads;
printf("Average time difference between reads (ms): %.2f\n", avg_diff);
// --- Holding Registers (HR) ---
// Read a subset of HR registers into our buffer.
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
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
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'
}
//

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex
@ -18,8 +18,16 @@
//
#ifndef uORB_MODBUS_TCP_h_
#define uORB_MODBUS_TCP_h_
#include <poll.h>
#include <uORB/uORB.h>
#include "rtwtypes.h"
#include "MW_uORB_Read.h"
#include "MW_uORB_Write.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"
// Macros for accessing real-time model data structure
@ -31,6 +39,14 @@
#define rtmSetErrorStatus(rtm, val) ((rtm)->errorStatus = (val))
#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)
#include <netinet/in.h>
#include <sys/types.h>
@ -40,18 +56,127 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "modbus_tcp_client.h"
// Block signals (default storage)
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
struct tag_RTM_uORB_MODBUS_TCP_T {
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)
#ifdef __cplusplus
@ -68,6 +193,25 @@ extern "C"
#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
extern "C"
@ -77,7 +221,9 @@ extern "C"
// Model entry point functions
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);
#ifdef __cplusplus
@ -120,6 +266,22 @@ extern volatile boolean_T runModel;
// Here is the system hierarchy for this model
//
// '<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'
//-

View File

@ -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]
//

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex

View File

@ -7,9 +7,9 @@
//
// 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
// 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
// Embedded hardware selection: ARM Compatible->ARM Cortex
@ -18,6 +18,52 @@
//
#ifndef 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
typedef struct tag_RTM_uORB_MODBUS_TCP_T RT_MODEL_uORB_MODBUS_TCP_T;