Hello! I am working on a project where I need to attach a CONTROLLINO to an industrial printer for controlling a particular phase of production.
Expected behaviour
After receiving the "start" signal from an outside source, the CONTROLLINO should hold an output on HIGH indefinitely. When the outside source sends a "stop" signal, the CONTROLLINO should:
- Command the output to OFF
- Send a sequence of five strings using TCP/IP to the printer
- Wait for the new "start" signal
Below is the full code (I have obscured data such as addresses and the strings being sent, however I can confirm that they are sent and received properly by the printer).
#include <Controllino.h>
#include <Ethernet.h>
// Ethernet
IPAddress localip([...]);
IPAddress serverip([...]);
int port = [...];
byte mac[] = {[...]};
EthernetClient client;
// Misc. variables
unsigned long startTime = 0;
unsigned long timeDelta = 0;
void setup() {
pinMode(CONTROLLINO_A0, INPUT); // printer ready (RDY)
pinMode(CONTROLLINO_A1, INPUT); // print stop (STP)
attachInterrupt(digitalPinToInterrupt(CONTROLLINO_IN0), start_print, RISING); // from ext. (GO)
pinMode(CONTROLLINO_D0, OUTPUT); // trigger (TRG)
pinMode(CONTROLLINO_D1, OUTPUT); // process finished monitor (FIN)
pinMode(CONTROLLINO_D2, OUTPUT); // connection error (CON)
// Initialization
Serial.begin(9600);
Serial.println("\n\nSerial communication initialized.");
Serial.print("Initializing ethernet connection... ");
Ethernet.begin(mac, localip);
delay(4000);
if (client.connect(serverip, port)) {
Serial.println("Ethernet connection OK.");
} else {
Serial.println("Ethernet connection failed. Please check network settings and reset the PLC.");
digitalWrite(CONTROLLINO_D2, HIGH); // connection error output (CON)
while(1); // Block startup if ethernet connection error detected
}
Serial.println("\nStart-up completed.\n\n");
}
void loop() {
if (digitalRead(CONTROLLINO_A1) == HIGH) {
startTime = millis();
Serial.println("- - - Stop signal detected. Initiating stop sequence. - - -");
digitalWrite(CONTROLLINO_D0, LOW); // Trigger OFF
sendMessage("string1");
sendMessage("string2");
sendMessage("string3");
sendMessage("string4");
sendMessage("string5");
Serial.println("- - - Process complete. Waiting for new print start signal. - - -");
digitalWrite(CONTROLLINO_D1, HIGH); // Process finished monitor ON
timeDelta = millis() - startTime;
Serial.print("Elapsed time: ");
Serial.print(timeDelta);
Serial.println("ms.");
}
Serial.println("Waiting...");
}
void start_print() {
digitalWrite(CONTROLLINO_D1, LOW); // Monitor OFF
while (digitalRead(CONTROLLINO_A0) == LOW) {} // wait for print ready (RDY)
digitalWrite(CONTROLLINO_D0, HIGH); // Trigger ON
}
String receiveReply() {
String reply = "";
while (client.available()) {
char c = client.read();
reply += c;
}
Serial.print("> ");
Serial.println(reply);
return reply;
}
String sendMessage(String message) {
int retryAttempts = 3;
for (int i = 0; i < retryAttempts; i++) {
if (client.connected()) {
client.println(message);
Serial.print("< ");
Serial.println(message);
return receiveReply();
} else {
client.stop();
delay(1000);
if (client.connect(serverip, port)) {
client.println("WARN: Reconnected after connection loss.");
client.println(message);
Serial.print("< ");
Serial.println(message);
return receiveReply();
}
delay(1000);
}
}
Serial.println("ERR: Failed to send message after multiple attempts.");
return "";
}
Actual behaviour
The CONTROLLINO behaves as expected most of the time. Looking at the serial monitor, it sends "Waiting..." continuously during normal operation. When the stop signal is input, it performs the stop sequence printing the correct data to the serial monitor. It then waits for the new print start.
However, every once in a while (not a lot, maybe 1 in 30) the CONTROLLINO will finish the stop sequence, but it will get stuck and won't accept any new inputs (either stop or start). What's more, it will not even print "Waiting..." to the serial monitor. The serial monitor will look something like:
- - - Process complete. Waiting for new print start signal. - - -
Elapsed time: 173ms.
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
W
The "W" is what bugs me: it seems like the serial.print() didn't even finish, the execution just stopped mid-line. The outputs that are already HIGH remain high, and the CONTROLLINO remains powered and in normal state, but it doesn't process any outputs (regular or interrupt) anymore.
What I have already tried to fix the issue
- Removing the "println("Waiting...")" statement from the main body of void loop(): I use it as debugging, but I thought maybe it was creating issues. Removing it had no effect however, the problem still happened with the same frequency.
- Trying to figure out which conditions trigger the issue: I tried with sending the start and stop signal multiple times, simultaneously, out of order, with very short breaks in-between them. I could not figure out what exactly causes the issue, it seems to happen with the same frequency.
- Adding a delay() in the main body of void loop() to slow down the execution. I tried with 1ms, 5ms, 100ms delays. In all cases the problem still appeared with the same frequency.
- Moving the whole print stop process to an interrupt function: I considered this, but I read that print() statements shouldn't be used in interrupts, and since the whole stop process consists of several client.print() statements, I abandoned the idea.
I would like to know what causes this issue and how I can avoid it. I think it's likely that it's due to some bad coding practice on my part, so if you have any advice I will gladly try it out.
Thanks!