Came across an odd error lately. If I use the exact same code in Visual Studio and Arduino IDE and upload to my Teensy 4.1 I get some changes in performance. Specifically I think it's affecting the EthernetClient aspect of NativeEthernet has trouble with connecting clients. VS code seems to have no issues managing the clients whereas the Arduino IDE will hang and disconnect the socket sometimes. I've attached screenshots of the errors. There is a time based algorithm that I am using so hangs aren't any good. I've copied the ArduinoModbus and ArduinoRS485 libraries from VS to the Arduino IDE and they both pull the same NativeEthernet library so I am not sure what's going on here. I've made sure Arduino IDE was latest version as well as all the libraries. This code also needs to go onto some lockable teensy 4.1s that I have so I am unaware of anyway to upload code to those unless it's through the Arduino IDE. Otherwise I'd just go along using VS.
The code as a whole sends out a UDP message with the Teensy IP every 10th loop cycle, that I have another device use to connect to it initially. The Teensy then does some work, posts it to some registers and repeats the cycle.
I'm sure the issue is in the dowork function. This function runs 1000 times and iterates through some data so I embedded the modbuspoll into it as I'll potentially have a few clients trying to get data every couple of seconds and I feel like this is the best place to poll. I used to poll outside this function (so once every ten seconds) for when I had just one client and it worked very well. With more clients I figured I had to poll/establish clients quicker and this does work very well with the VS uploaded code, but hangs and pauses a lot in Arduino IDE.
Code:
The code as a whole sends out a UDP message with the Teensy IP every 10th loop cycle, that I have another device use to connect to it initially. The Teensy then does some work, posts it to some registers and repeats the cycle.
I'm sure the issue is in the dowork function. This function runs 1000 times and iterates through some data so I embedded the modbuspoll into it as I'll potentially have a few clients trying to get data every couple of seconds and I feel like this is the best place to poll. I used to poll outside this function (so once every ten seconds) for when I had just one client and it worked very well. With more clients I figured I had to poll/establish clients quicker and this does work very well with the VS uploaded code, but hangs and pauses a lot in Arduino IDE.
Code:
Code:
#include <Arduino.h>
#include <NativeEthernet.h>
#include <ArduinoRS485.h>
#include <ArduinoModbus.h>
//Udp stuff
EthernetUDP Udp;
uint16_t destPort = 52362; // port to send Teensy UDP heartbeat to
const char all_ip[] = "255.255.255.255";
char udp_message[] = "Teensy";
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
//Modbus Registers
int variable1_reg = 46000;
int variable2_reg = 46002;
int variable3_reg = 46004;
int variable4_reg = 46006;
int variable5_reg = 46080;
int register_range = 65500;
float variable1 = 1.0;
float variable2 = 2.0;
float variable3 = 3.0;
float variable4 = 4.0;
int variable5 = 5;
int modport = 50000;
uint8_t LED = 13;
uint8_t mac[6];
EthernetServer ethServer(modport);
ModbusTCPServer modbusTCPServer;
void teensyMAC(uint8_t *mac) {
// Obbtaining native hardware mac address
for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
void blink(uint8_t repititions, uint16_t time) {
//Blinks a defined number of times with a declared delay
for (int i=0; i<repititions; i++){
digitalWrite(LED, HIGH);
delay(time);
digitalWrite(LED, LOW);
delay(time);
}
}
void udp_heartbeat() {
//Send out UDP message with Teensy IP every 10th call
static int i = 0;
int call_freq = 10;
int packet_size = Udp.parsePacket();
if (i==0) {
Udp.beginPacket(all_ip, destPort);
Udp.write(udp_message);
Udp.endPacket();
i++;
}
else if (i == call_freq){
i = 0;
}
else {
i++;
}
}
void modbus_init() {
if (!modbusTCPServer.begin()) {
Serial.println("Failed to start Modbus TCP Server!");
blink(6, 500);
delay(2000);
}
else {
Serial.println("Modbus TCP Server Active");
modbusTCPServer.configureHoldingRegisters(1, register_range);
delay(10);
}
}
void Ethernet_init() {
String IP;
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
blink(3, 500);
delay(2000);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("No Ethernet hardware found");
blink(4, 500);
delay(2000);
}
// Check if a link is present
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected");
blink(5, 500);
delay(2000);
}
}
// Good Ethernet connection established, getting assigned IP of Teensy
else {
Serial.print("DHCP assigned IP: ");
Serial.println(Ethernet.localIP());
blink(1, 1000);
}
}
void dowork() {
//Slimmed down of real version, but analyses data in the for loop from various sensors that then get put into the modbus registers
EthernetClient modclient;
for(int i = 0; i<1000; i++) {
modclient = ethServer.available();
if (modclient) {
modbusTCPServer.accept(modclient);
}
//Get some sensor data here
delay(10);
if (modclient.connected()) {
modbusTCPServer.poll();
Serial.println("Modbus Polled");
}
}
Serial.println("Work Completed");
}
union {
float asFloat;
u_int16_t asInt[2];
}
variable1_modbus;
union {
float asFloat;
u_int16_t asInt[2];
}
variable2_modbus;
union {
float asFloat;
u_int16_t asInt[2];
}
variable3_modbus;
union {
long asLong;
u_int16_t asInt[2];
}
variable4_modbus;
void modbus_write_values() {
//Splitting Floats into two u_int_16 variables
variable1_modbus.asFloat=variable1;
variable2_modbus.asFloat=variable2;
variable3_modbus.asFloat=variable3;
variable4_modbus.asLong=variable4;
modbusTCPServer.holdingRegisterWrite(variable1_reg, variable1_modbus.asInt[0]);
modbusTCPServer.holdingRegisterWrite(variable1_reg + 1, variable1_modbus.asInt[1]);
modbusTCPServer.holdingRegisterWrite(variable2_reg, variable2_modbus.asInt[0]);
modbusTCPServer.holdingRegisterWrite(variable2_reg + 1, variable2_modbus.asInt[1]);
modbusTCPServer.holdingRegisterWrite(variable3_reg, variable3_modbus.asInt[0]);
modbusTCPServer.holdingRegisterWrite(variable3_reg + 1, variable3_modbus.asInt[1]);
modbusTCPServer.holdingRegisterWrite(variable4_reg, variable4_modbus.asInt[0]);
modbusTCPServer.holdingRegisterWrite(variable4_reg + 1, variable4_modbus.asInt[1]);
modbusTCPServer.holdingRegisterWrite(variable5_reg, variable5);
blink(1, 50);
}
void setup() {
delay(100);
Serial.begin(9600);
teensyMAC(mac);
Ethernet_init();
modbus_init();
Udp.begin(destPort);
ethServer.begin();
}
void loop() {
udp_heartbeat();
dowork();
modbus_write_values();
}