I am using Automation Direct's P1AM Arduino PLC to try and send commands to a TCP/IP stepper motor driver. Using Wireshark I was able to see the data that needed to be in the packet to control the motor.
I wrote the following program to try and send this same packet to the stepper driver but from the Arduino instead of my computer:
#include <SPI.h>
#include <Ethernet.h>
String Control, Command;
byte mac[] = { //Mac address on side of P1AM Eth module
0x60, 0x52, 0xD0, 0x07, 0x41, 0x95
};
IPAddress ip(192, 168, 1, 2);//IP Address of the P1AM-ETH module.
IPAddress stepperDriver(192, 168, 1, 1); //IP Address for stepper motor driver
EthernetClient client;
char Null = 0; //Ascii value of null character
char Bell = 7; //Ascii value of bell character
char Ret = 13; //Ascii value of carriage return
char Lf = 10; //Ascii value of line feed
void setup() {
Control = String("FL10000"); //step motor 10000 steps
Command = String(Null + Bell + Control + Ret + Lf); //append header and footer to command string
Ethernet.begin(mac, ip);
Serial.begin(9600);
delay(2000); //sanity delay
Serial.println("Connecting...");
if (client.connect(stepperDriver, 49153)) { //Connect to device
Serial.println("Connected");
} else {
Serial.println("Connection Failed");
}
}
void loop() {
delay(3000);
client.print(Command); //send packet
Serial.print(Command); //print packet in serial monitor
}
Running this and using Wireshark again gives me this:
However if I change the line:
Command = String(Null + Bell + Control + Ret + Lf);
To:
Command = String(Bell + Control + Ret + Lf);
I get closer to my expected result but still do not have the null character at the start:
#include <SPI.h>
#include <Ethernet.h>
String Control, Command;
byte mac[] = { //Mac address on side of P1AM Eth module
0x60, 0x52, 0xD0, 0x07, 0x41, 0x95
};
byte command[] = {0x00, 0x07, 0x46, 0x4c, 0x31, 0x30, 0x30, 0x30, 0x30, 0x0d, 0x0a};
IPAddress ip(192, 168, 1, 2);//IP Address of the P1AM-ETH module.
IPAddress stepperDriver(192, 168, 1, 1); //IP Address for stepper motor driver
EthernetClient client;
char Null = 0; //Ascii value of null character
char Bell = 7; //Ascii value of bell character
char Ret = 13; //Ascii value of carriage return
char Lf = 10; //Ascii value of line feed
void setup() {
Control = String("FL10000"); //step motor 10000 steps
Command = String(Null + Bell + Control + Ret + Lf); //append header and footer to command string
Ethernet.begin(mac, ip);
Serial.begin(9600);
delay(2000); //sanity delay
Serial.println("Connecting...");
if (client.connect(stepperDriver, 49153)) { //Connect to device
Serial.println("Connected");
} else {
Serial.println("Connection Failed");
}
}
void loop() {
delay(3000);
client.print(Command); //send packet
client.write(command, sizeof(command));
Serial.print(Command); //print packet in serial monitor
}
Will the String library let you put a null inside a String like that? I'm pretty sure that will confuse some of the functions?
Why do you need to assemble the command first? Are you using it elsewhere? If you do want to assemble it, then assemble it in a char array instead of a String.
char command[5] = {Null, Bell, Control, Ret, Lf};
in loop:
for (int i=0; i<5; i++){
client.write(command[i]);
Serial.write(command[i]);
}
Or the more concise:
client.write(command, sizeof(command));
This is correct. You definitely won't be able to do it using print. You'll have to use write one way or the other if there's a null in it.
Although I doubt this is the solution that the OP is looking for. I bet that String in the middle is supposed to change. In which case you'd best to just break it up into separate statements.
Thank you all very much for the help, I ended up solving the issue by using memcpy and .c_str() to copy the contents of the header, command, and footer into a byte array and sending that to the server using the client.write function rather than client.print.
For those interested here is my code:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x60, 0x52, 0xD0, 0x07, 0x41, 0x95 };
int port = 49153;
int time = 5000;
IPAddress ip(192, 168, 1, 2);//IP Address of the P1AM-ETH module.
IPAddress stepperDriver(192, 168, 1, 1); //IP Address for stepper motor driver
EthernetClient client;
byte header[2] = {0x00, 0x07};
byte footer[2] = {0x0d, 0x0a};
String Control = "FL10000";
void setup() {
Ethernet.begin(mac, ip);
Serial.begin(9600);
delay(2000); //sanity delay
Serial.println("Connecting...");
if (client.connect(stepperDriver, port)) { //Connect to device
Serial.println("Connected");
} else {
Serial.println("Connection Failed");
}
}
void loop() {
if(client.connected()){
int commandSize = sizeof(header) + sizeof(footer) + Control.length();
byte Command[commandSize];
memcpy(Command, header, sizeof(header));
memcpy(Command + sizeof(header), Control.c_str(), Control.length());
memcpy(Command + sizeof(header) + Control.length(), footer, sizeof(footer));
client.write(Command, commandSize); //send command
}
else{
Serial.println("Connection lost, attempting to reconnect.");
client.connect(stepperDriver, port); //attempt to reconnect
}
delay(time);
}