Updated simulink models and modbus_tcp code to most recent version
This commit is contained in:
parent
c3e0677ce4
commit
e82bbf20de
@ -1,5 +1,4 @@
|
||||
#include "modbus_tcp_client.h"
|
||||
#include <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;
|
||||
}
|
||||
@ -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();
|
||||
@ -1,757 +0,0 @@
|
||||
#include "modbus_tcp_client.h"
|
||||
#include <sys/select.h> // For select() timeout
|
||||
|
||||
ModbusTCPClient::ModbusTCPClient(const char* ip, int port, int numCoils, int numDI, int numIR, int numHR,
|
||||
int startCoils, int startDI, int startIR, int startHR)
|
||||
: serverIP(ip), serverPort(port), socketFD(-1), transactionID(1),
|
||||
numCoils(numCoils), numDiscreteInputs(numDI), numInputRegisters(numIR), numHoldingRegisters(numHR),
|
||||
startCoils(startCoils), startDiscreteInputs(startDI), startInputRegisters(startIR), startHoldingRegisters(startHR) {
|
||||
|
||||
// Allocate memory dynamically based on provided sizes
|
||||
coilsRead = new bool[numCoils]();
|
||||
coilsWrite = new bool[numCoils]();
|
||||
discreteInputs = new bool[numDiscreteInputs]();
|
||||
|
||||
inputRegisters = new uint16_t[numInputRegisters]();
|
||||
holdingRegistersRead = new uint16_t[numHoldingRegisters]();
|
||||
holdingRegistersWrite = new uint16_t[numHoldingRegisters]();
|
||||
}
|
||||
|
||||
ModbusTCPClient::ModbusTCPClient(const char* ip, int port)
|
||||
: serverIP(ip), serverPort(port), socketFD(-1) {
|
||||
/*
|
||||
This constructor is if the user manually wants to call MODBUS TCP functions and not
|
||||
use readAll() and writeAll() and the setters/getters
|
||||
*/
|
||||
|
||||
// Set everything to nullptr so that readAll() and writeAll() won't work
|
||||
coilsRead = nullptr;
|
||||
coilsWrite = nullptr;
|
||||
discreteInputs = nullptr;
|
||||
|
||||
inputRegisters = nullptr;
|
||||
holdingRegistersRead = nullptr;
|
||||
holdingRegistersWrite = nullptr;
|
||||
}
|
||||
|
||||
ModbusTCPClient::~ModbusTCPClient() {
|
||||
delete[] coilsRead;
|
||||
delete[] coilsWrite;
|
||||
delete[] discreteInputs;
|
||||
|
||||
delete[] inputRegisters;
|
||||
delete[] holdingRegistersRead;
|
||||
delete[] holdingRegistersWrite;
|
||||
}
|
||||
|
||||
void ModbusTCPClient::setStartAddresses(int startCoils, int startDI, int startIR, int startHR) {
|
||||
this->startCoils = startCoils;
|
||||
this->startDiscreteInputs = startDI;
|
||||
this->startInputRegisters = startIR;
|
||||
this->startHoldingRegisters = startHR;
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::connectServer() {
|
||||
// Step 1: If socket is already open, verify it's still connected
|
||||
if (socketFD != -1) {
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 100000; // 100ms timeout for connection check
|
||||
|
||||
fd_set read_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(socketFD, &read_fds);
|
||||
|
||||
int result = select(socketFD + 1, &read_fds, NULL, NULL, &timeout);
|
||||
|
||||
if (result == 0) {
|
||||
// No error in select, socket is still connected
|
||||
printf("MODBUS_TCP_CLIENT: Already connected to MODBUS server\n");
|
||||
return true;
|
||||
} else {
|
||||
// Connection is broken, close and reset
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Connection lost, reconnecting...\n");
|
||||
disconnectServer();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Create a new socket
|
||||
for (int attempts = 0; attempts < 5; attempts++) { // Retry up to 5 times
|
||||
socketFD = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (socketFD < 0) {
|
||||
printf("MODBUS_TCP_CLIENT: Could not create socket\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in serverAddr;
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(serverPort);
|
||||
inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);
|
||||
|
||||
// Step 3: Attempt to connect
|
||||
printf("MODBUS_TCP_CLIENT: Attempting to connect to MODBUS server (Try %d)...\n", attempts + 1);
|
||||
if (connect(socketFD, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == 0) {
|
||||
printf("MODBUS_TCP_CLIENT: Connected to MODBUS server at %s:%d\n", serverIP, serverPort);
|
||||
return true;
|
||||
}
|
||||
|
||||
printf("MODBUS_TCP_CLIENT: Connection failed, retrying...\n");
|
||||
disconnectServer(); // Close socket before retrying
|
||||
usleep(100000); // Wait 100ms before retrying
|
||||
}
|
||||
}
|
||||
|
||||
void ModbusTCPClient::disconnectServer() {
|
||||
if (socketFD != -1) {
|
||||
close(socketFD);
|
||||
socketFD = -1;
|
||||
printf("MODBUS_TCP_CLIENT: Disconnected from MODBUS server\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ModbusTCPClient::setTimeout(int milliseconds) {
|
||||
timeoutMilliseconds = milliseconds;
|
||||
printf("MODBUS_TCP_CLIENT: Timeout set to %d ms\n", timeoutMilliseconds);
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::isConnected() const {
|
||||
return socketFD != -1;
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::reconnectServer() {
|
||||
printf("MODBUS_TCP_CLIENT: Attempting manual reconnection...\n");
|
||||
disconnectServer();
|
||||
return connectServer();
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::sendRequest(uint8_t* request, int requestSize) {
|
||||
// Ensure we're connected before sending
|
||||
if (socketFD == -1) {
|
||||
printf("MODBUS_TCP_CLIENT: Connection lost. Attempting to reconnect...\n");
|
||||
if (!connectServer()) {
|
||||
printf("MODBUS_TCP_CLIENT: Reconnection failed. Cannot send request.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int bytesSent = write(socketFD, request, requestSize);
|
||||
if (bytesSent <= 0) { // Detect broken connection during write
|
||||
printf("MODBUS_TCP_CLIENT: Write failed, connection lost. Disconnecting...\n");
|
||||
disconnectServer();
|
||||
return false;
|
||||
}
|
||||
|
||||
return bytesSent == requestSize;
|
||||
return bytesSent == requestSize;
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::receiveResponse(uint8_t* response, int expectedSize) {
|
||||
int totalBytesReceived = 0;
|
||||
|
||||
while (totalBytesReceived < expectedSize) {
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = timeoutMilliseconds / 1000; // Convert ms to seconds
|
||||
timeout.tv_usec = (timeoutMilliseconds % 1000) * 1000; // Convert remaining ms to µs
|
||||
|
||||
fd_set read_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(socketFD, &read_fds);
|
||||
|
||||
// Use select() to wait for data before reading
|
||||
int ready = select(socketFD + 1, &read_fds, NULL, NULL, &timeout);
|
||||
if (ready == 0) { // Timeout case
|
||||
printf("MODBUS_TCP_CLIENT: Timeout waiting for MODBUS response. Disconnecting...\n");
|
||||
disconnectServer(); // Close socket and reset socketFD
|
||||
return false;
|
||||
} else if (ready < 0) { // Select failed
|
||||
printf("MODBUS_TCP_CLIENT: Select failed. Disconnecting...\n");
|
||||
disconnectServer(); // Close socket and reset socketFD
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read available data
|
||||
int bytesReceived = read(socketFD, response + totalBytesReceived, expectedSize - totalBytesReceived);
|
||||
if (bytesReceived <= 0) { // Connection lost or no data received
|
||||
printf("MODBUS_TCP_CLIENT: Connection lost. Disconnecting...\n");
|
||||
disconnectServer(); // Close socket and reset socketFD
|
||||
return false;
|
||||
}
|
||||
|
||||
totalBytesReceived += bytesReceived;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModbusTCPClient::buildReadRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t startAddr, uint16_t quantity) {
|
||||
transactionID++;
|
||||
|
||||
// Transaction ID
|
||||
buffer[0] = transactionID >> 8;
|
||||
buffer[1] = transactionID & 0xFF;
|
||||
// Protocol ID, always 00 00
|
||||
buffer[2] = 0x00;
|
||||
buffer[3] = 0x00;
|
||||
// Length (remaining bytes after Unit ID)
|
||||
buffer[4] = 0x00;
|
||||
buffer[5] = 0x06;
|
||||
// Unit ID (Slave Address)
|
||||
buffer[6] = 0x01;
|
||||
// Function code
|
||||
buffer[7] = static_cast<uint8_t>(functionCode);
|
||||
// Start Address
|
||||
buffer[8] = startAddr >> 8;
|
||||
buffer[9] = startAddr & 0xFF;
|
||||
// Quantity (How many coils to read)
|
||||
buffer[10] = quantity >> 8;
|
||||
buffer[11] = quantity & 0xFF;
|
||||
}
|
||||
|
||||
void ModbusTCPClient::buildWriteSingleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t value) {
|
||||
transactionID++;
|
||||
|
||||
buffer[0] = transactionID >> 8;
|
||||
buffer[1] = transactionID & 0xFF;
|
||||
buffer[2] = 0x00;
|
||||
buffer[3] = 0x00;
|
||||
buffer[4] = 0x00;
|
||||
buffer[5] = 0x06;
|
||||
buffer[6] = 0x01;
|
||||
buffer[7] = static_cast<uint8_t>(functionCode);
|
||||
buffer[8] = address >> 8;
|
||||
buffer[9] = address & 0xFF;
|
||||
buffer[10] = value >> 8;
|
||||
buffer[11] = value & 0xFF;
|
||||
}
|
||||
|
||||
void ModbusTCPClient::buildWriteMultipleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t count, const void* values, uint8_t byteCount) {
|
||||
transactionID++;
|
||||
|
||||
// MODBUS TCP Header
|
||||
buffer[0] = transactionID >> 8;
|
||||
buffer[1] = transactionID & 0xFF;
|
||||
buffer[2] = 0x00; // Protocol ID (always 0x0000)
|
||||
buffer[3] = 0x00;
|
||||
buffer[4] = 0x00; // Length (remaining bytes after Unit ID)
|
||||
buffer[5] = 7 + byteCount;
|
||||
buffer[6] = 0x01; // Unit ID
|
||||
buffer[7] = static_cast<uint8_t>(functionCode); // Function Code (0x0F for coils, 0x10 for registers)
|
||||
buffer[8] = address >> 8; // Start address high byte
|
||||
buffer[9] = address & 0xFF; // Start address low byte
|
||||
buffer[10] = count >> 8; // Quantity high byte
|
||||
buffer[11] = count & 0xFF; // Quantity low byte
|
||||
buffer[12] = byteCount; // Byte count
|
||||
|
||||
// Copy data payload manually (instead of memcpy)
|
||||
const uint8_t* data = (const uint8_t*)values;
|
||||
for (uint8_t i = 0; i < byteCount; i++) {
|
||||
buffer[13 + i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readCoil(int address, bool &coilState) {
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_COIL, address, 1);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
uint8_t response[10]; // Expecting 10 bytes
|
||||
if (!receiveResponse(response, 10)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure function code matches the request (allowing for server behavior)
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_COIL), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Extract coil state (only first bit is used)
|
||||
coilState = (response[9] & 0x01) != 0; // Adjusted index based on 10-byte response
|
||||
return ModbusError::NONE;
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readMultipleCoils(int address, int count, bool coilStates[]) {
|
||||
if (count < 1 || count > 2000) {
|
||||
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-2000 allowed)\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_COIL, address, count);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
// Expected response size: Fixed header (9) + variable byte count
|
||||
int byteCount = (count + 7) / 8; // 1 byte per 8 coils
|
||||
int expectedSize = 9 + byteCount;
|
||||
|
||||
uint8_t response[256]; // Ensure buffer is large enough
|
||||
if (!receiveResponse(response, expectedSize)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure the function code matches
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_COIL)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_COIL), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Read coil values
|
||||
for (int i = 0; i < count; i++) {
|
||||
int byteIndex = 9 + (i / 8); // Data starts at index 9
|
||||
int bitIndex = i % 8;
|
||||
coilStates[i] = (response[byteIndex] >> bitIndex) & 0x01;
|
||||
}
|
||||
|
||||
return ModbusError::NONE;
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readDiscreteInput(int address, bool &discreteInput) {
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_DISCRETE_INPUT, address, 1);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
uint8_t response[10]; // Expected response size
|
||||
if (!receiveResponse(response, 10)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure function code matches the request
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Extract single discrete input state
|
||||
discreteInput = (response[9] & 0x01) != 0;
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readMultipleDiscreteInputs(int address, int count, bool discreteInputs[]) {
|
||||
if (count < 1 || count > 2000) {
|
||||
printf("MODBUS_TCP_CLIENT: Invalid discrete input count (1-2000 allowed)\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_DISCRETE_INPUT, address, count);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
// Expected response size: Fixed header (9) + variable byte count
|
||||
int byteCount = (count + 7) / 8; // 1 byte per 8 inputs
|
||||
int expectedSize = 9 + byteCount;
|
||||
|
||||
uint8_t response[256]; // Ensure buffer is large enough
|
||||
if (!receiveResponse(response, expectedSize)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure the function code matches
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_DISCRETE_INPUT), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Read discrete input values
|
||||
for (int i = 0; i < count; i++) {
|
||||
int byteIndex = 9 + (i / 8); // Data starts at index 9
|
||||
int bitIndex = i % 8;
|
||||
discreteInputs[i] = (response[byteIndex] >> bitIndex) & 0x01;
|
||||
}
|
||||
|
||||
return ModbusError::NONE;
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readHoldingRegister(int address, uint16_t &holdingRegister) {
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_HOLDING_REGISTER, address, 1);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
uint8_t response[11]; // Expected response size for reading 1 register
|
||||
if (!receiveResponse(response, 11)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure function code matches the request
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Extract holding register value (Big-endian format)
|
||||
holdingRegister = (response[9] << 8) | response[10];
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readMultipleHoldingRegisters(int address, int count, uint16_t holdingRegisters[]) {
|
||||
if (count < 1 || count > 125) { // MODBUS limits reading up to 125 registers per request
|
||||
printf("MODBUS_TCP_CLIENT: Invalid holding register count (1-125 allowed)\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_HOLDING_REGISTER, address, count);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
// Expected response size: 9-byte header + 2 * count registers
|
||||
int expectedSize = 9 + (count * 2);
|
||||
uint8_t response[256]; // Ensure buffer is large enough
|
||||
|
||||
if (!receiveResponse(response, expectedSize)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure function code matches the request
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_HOLDING_REGISTER), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Extract register values (each register is 2 bytes, big-endian)
|
||||
for (int i = 0; i < count; i++) {
|
||||
holdingRegisters[i] = (response[9 + (i * 2)] << 8) | response[10 + (i * 2)];
|
||||
}
|
||||
|
||||
return ModbusError::NONE;
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readInputRegister(int address, uint16_t &inputRegister) {
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_INPUT_REGISTER, address, 1);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
uint8_t response[11]; // Expected response size for reading 1 register
|
||||
if (!receiveResponse(response, 11)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure function code matches the request
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Extract input register value (Big-endian format)
|
||||
inputRegister = (response[9] << 8) | response[10];
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readMultipleInputRegisters(int address, int count, uint16_t inputRegisters[]) {
|
||||
if (count < 1 || count > 125) { // MODBUS limits reading up to 125 registers per request
|
||||
printf("MODBUS_TCP_CLIENT: Invalid input register count (1-125 allowed)\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
uint8_t request[12];
|
||||
buildReadRequest(request, ModbusFunction::READ_INPUT_REGISTER, address, count);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
// Expected response size: 9-byte header + 2 * count registers
|
||||
int expectedSize = 9 + (count * 2);
|
||||
uint8_t response[256]; // Ensure buffer is large enough
|
||||
|
||||
if (!receiveResponse(response, expectedSize)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Handle MODBUS exception responses (0x80 + function code)
|
||||
if (response[7] & 0x80) {
|
||||
printf("MODBUS_TCP_CLIENT: MODBUS Exception Code %02X\n", response[8]);
|
||||
return ModbusError::EXCEPTION_RESPONSE;
|
||||
}
|
||||
|
||||
// Ensure function code matches the request
|
||||
if (response[7] != static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER)) {
|
||||
printf("MODBUS_TCP_CLIENT: Warning: Unexpected function code (Expected: %02X, Got: %02X)\n",
|
||||
static_cast<uint8_t>(ModbusFunction::READ_INPUT_REGISTER), response[7]);
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
// Extract register values (each register is 2 bytes, big-endian)
|
||||
for (int i = 0; i < count; i++) {
|
||||
inputRegisters[i] = (response[9 + (i * 2)] << 8) | response[10 + (i * 2)];
|
||||
}
|
||||
|
||||
return ModbusError::NONE;
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::writeCoil(int address, bool value) {
|
||||
uint8_t request[12];
|
||||
buildWriteSingleRequest(request, ModbusFunction::WRITE_SINGLE_COIL, address, value ? 0xFF00 : 0x0000);
|
||||
sendRequest(request, 12);
|
||||
|
||||
// Receive response
|
||||
uint8_t response[12];
|
||||
if (!receiveResponse(response, 12)) {
|
||||
return ModbusError::TIMEOUT; // No response received
|
||||
}
|
||||
|
||||
// Check if response matches request (MODBUS TCP should echo back the same request)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (request[i] != response[i]) {
|
||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::writeMultipleCoils(int address, int count, const bool values[]) {
|
||||
if (count < 1 || count > 1968) { // MODBUS limit: max 1968 coils per request
|
||||
printf("MODBUS_TCP_CLIENT: Invalid coil count (1-1968 allowed)\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
int byteCount = (count + 7) / 8; // Each byte holds 8 coils
|
||||
uint8_t coilData[byteCount];
|
||||
|
||||
// Initialize to 0 (since we may not use all bits)
|
||||
for (int i = 0; i < byteCount; i++) {
|
||||
coilData[i] = 0;
|
||||
}
|
||||
|
||||
// Pack coil data into bytes
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (values[i]) {
|
||||
coilData[i / 8] |= (1 << (i % 8));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t request[13 + byteCount];
|
||||
buildWriteMultipleRequest(request, ModbusFunction::WRITE_MULTIPLE_COILS, address, count, coilData, byteCount);
|
||||
|
||||
sendRequest(request, 13 + byteCount);
|
||||
|
||||
// The expected response is always **12 bytes**
|
||||
uint8_t response[12];
|
||||
if (!receiveResponse(response, 12)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Ensure the response matches the **first 10 bytes**, except for byte 5 (message length byte)
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (i == 5) continue; // Skip byte 5 (message length field)
|
||||
|
||||
if (request[i] != response[i]) {
|
||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::writeHoldingRegister(int address, uint16_t value) {
|
||||
uint8_t request[12];
|
||||
buildWriteSingleRequest(request, ModbusFunction::WRITE_SINGLE_HOLDING_REGISTER, address, value);
|
||||
|
||||
sendRequest(request, 12);
|
||||
|
||||
// Expected response size = 12 bytes (full echo of the request)
|
||||
uint8_t response[12];
|
||||
if (!receiveResponse(response, 12)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Ensure response matches request exactly (full 12 bytes)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (request[i] != response[i]) {
|
||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]) {
|
||||
if (count < 1 || count > 123) { // MODBUS limit: max 123 registers per request
|
||||
printf("MODBUS_TCP_CLIENT: Invalid register count (1-123 allowed)\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
int byteCount = count * 2; // Each register is 2 bytes
|
||||
uint8_t registerData[byteCount];
|
||||
|
||||
// Convert register values to byte array (big-endian format)
|
||||
for (int i = 0; i < count; i++) {
|
||||
registerData[i * 2] = values[i] >> 8; // High byte
|
||||
registerData[i * 2 + 1] = values[i] & 0xFF; // Low byte
|
||||
}
|
||||
|
||||
uint8_t request[13 + byteCount];
|
||||
buildWriteMultipleRequest(request, ModbusFunction::WRITE_MULTIPLE_HOLDING_REGISTERS, address, count, registerData, byteCount);
|
||||
|
||||
sendRequest(request, 13 + byteCount);
|
||||
|
||||
// Expected response size = 12 bytes (first 10 bytes + 2 bytes for number of registers written)
|
||||
uint8_t response[12];
|
||||
if (!receiveResponse(response, 12)) {
|
||||
return ModbusError::TIMEOUT;
|
||||
}
|
||||
|
||||
// Ensure response matches request (except for byte 5)
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (i == 5) continue; // Skip byte 5 (message length field)
|
||||
|
||||
if (request[i] != response[i]) {
|
||||
printf("MODBUS_TCP_CLIENT: Response does not match request!\n");
|
||||
return ModbusError::INVALID_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ModbusError::NONE; // Success
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::readAll() {
|
||||
/*
|
||||
Reads every coil, discrete input, input register, and holding register
|
||||
assuming that they start at address 0
|
||||
*/
|
||||
|
||||
if (coilsRead == nullptr && discreteInputs == nullptr &&
|
||||
inputRegisters == nullptr && holdingRegistersRead == nullptr) {
|
||||
printf("MODBUS_TCP_CLIENT: readAll() called, but wrong constructor was used.\n");
|
||||
return ModbusError::INVALID_REQUEST;
|
||||
}
|
||||
|
||||
ModbusError error = ModbusError::NONE;
|
||||
if (coilsRead != nullptr) {
|
||||
error = readMultipleCoils(startCoils, numCoils, coilsRead);
|
||||
if (error != ModbusError::NONE) return error;
|
||||
}
|
||||
|
||||
if (discreteInputs != nullptr) {
|
||||
error = readMultipleDiscreteInputs(startDiscreteInputs, numDiscreteInputs, discreteInputs);
|
||||
if (error != ModbusError::NONE) return error;
|
||||
}
|
||||
|
||||
if (inputRegisters != nullptr) {
|
||||
error = readMultipleInputRegisters(startInputRegisters, numInputRegisters, inputRegisters);
|
||||
if (error != ModbusError::NONE) return error;
|
||||
}
|
||||
|
||||
if (holdingRegistersRead != nullptr) {
|
||||
error = readMultipleHoldingRegisters(startHoldingRegisters, numHoldingRegisters, holdingRegistersRead);
|
||||
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
ModbusError ModbusTCPClient::writeAll() {
|
||||
/*
|
||||
Reads every coil and holding register assuming that they start at address 0
|
||||
*/
|
||||
if (coilsWrite == nullptr && holdingRegistersWrite) {
|
||||
printf("MODBUS_TCP_CLIENT: writeAll() called, but wrong constructor was used.\n");
|
||||
return ModbusError::INVALID_REQUEST;
|
||||
}
|
||||
|
||||
ModbusError error = ModbusError::NONE;
|
||||
if (coilsWrite != nullptr) {
|
||||
error = writeMultipleCoils(startCoils, numCoils, coilsWrite);
|
||||
if (error != ModbusError::NONE) return error;
|
||||
}
|
||||
|
||||
if (holdingRegistersWrite != nullptr) {
|
||||
error = writeMultipleHoldingRegisters(startHoldingRegisters, numHoldingRegisters, holdingRegistersWrite);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// Setters for writing values (preferred to be used)
|
||||
void ModbusTCPClient::setCoil(int address, bool value) {
|
||||
if (address >= 0 && address < numCoils) {
|
||||
coilsWrite[address] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void ModbusTCPClient::setHoldingRegister(int address, uint16_t value) {
|
||||
if (address >= 0 && address < numHoldingRegisters) {
|
||||
holdingRegistersWrite[address] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Getters (preferred to be used as long as readAll is being called)
|
||||
bool ModbusTCPClient::getCoil(int address) const {
|
||||
return (address >= 0 && address < numCoils) ? coilsRead[address] : false;
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::getDesiredCoil(int address) const {
|
||||
return (address >= 0 && address < numCoils) ? coilsWrite[address] : false;
|
||||
}
|
||||
|
||||
bool ModbusTCPClient::getDiscreteInput(int address) const {
|
||||
return (address >= 0 && address < numDiscreteInputs) ? discreteInputs[address] : false;
|
||||
}
|
||||
|
||||
uint16_t ModbusTCPClient::getHoldingRegister(int address) const {
|
||||
return (address >= 0 && address < numHoldingRegisters) ? holdingRegistersRead[address] : 0;
|
||||
}
|
||||
|
||||
uint16_t ModbusTCPClient::getDesiredHoldingRegister(int address) const {
|
||||
return (address >= 0 && address < numHoldingRegisters) ? holdingRegistersWrite[address] : 0;
|
||||
}
|
||||
|
||||
uint16_t ModbusTCPClient::getInputRegister(int address) const {
|
||||
return (address >= 0 && address < numInputRegisters) ? inputRegisters[address] : 0;
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
#ifndef MODBUS_TCP_CLIENT_H
|
||||
#define MODBUS_TCP_CLIENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
// Enum class for MODBUS function codes
|
||||
enum class ModbusFunction : uint8_t {
|
||||
READ_COIL = 0x01,
|
||||
READ_DISCRETE_INPUT = 0x02,
|
||||
READ_HOLDING_REGISTER = 0x03,
|
||||
READ_INPUT_REGISTER = 0x04,
|
||||
WRITE_SINGLE_COIL = 0x05,
|
||||
WRITE_SINGLE_HOLDING_REGISTER = 0x06,
|
||||
WRITE_MULTIPLE_COILS = 0x0F,
|
||||
WRITE_MULTIPLE_HOLDING_REGISTERS = 0x10
|
||||
};
|
||||
|
||||
enum class ModbusError {
|
||||
NONE = 0, // No error
|
||||
TIMEOUT, // No response from server
|
||||
INVALID_RESPONSE, // Response does not match request
|
||||
CONNECTION_LOST, // Connection issue
|
||||
EXCEPTION_RESPONSE, // MODBUS Exception response (error code)
|
||||
INVALID_REQUEST, // User tries doing something they shouldn't
|
||||
};
|
||||
|
||||
|
||||
class ModbusTCPClient {
|
||||
public:
|
||||
ModbusTCPClient(const char* ip, int port); // Extra constructor that CANNOT use readAll() or writeAll()
|
||||
ModbusTCPClient(const char* ip, int port, int numCoils, int numDI, int numIR, int numHR,
|
||||
int startCoils = 0, int startDI = 0, int startIR = 0, int startHR = 0);
|
||||
|
||||
~ModbusTCPClient();
|
||||
|
||||
// Set the start address of each type. Either use this after creating the object or put them in the constructor
|
||||
void setStartAddresses(int startCoils, int startDI, int startIR, int startHR);
|
||||
|
||||
bool connectServer();
|
||||
void disconnectServer();
|
||||
bool isConnected() const;
|
||||
|
||||
// Manually disconnectServer and return reconnectServer()
|
||||
bool reconnectServer();
|
||||
|
||||
// Set the timeout for receiving responses
|
||||
void setTimeout(int milliseconds);
|
||||
|
||||
// Setters (preferred to be used when calling writeAll())
|
||||
void setCoil(int address, bool value);
|
||||
void setHoldingRegister(int address, uint16_t value);
|
||||
|
||||
// Getters (preferred to be used when calling readAll())
|
||||
bool getCoil(int address) const;
|
||||
bool getDesiredCoil(int address) const; // Retrieves the "to be written" value
|
||||
bool getDiscreteInput(int address) const;
|
||||
uint16_t getHoldingRegister(int address) const;
|
||||
uint16_t getDesiredHoldingRegister(int address) const; // Retrieves the "to be written" value
|
||||
uint16_t getInputRegister(int address) const;
|
||||
|
||||
ModbusError readAll(); // Reads every coil, DI, IR, and HR
|
||||
ModbusError writeAll(); // Writes every coil and HR
|
||||
|
||||
// Manual MODBUS TCP actions (not preferred to be called by user)
|
||||
ModbusError readCoil(int address, bool &coilState);
|
||||
ModbusError readMultipleCoils(int address, int count, bool coilStates[]);
|
||||
|
||||
ModbusError readDiscreteInput(int address, bool &discreteInput);
|
||||
ModbusError readMultipleDiscreteInputs(int address, int count, bool discreteInputs[]);
|
||||
|
||||
ModbusError readHoldingRegister(int address, uint16_t &holdingRegister);
|
||||
ModbusError readMultipleHoldingRegisters(int address, int count, uint16_t holdingRegisters[]);
|
||||
|
||||
ModbusError readInputRegister(int address, uint16_t &inputRegister);
|
||||
ModbusError readMultipleInputRegisters(int address, int count, uint16_t inputRegisters[]);
|
||||
|
||||
ModbusError writeCoil(int address, bool value);
|
||||
ModbusError writeMultipleCoils(int address, int count, const bool values[]);
|
||||
|
||||
ModbusError writeHoldingRegister(int address, uint16_t value);
|
||||
ModbusError writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]);
|
||||
|
||||
private:
|
||||
// TCP settings
|
||||
const char* serverIP;
|
||||
int serverPort;
|
||||
int socketFD;
|
||||
uint16_t transactionID;
|
||||
int timeoutMilliseconds = 2000; // Default 2 second timeout on receiving responses
|
||||
|
||||
// Storing MODBUS register information
|
||||
int numCoils, numDiscreteInputs, numInputRegisters, numHoldingRegisters;
|
||||
int startCoils, startDiscreteInputs, startInputRegisters, startHoldingRegisters; // The start address of each type of register
|
||||
|
||||
bool* coilsRead; // Stores the actual state of coils on the MODBUS server
|
||||
bool* coilsWrite; // Stores the desired state of coils to be written
|
||||
bool* discreteInputs; // Only read from the MODBUS server (no writes)
|
||||
|
||||
uint16_t* inputRegisters; // Only read from the MODBUS server
|
||||
uint16_t* holdingRegistersRead; // Stores actual values from the MODBUS server
|
||||
uint16_t* holdingRegistersWrite; // Stores desired values to write
|
||||
|
||||
bool sendRequest(uint8_t* request, int requestSize);
|
||||
bool receiveResponse(uint8_t* response, int expectedSize);
|
||||
|
||||
void buildReadRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t startAddr, uint16_t quantity);
|
||||
void buildWriteSingleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t value);
|
||||
void buildWriteMultipleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t count, const void* values, uint8_t byteCount);
|
||||
};
|
||||
|
||||
#endif // MODBUS_TCP_CLIENT_H
|
||||
Binary file not shown.
@ -0,0 +1,46 @@
|
||||
#ifndef __customcode_jkx3iHsM9OOrSN3xw6c8aB_h__
|
||||
#define __customcode_jkx3iHsM9OOrSN3xw6c8aB_h__
|
||||
|
||||
/* Include files */
|
||||
#include "mex.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "tmwtypes.h"
|
||||
|
||||
|
||||
/* Helper definitions for DLL support */
|
||||
#if defined _WIN32
|
||||
#define DLL_EXPORT_CC __declspec(dllexport)
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define DLL_EXPORT_CC __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define DLL_EXPORT_CC
|
||||
#endif
|
||||
#endif
|
||||
/* Custom Code from Simulation Target dialog */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "modbus_tcp_client.h"
|
||||
|
||||
|
||||
/* Function Declarations */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#define customcode_jkx3iHsM9OOrSN3xw6c8aB_initializer()
|
||||
|
||||
#define customcode_jkx3iHsM9OOrSN3xw6c8aB_terminator()
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,283 @@
|
||||
#ifndef MULTIWORD_TYPES_H
|
||||
#define MULTIWORD_TYPES_H
|
||||
#include "rtwtypes.h"
|
||||
|
||||
/*
|
||||
* MultiWord supporting definitions
|
||||
*/
|
||||
typedef long long longlong_T;
|
||||
|
||||
/*
|
||||
* MultiWord types
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_T chunks[2];
|
||||
} int128m_T;
|
||||
|
||||
typedef struct {
|
||||
int128m_T re;
|
||||
int128m_T im;
|
||||
} cint128m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[2];
|
||||
} uint128m_T;
|
||||
|
||||
typedef struct {
|
||||
uint128m_T re;
|
||||
uint128m_T im;
|
||||
} cuint128m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[3];
|
||||
} int192m_T;
|
||||
|
||||
typedef struct {
|
||||
int192m_T re;
|
||||
int192m_T im;
|
||||
} cint192m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[3];
|
||||
} uint192m_T;
|
||||
|
||||
typedef struct {
|
||||
uint192m_T re;
|
||||
uint192m_T im;
|
||||
} cuint192m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[4];
|
||||
} int256m_T;
|
||||
|
||||
typedef struct {
|
||||
int256m_T re;
|
||||
int256m_T im;
|
||||
} cint256m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[4];
|
||||
} uint256m_T;
|
||||
|
||||
typedef struct {
|
||||
uint256m_T re;
|
||||
uint256m_T im;
|
||||
} cuint256m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[5];
|
||||
} int320m_T;
|
||||
|
||||
typedef struct {
|
||||
int320m_T re;
|
||||
int320m_T im;
|
||||
} cint320m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[5];
|
||||
} uint320m_T;
|
||||
|
||||
typedef struct {
|
||||
uint320m_T re;
|
||||
uint320m_T im;
|
||||
} cuint320m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[6];
|
||||
} int384m_T;
|
||||
|
||||
typedef struct {
|
||||
int384m_T re;
|
||||
int384m_T im;
|
||||
} cint384m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[6];
|
||||
} uint384m_T;
|
||||
|
||||
typedef struct {
|
||||
uint384m_T re;
|
||||
uint384m_T im;
|
||||
} cuint384m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[7];
|
||||
} int448m_T;
|
||||
|
||||
typedef struct {
|
||||
int448m_T re;
|
||||
int448m_T im;
|
||||
} cint448m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[7];
|
||||
} uint448m_T;
|
||||
|
||||
typedef struct {
|
||||
uint448m_T re;
|
||||
uint448m_T im;
|
||||
} cuint448m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[8];
|
||||
} int512m_T;
|
||||
|
||||
typedef struct {
|
||||
int512m_T re;
|
||||
int512m_T im;
|
||||
} cint512m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[8];
|
||||
} uint512m_T;
|
||||
|
||||
typedef struct {
|
||||
uint512m_T re;
|
||||
uint512m_T im;
|
||||
} cuint512m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[9];
|
||||
} int576m_T;
|
||||
|
||||
typedef struct {
|
||||
int576m_T re;
|
||||
int576m_T im;
|
||||
} cint576m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[9];
|
||||
} uint576m_T;
|
||||
|
||||
typedef struct {
|
||||
uint576m_T re;
|
||||
uint576m_T im;
|
||||
} cuint576m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[10];
|
||||
} int640m_T;
|
||||
|
||||
typedef struct {
|
||||
int640m_T re;
|
||||
int640m_T im;
|
||||
} cint640m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[10];
|
||||
} uint640m_T;
|
||||
|
||||
typedef struct {
|
||||
uint640m_T re;
|
||||
uint640m_T im;
|
||||
} cuint640m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[11];
|
||||
} int704m_T;
|
||||
|
||||
typedef struct {
|
||||
int704m_T re;
|
||||
int704m_T im;
|
||||
} cint704m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[11];
|
||||
} uint704m_T;
|
||||
|
||||
typedef struct {
|
||||
uint704m_T re;
|
||||
uint704m_T im;
|
||||
} cuint704m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[12];
|
||||
} int768m_T;
|
||||
|
||||
typedef struct {
|
||||
int768m_T re;
|
||||
int768m_T im;
|
||||
} cint768m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[12];
|
||||
} uint768m_T;
|
||||
|
||||
typedef struct {
|
||||
uint768m_T re;
|
||||
uint768m_T im;
|
||||
} cuint768m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[13];
|
||||
} int832m_T;
|
||||
|
||||
typedef struct {
|
||||
int832m_T re;
|
||||
int832m_T im;
|
||||
} cint832m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[13];
|
||||
} uint832m_T;
|
||||
|
||||
typedef struct {
|
||||
uint832m_T re;
|
||||
uint832m_T im;
|
||||
} cuint832m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[14];
|
||||
} int896m_T;
|
||||
|
||||
typedef struct {
|
||||
int896m_T re;
|
||||
int896m_T im;
|
||||
} cint896m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[14];
|
||||
} uint896m_T;
|
||||
|
||||
typedef struct {
|
||||
uint896m_T re;
|
||||
uint896m_T im;
|
||||
} cuint896m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[15];
|
||||
} int960m_T;
|
||||
|
||||
typedef struct {
|
||||
int960m_T re;
|
||||
int960m_T im;
|
||||
} cint960m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[15];
|
||||
} uint960m_T;
|
||||
|
||||
typedef struct {
|
||||
uint960m_T re;
|
||||
uint960m_T im;
|
||||
} cuint960m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[16];
|
||||
} int1024m_T;
|
||||
|
||||
typedef struct {
|
||||
int1024m_T re;
|
||||
int1024m_T im;
|
||||
} cint1024m_T;
|
||||
|
||||
typedef struct {
|
||||
uint64_T chunks[16];
|
||||
} uint1024m_T;
|
||||
|
||||
typedef struct {
|
||||
uint1024m_T re;
|
||||
uint1024m_T im;
|
||||
} cuint1024m_T;
|
||||
|
||||
#endif /* MULTIWORD_TYPES_H */
|
||||
Binary file not shown.
@ -0,0 +1,61 @@
|
||||
#ifndef RTWTYPES_H
|
||||
#define RTWTYPES_H
|
||||
#include "tmwtypes.h"
|
||||
#ifndef POINTER_T
|
||||
#define POINTER_T
|
||||
|
||||
typedef void * pointer_T;
|
||||
|
||||
#endif
|
||||
|
||||
/* Logical type definitions */
|
||||
#if (!defined(__cplusplus))
|
||||
#ifndef false
|
||||
#define false (0U)
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true (1U)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT64_T
|
||||
#define INT64_T
|
||||
|
||||
typedef long int64_T;
|
||||
|
||||
#define MAX_int64_T ((int64_T)(9223372036854775807L))
|
||||
#define MIN_int64_T ((int64_T)(-9223372036854775807L-1L))
|
||||
#endif
|
||||
|
||||
#ifndef UINT64_T
|
||||
#define UINT64_T
|
||||
|
||||
typedef unsigned long uint64_T;
|
||||
|
||||
#define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFUL))
|
||||
#endif
|
||||
|
||||
/*===========================================================================*
|
||||
* Additional complex number type definitions *
|
||||
*===========================================================================*/
|
||||
#ifndef CINT64_T
|
||||
#define CINT64_T
|
||||
|
||||
typedef struct {
|
||||
int64_T re;
|
||||
int64_T im;
|
||||
} cint64_T;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CUINT64_T
|
||||
#define CUINT64_T
|
||||
|
||||
typedef struct {
|
||||
uint64_T re;
|
||||
uint64_T im;
|
||||
} cuint64_T;
|
||||
|
||||
#endif
|
||||
#endif /* RTWTYPES_H */
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
#include "customcode_jkx3iHsM9OOrSN3xw6c8aB.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Type Definitions */
|
||||
|
||||
/* Named Constants */
|
||||
|
||||
/* Variable Declarations */
|
||||
|
||||
/* Variable Definitions */
|
||||
|
||||
/* Function Declarations */
|
||||
DLL_EXPORT_CC extern const char_T *get_dll_checksum_jkx3iHsM9OOrSN3xw6c8aB();
|
||||
DLL_EXPORT_CC extern void *create_ModbusTCPClient_DTOtnS5jzeCt7wI4BrWszE_jkx3iHsM9OOrSN3xw6c8aB(const char_T *ip, int32_T port, int32_T numCoils, int32_T numDI, int32_T numIR, int32_T numHR, int32_T startCoils, int32_T startDI, int32_T startIR, int32_T startHR);
|
||||
DLL_EXPORT_CC extern void *create_ModbusTCPClient_m6DHLsRJatb7jFhPa9sibF_jkx3iHsM9OOrSN3xw6c8aB(const char_T *ip, int32_T port);
|
||||
DLL_EXPORT_CC extern void delete_ModbusTCPClient_IUI8Q2S0ulkAvLxLsx7k7_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern void ModbusTCPClient_setStartAddresses_WBPKyX5chtvoJpkQQz9yaE_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T startCoils, int32_T startDI, int32_T startIR, int32_T startHR);
|
||||
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_connectServer_QWoAn8DsWluHwos1RJjgIB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern void ModbusTCPClient_disconnectServer_8RQB4Kyl2X5kNVGUlAlOgF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_isConnected_6gPjpu9NwavTxFjRzBfnHH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_reconnectServer_tmHQpYOBqsG4QOWlcN1JCG_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern void ModbusTCPClient_setTimeout_pKk7C4CiK7cGunjmXsoo9G_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T milliseconds);
|
||||
DLL_EXPORT_CC extern void ModbusTCPClient_setCoil_uKV63H2F6Bk5GhMpqdzPnH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T value);
|
||||
DLL_EXPORT_CC extern void ModbusTCPClient_setHoldingRegister_4XFxsavHXRTDHK2Ce0yJN_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T value);
|
||||
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_getCoil_koLGZb1i8WN62u3e1PZwYH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_getDesiredCoil_4MZCcH6ezDGZg0uObXZUCC_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||
DLL_EXPORT_CC extern boolean_T ModbusTCPClient_getDiscreteInput_ae9HPljrPWD4BuZzmFBLEH_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||
DLL_EXPORT_CC extern uint16_T ModbusTCPClient_getHoldingRegister_mYLPn0wppPgH4bOhTiVvvF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||
DLL_EXPORT_CC extern uint16_T ModbusTCPClient_getDesiredHoldingRegister_15FbNf22xvcBTZOmdfDtkC_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||
DLL_EXPORT_CC extern uint16_T ModbusTCPClient_getInputRegister_ULtxwrYKJbrRxoQjkBCEs_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_getMultipleHoldingRegisters_dolsLHExIVVRdXIf6qYZmF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T startAddress, int32_T count, uint16_T *destination);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readAll_0LzP2HH0Zq4XkTmFCbG4o_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeAll_zaImFzR1o00mWpc4RczmN_jkx3iHsM9OOrSN3xw6c8aB(void *classObj);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readCoil_zMFMzEaWMy4AM0fCGw6vkB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T *coilState);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleCoils_FsHZsYjrSrPY8P2Ay58lEB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, boolean_T *coilStates);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readDiscreteInput_hw3i2qSdn19YvGoOIzPSQF_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T *discreteInput);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleDiscreteInputs_ejm6F8zFfmummwJiWr5WWE_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, boolean_T *discreteInputs);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readHoldingRegister_6gyuCNdZQDr6LxODE49ARC_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T *holdingRegister);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleHoldingRegisters_Nsd2PmYkYCsTdyTlOKb0KB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, uint16_T *holdingRegisters);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readInputRegister_LiIzv9TV0ONDt8VfLmy35G_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T *inputRegister);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_readMultipleInputRegisters_two67DgbwFGoO6KyFi3I5B_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, uint16_T *inputRegisters);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeCoil_QoP3Zii3RZpABaPcesHRiB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, boolean_T value);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeMultipleCoils_p5zcgcGPFH7wlbBhce5JYG_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, const boolean_T *values);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeHoldingRegister_mGVMywqtoVY5ZLnrtEy19G_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, uint16_T value);
|
||||
DLL_EXPORT_CC extern ModbusError ModbusTCPClient_writeMultipleHoldingRegisters_ga2jca071NX41GYGjHLKzB_jkx3iHsM9OOrSN3xw6c8aB(void *classObj, int32_T address, int32_T count, const uint16_T *values);
|
||||
|
||||
/* Function Definitions */
|
||||
DLL_EXPORT_CC const uint8_T *get_checksum_source_info(int32_T *size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>{"Inports":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Outports":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","ParameterArguments":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","LocalParameters":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","GlobalParameters":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","InternalData":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","SharedLocalDataStores":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","GlobalDataStores":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Constants":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","DataTransfers":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","ModelData":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","InitializeTerminate":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","Execution":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}","SharedUtility":"{\"Name\":\"Default\",\"Checksum\":\"Default\",\"PerInstancePropertiesChecksum\":\"\",\"MemorySectionName\":\"None\",\"MemorySectionChecksum\":\"None\"}"}</defaultsCMapping>
|
||||
<fastestNoncontSigFeedingDerivPorts>-1.0</fastestNoncontSigFeedingDerivPorts>
|
||||
<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><?xml version="1.0"?>
|
||||
<slexec_sto version="1.1" packageUris="http://schema.mathworks.com/mf0/slexec_mm_sto/R2024a_202305081229">
|
||||
<sto.Registry type="sto.Registry" uuid="ee73db1b-f182-40a7-b4b2-32cb5a9d4db8">
|
||||
<sto.Registry type="sto.Registry" uuid="9f787942-3fbf-40bf-83d9-ca31d2944761">
|
||||
<executionSpec>Undetermined</executionSpec>
|
||||
<identifier>uORB_MODBUS_TCP</identifier>
|
||||
<clockRegistry type="sto.ClockRegistry" uuid="ec9112c3-f7df-4d70-9e32-e8deed783d4b">
|
||||
<clocks type="sto.Timer" uuid="2d74743a-7fa6-484f-840f-02b24087f560">
|
||||
<computedFundamentalDiscretePeriod>5.0</computedFundamentalDiscretePeriod>
|
||||
<fastestDiscreteRate type="sto.ClassicPeriodicDiscreteRate" uuid="29f1da5c-2a35-48ef-a7fe-a82629440e39"/>
|
||||
<clockRegistry type="sto.ClockRegistry" uuid="e3adf32f-9edb-41d2-8d65-2aa99a600d7d">
|
||||
<clocks type="sto.Timer" uuid="3a0b736d-652a-409a-b254-5d476adf58b2">
|
||||
<computedFundamentalDiscretePeriod>.25</computedFundamentalDiscretePeriod>
|
||||
<fastestDiscreteRate type="sto.ClassicPeriodicDiscreteRate" uuid="ba617304-1665-47a9-8567-cc2b033188ef"/>
|
||||
<isDefaultTimer>true</isDefaultTimer>
|
||||
<resolution>5.0</resolution>
|
||||
<resolution>.25</resolution>
|
||||
<timeAdvanceMode>FixedStep</timeAdvanceMode>
|
||||
<identifier>uORB_MODBUS_TCP::defaultTimer</identifier>
|
||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="29f1da5c-2a35-48ef-a7fe-a82629440e39">
|
||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="ba617304-1665-47a9-8567-cc2b033188ef">
|
||||
<annotation>D1</annotation>
|
||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||
<description>Discrete 1</description>
|
||||
<taskId>_task0</taskId>
|
||||
<rateSpec type="sto.RateSpec" uuid="1368f082-b58c-4c67-b97a-0fb3024453e7">
|
||||
<rateSpec type="sto.RateSpec" uuid="26cde9ad-fd89-4996-b202-d4b6c44daffc">
|
||||
<period>.25</period>
|
||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||
</rateSpec>
|
||||
</rates>
|
||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="6f6b4dea-ac0b-4961-855e-736959b539d1">
|
||||
<annotation>D2</annotation>
|
||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||
<colorIndex>1</colorIndex>
|
||||
<description>Discrete 2</description>
|
||||
<rateIdx>1</rateIdx>
|
||||
<taskId>_task1</taskId>
|
||||
<rateSpec type="sto.RateSpec" uuid="f257fe37-2af7-417a-b5c7-0428c312f42d">
|
||||
<period>5.0</period>
|
||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||
</rateSpec>
|
||||
</rates>
|
||||
<baseRate type="sto.ClassicPeriodicDiscreteRate" uuid="fc5d4684-395b-44c9-8cfa-430a2d34b8de">
|
||||
<baseRate type="sto.ClassicPeriodicDiscreteRate" uuid="65b35d5e-227d-4911-bc52-2893aadaefbf">
|
||||
<annotation>D1</annotation>
|
||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||
<description>Discrete 1</description>
|
||||
<taskId>_task0</taskId>
|
||||
<rateSpec type="sto.RateSpec" uuid="ae85af8c-7a93-4769-abad-dfb66bc50c8e">
|
||||
<period>5.0</period>
|
||||
<rateSpec type="sto.RateSpec" uuid="ff2d4d8a-96eb-48d4-9f8f-062960f9fb1d">
|
||||
<period>.25</period>
|
||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||
</rateSpec>
|
||||
</baseRate>
|
||||
</clocks>
|
||||
<timeAdvanceMode>FixedStep</timeAdvanceMode>
|
||||
</clockRegistry>
|
||||
<taskRegistry type="sto.TaskRegistry" uuid="052f32c4-2b96-4908-913e-03a4854d96c0">
|
||||
<rootTaskHierarchyElements type="sto.Task" uuid="8de7de87-835c-46ef-ad46-f88050f2605e">
|
||||
<taskRegistry type="sto.TaskRegistry" uuid="b6adc007-26b8-402c-b01d-1e3d81bb5c20">
|
||||
<rootTaskHierarchyElements type="sto.Task" uuid="5edff6a2-d515-4f58-a3d8-c5326ec15f76">
|
||||
<isExecutable>true</isExecutable>
|
||||
<orderIndex>1</orderIndex>
|
||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="287f9e9c-18e9-462d-bf56-5a7dc6aad9b7">
|
||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="f55c6bcc-446d-42c6-90e7-ff6c2ff6f624">
|
||||
<annotation>D1</annotation>
|
||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||
<description>Discrete 1</description>
|
||||
<taskId>_task0</taskId>
|
||||
<rateSpec type="sto.RateSpec" uuid="31b43a7e-4ce0-4be9-a684-8e88514ad3d8">
|
||||
<period>5.0</period>
|
||||
<rateSpec type="sto.RateSpec" uuid="d3854663-c664-46a3-a0a9-41f57f4994dd">
|
||||
<period>.25</period>
|
||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||
</rateSpec>
|
||||
</rates>
|
||||
@ -91,7 +114,33 @@
|
||||
<identifier>_task0</identifier>
|
||||
<priority>40</priority>
|
||||
</rootTaskHierarchyElements>
|
||||
<taskDependencyGraph type="sto.SerializedTaskConnectionList" uuid="6a78d61d-7a32-4285-b101-584200d36c5c">
|
||||
<rootTaskHierarchyElements type="sto.Task" uuid="a86fefe7-45e4-423e-9db6-880c90fa3d37">
|
||||
<isExecutable>true</isExecutable>
|
||||
<orderIndex>2</orderIndex>
|
||||
<rates type="sto.ClassicPeriodicDiscreteRate" uuid="8d76a60f-fbc0-4d52-b0c5-783585f4eb4e">
|
||||
<annotation>D2</annotation>
|
||||
<clockId>uORB_MODBUS_TCP::defaultTimer</clockId>
|
||||
<colorIndex>1</colorIndex>
|
||||
<description>Discrete 2</description>
|
||||
<rateIdx>1</rateIdx>
|
||||
<taskId>_task1</taskId>
|
||||
<rateSpec type="sto.RateSpec" uuid="7e68009f-8a4a-4dac-9abb-5a4cbf16a75c">
|
||||
<period>5.0</period>
|
||||
<rateType>ClassicPeriodicDiscrete</rateType>
|
||||
</rateSpec>
|
||||
</rates>
|
||||
<schedulingClockId>uORB_MODBUS_TCP::defaultTimer</schedulingClockId>
|
||||
<tNum>1</tNum>
|
||||
<timeKeeperClockId>uORB_MODBUS_TCP::defaultTimer</timeKeeperClockId>
|
||||
<elementType>Task</elementType>
|
||||
<identifier>_task1</identifier>
|
||||
<priority>39</priority>
|
||||
</rootTaskHierarchyElements>
|
||||
<taskDependencyGraph type="sto.SerializedTaskConnectionList" uuid="d51d07bc-b865-4d1b-bd8f-102c79ccc172">
|
||||
<clockIdentifier>uORB_MODBUS_TCP::defaultTimer</clockIdentifier>
|
||||
<taskIdentifier>_task1</taskIdentifier>
|
||||
</taskDependencyGraph>
|
||||
<taskDependencyGraph type="sto.SerializedTaskConnectionList" uuid="711a613b-96b6-4f2f-bbfe-1a5d260148ac">
|
||||
<clockIdentifier>uORB_MODBUS_TCP::defaultTimer</clockIdentifier>
|
||||
<taskIdentifier>_task0</taskIdentifier>
|
||||
</taskDependencyGraph>
|
||||
@ -100,20 +149,22 @@
|
||||
</sto.Registry>
|
||||
</slexec_sto></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>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,16 +5,19 @@ set(MAVLINK_LIBRARY_DIR "${CMAKE_BINARY_DIR}/mavlink")
|
||||
set(MAVLINK_DIALECT_UAVIONIX "uAvionix")
|
||||
|
||||
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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Binary file not shown.
@ -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>
|
||||
Binary file not shown.
@ -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'
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@ -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'
|
||||
|
||||
|
||||
//-
|
||||
|
||||
@ -0,0 +1,268 @@
|
||||
//
|
||||
// Academic License - for use in teaching, academic research, and meeting
|
||||
// course requirements at degree granting institutions only. Not for
|
||||
// government, commercial, or other organizational use.
|
||||
//
|
||||
// File: uORB_MODBUS_TCP_data.cpp
|
||||
//
|
||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||
//
|
||||
// Model version : 1.22
|
||||
// Simulink Coder version : 24.1 (R2024a) 19-Nov-2023
|
||||
// C/C++ source code generated on : Sat Apr 12 20:53:52 2025
|
||||
//
|
||||
// Target selection: ert.tlc
|
||||
// Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
// Code generation objectives: Unspecified
|
||||
// Validation result: Not run
|
||||
//
|
||||
#include "uORB_MODBUS_TCP.h"
|
||||
|
||||
// Block parameters (default storage)
|
||||
P_uORB_MODBUS_TCP_T uORB_MODBUS_TCP_P{
|
||||
// Computed Parameter: Out1_Y0
|
||||
// Referenced by: '<S13>/Out1'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||
// register_array_read
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value
|
||||
// Referenced by: '<S1>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||
// register_array_read
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_o
|
||||
// Referenced by: '<S5>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||
// register_array_read
|
||||
},
|
||||
|
||||
// Computed Parameter: Out1_Y0_h
|
||||
// Referenced by: '<S15>/Out1'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||
// register_array
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_f
|
||||
// Referenced by: '<S3>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||
// register_array
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_om
|
||||
// Referenced by: '<S7>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
|
||||
0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U }
|
||||
// register_array
|
||||
},
|
||||
|
||||
// Computed Parameter: Out1_Y0_g
|
||||
// Referenced by: '<S14>/Out1'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false }
|
||||
// coil_array_read
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_m
|
||||
// Referenced by: '<S2>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false }
|
||||
// coil_array_read
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_k
|
||||
// Referenced by: '<S6>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false }
|
||||
// coil_array_read
|
||||
},
|
||||
|
||||
// Computed Parameter: Out1_Y0_l
|
||||
// Referenced by: '<S16>/Out1'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false }
|
||||
// input_array
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_d
|
||||
// Referenced by: '<S4>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false }
|
||||
// input_array
|
||||
},
|
||||
|
||||
// Computed Parameter: Constant_Value_mf
|
||||
// Referenced by: '<S8>/Constant'
|
||||
|
||||
{
|
||||
(0ULL), // timestamp
|
||||
|
||||
{
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false }
|
||||
// input_array
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// File trailer for generated code.
|
||||
//
|
||||
// [EOF]
|
||||
//
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// Code generated for Simulink model 'uORB_MODBUS_TCP'.
|
||||
//
|
||||
// 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
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user