Hello,
i got a High Performance Converter Maschine from M&P, which controls a synchronous motor. My challenge is it to control the converter using an Controllino Mega.
The converter is sending a UDP-message every 500 microseconds with new values. I can extract the single 20 Bytes of the payload from the incoming UDP-Message to read out the values from the motor (speed, torque ...).
Currently the Controllino is too "slow" to print the values to the serial port, so I get a delay of about 500milliseconds .
How can I improve my code that the Controllino can handle the amount of data ? Is there a way to read for example only every 10th message, to prevent the 500ms delay ?
The actual problem is not that I miss some messages, it is rather that the values show up too late on the serial montior. For example, if the motor is on a rotation angle of 360° and I turn it to an angle of 180° the value shows up 500 ms later on the display of the serial port.
Do you think the Arduino is able to handle this Task ?
Here is my Code for reading the UDP Packets. The magic happens in the void loop(). The other functions are only for analog value for a safety operation with the motor so i think you can ignore that part.
#include <Controllino.h>
#include<SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#define TIMER_INTERRUPT_DEBUG 0
#define _TIMERINTERRUPT_LOGLEVEL_ 0
#define USE_TIMER_3 true
#include <TimerInterrupt.h>
const int EMRM = CONTROLLINO_R0; //HPC emergency off RM
const int ign = CONTROLLINO_R1; //HPC ignition
const int STORM = CONTROLLINO_R2; //HPC STO RM
const int inTempA = CONTROLLINO_A0; //temperature bearing A KATT
const int inTempB = CONTROLLINO_A1; //temperature bearing B KATT
const int inTempU = CONTROLLINO_A2; //temperature phase U KATT
const int inTempV = CONTROLLINO_A3; //temperature phase V KATT
const int inTempW = CONTROLLINO_A4; //temperature phase W KATT
const int inTempSh= CONTROLLINO_A7; //temperature shaft KATT
const int inHPCvol = CONTROLLINO_A5; //flow sensor HPC
const int inHPCtemp= CONTROLLINO_A6; //flow sensor temperature
const int HBLED = CONTROLLINO_D23; //heartbeat
const int TimerInterval = 1000; //read temps every second
int tempA = 200;
int tempB = 200;
int tempU = 200;
int tempV = 200;
int tempW = 200;
int tempSh= 200;
int HPCvol = 0;
int HPCtemp = 0;
bool warnTempBea = true;
const int warnTempBeaTres = 95;
bool critTempBea = true;
const int critTempBeaTres = 105;
bool tempBeaMeasFault = true;
bool warnTempPhase = true;
const int warnTempPhaseTres = 150; //150
bool critTempPhase = true;
const int critTempPhaseTres = 165; //165
bool tempPhaseMeasFault = true;
bool warnTempShaft = true;
const int warnTempShaftTres = 145;
bool critTempShaft = true;
const int critTempShaftTres = 160;
bool tempShaftMeasFault = true;
bool warnStateTemp = true;
bool saveStateTemp = false;
bool toggle = false;
/////////////////////////////////////////////
//Umrichtier Variablen
float UmrechungsfaktorNormiert = 1073741824;// eintspricht 4000 0000 in HEX siehe Handbuch S.23
float BezugwertIstDrehwinkelNormiert = 360; //Bezugwert auf den Normiert wird
float BezugwertIstDrehzahlNormiert = 9549 ;
float BezugwertIstDrehmomentNormiert = 1;
// UDP SetUP
//bool thisPacketIsNotEmpty = false;
//bool previousPacketIsLoaded = false;
byte mac[] =
{0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};//Mac Adresse Arudino frei gewählt
IPAddress ip(192, 168, 0, 2);// IP Adresse des PLC
unsigned int localPort = 25000; // local port to listen on //Port aus dem Handbuch S24
// buffers for receiving and sending data
byte packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet,
byte ReplyBuffer[] = "acknowledged"; // a string to send back
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
void TimerHandler(void) {
digitalWrite(HBLED,toggle);
toggle = !toggle;
digitalWrite(EMRM,HIGH);
digitalWrite(STORM,HIGH);
readTempKATT();
if (saveStateTemp) {
digitalWrite(ign, HIGH);
}
else {
digitalWrite(ign, LOW);
}
readHPCCool();
// printValuesToSerial();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
}
// start UDP
Udp.begin(localPort);
pinMode(EMRM,OUTPUT);
pinMode(ign,OUTPUT);
pinMode(STORM,OUTPUT);
pinMode(inTempA,INPUT);
pinMode(inTempB,INPUT);
pinMode(inTempU,INPUT);
pinMode(inTempV,INPUT);
pinMode(inTempW,INPUT);
pinMode(inTempSh,INPUT);
pinMode(inHPCvol,INPUT);
pinMode(inHPCtemp,INPUT);
digitalWrite(EMRM, LOW);
digitalWrite(ign, LOW);
digitalWrite(STORM, LOW);
pinMode(HBLED,OUTPUT);
ITimer3.init();
ITimer3.attachInterruptInterval(TimerInterval, TimerHandler);
}
void loop()
{
/* while (true)
{
Serial.println("Loop: ");
thisPacketIsNotEmpty = (Udp.parsePacket() > 0);
Serial.println(thisPacketIsNotEmpty);
if (thisPacketIsNotEmpty) { // raise flag that a packet is loaded and read it in the buffer
previousPacketIsLoaded = true;
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
}
else if (!thisPacketIsNotEmpty && previousPacketIsLoaded) { // if the current packet is empty, but a loaded packet exists, break out of the loop
previousPacketIsLoaded = false;
Serial.print("break: ");
break;
}
else { // you should never reach this spot
}
}*/
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize)
{
// read the packet into packetBufffer
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
// Serial.println("Contents:");
for (int i=0 ; i <= UDP_TX_PACKET_MAX_SIZE ; i++) {
/* Serial.print("Byte ");
Serial.print(i);
Serial.print(" : ");
Serial.println(packetBuffer[i],BIN);*/
}
uint32_t drehwinkel = packetBuffer[16];// 32 bit Variable in die die vier Bytes der Botschaft geschrieben werden sollen
drehwinkel <<= 8;
drehwinkel += packetBuffer[17];
drehwinkel <<= 8;
drehwinkel += packetBuffer[18];
drehwinkel <<= 8;
drehwinkel += packetBuffer[19];
float drehwinkelfloat = float(drehwinkel);
drehwinkelfloat= drehwinkelfloat*BezugwertIstDrehwinkelNormiert/UmrechungsfaktorNormiert;
uint32_t drehzahl = packetBuffer[4];// 32 bit Variable in die die vier Bytes der Botschaft geschrieben werden sollen
drehzahl <<= 8;
drehzahl += packetBuffer[5];
drehzahl <<= 8;
drehzahl += packetBuffer[6];
drehzahl <<= 8;
drehzahl += packetBuffer[7];
float drehzahlfloat = float(drehzahl);
//drehzahlfloat= drehzahlfloat*BezugwertIstDrehzahlNormiert/UmrechungsfaktorNormiert;
uint32_t drehmoment = packetBuffer[8];// 32 bit Variable in die die vier Bytes der Botschaft geschrieben werden sollen
drehmoment <<= 8;
drehmoment += packetBuffer[9];
drehmoment <<= 8;
drehmoment += packetBuffer[10];
drehmoment <<= 8;
drehmoment += packetBuffer[11];
float drehmomentfloat = float(drehmoment);
//drehmomentfloat= drehmomentfloat*BezugwertIstDrehmomentNormiert/UmrechungsfaktorNormiert;
/*
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remote = Udp.remoteIP();
for (int i=0; i < 4; i++)
{
Serial.print(remote[i], DEC);
if (i < 3)
{
Serial.print(".");
}
}
// Serial.print(", port ");
// Serial.println(Udp.remotePort());
Serial.println("Große Packet Buffer:");
Serial .println(sizeof(packetBuffer));
*/
// Serial.println("Contents:");
/* for (int i=0 ; i <= UDP_TX_PACKET_MAX_SIZE ; i++) {
Serial.print("Byte ");
Serial.print(i);
Serial.print(" : ");
Serial.println(packetBuffer[i],BIN);
}*/
// Serial.println("Drehzahl:");
//Serial.println(drehzahlfloat); // Raw binary value
Serial.print("Drehwinkel: ");
Serial.println(drehwinkelfloat); // Raw binary value
// Serial.println("Drehmoment:");
//Serial.println(drehmomentfloat); // Raw binary value
//Serial.println(packetBuffer[17],BIN);
// send a reply to the IP address and port that sent us the packet we received
// Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
// Udp.write(ReplyBuffer);
// Udp.endPacket();
}
// thisPacketIsNotEmpty = false;
//previousPacketIsLoaded = false;
//delay(500);
}
void readTempKATT(){
tempA = analogRead(inTempA) *0.225;
tempB = analogRead(inTempB) *0.225;
tempU = analogRead(inTempU) *0.3;
tempV = analogRead(inTempV) *0.3;
tempW = analogRead(inTempW) *0.3;
tempSh = analogRead(inTempSh) *0.54;
if (tempA >= critTempBeaTres || tempB >= critTempBeaTres) {
critTempBea = true;
}
else if (tempA >= warnTempBeaTres || tempB >= warnTempBeaTres) {
warnTempBea = true;
}
else if (tempA >=0 || tempB >= 0) {
critTempBea = false;
warnTempBea = false;
tempBeaMeasFault = false;
}
else {
tempBeaMeasFault = true;
}
if (tempU >= critTempPhaseTres || tempV >= critTempPhaseTres || tempW >= critTempPhaseTres) {
critTempPhase = true;
}
else if (tempU >= warnTempPhaseTres || tempV >= warnTempPhaseTres || tempW >= warnTempPhaseTres) {
warnTempPhase = true;
}
else if (tempU >= 0 || tempV >= 0 || tempW >= 0) {
critTempPhase = false;
warnTempPhase = false;
tempPhaseMeasFault = false;
}
else {
tempPhaseMeasFault = true;
}
if (tempSh >= critTempShaftTres) {
critTempShaft = true;
}
else if (tempSh >= warnTempShaftTres) {
warnTempShaft = true;
}
else if (tempSh >= 0) {
critTempShaft = false;
warnTempShaft = false;
tempShaftMeasFault = false;
}
else {
tempShaftMeasFault = true;
}
if (!critTempBea && !tempBeaMeasFault && !critTempPhase && !tempPhaseMeasFault && !critTempShaft && !tempShaftMeasFault) {
saveStateTemp = true;
}
else {
saveStateTemp = false;
}
if (!warnTempBea && !warnTempPhase && !warnTempShaft) {
warnStateTemp = false;
}
else {
warnStateTemp = true;
}
}
void readHPCCool() {
HPCvol = (analogRead(inHPCvol)*0.475)-10.8333;
HPCtemp = (analogRead(inHPCtemp)*0.5)-16.6666;
}
void printValuesToSerial() {
Serial.print("A:");
Serial.print(tempA);
Serial.print("degC");
Serial.print("\t");
Serial.print("B:");
Serial.print(tempB);
Serial.print("degC");
Serial.print("\t");
Serial.print("U:");
Serial.print(tempU);
Serial.print("degC");
Serial.print("\t");
Serial.print("V:");
Serial.print(tempV);
Serial.print("degC");
Serial.print("\t");
Serial.print("W:");
Serial.print(tempW);
Serial.print("degC");
Serial.print("\t");
Serial.print("Shaft:");
Serial.print(tempSh);
Serial.print("degC");
Serial.print("\t");
Serial.print("Vdot:");
Serial.print(HPCvol);
Serial.print("lpermin");
Serial.print("\t");
Serial.print("T:");
Serial.print(HPCtemp);
Serial.println("degC");
}