Sending Serial Commands to Equipment

I’m trying to connect a chiller to the spark via RS232 and poll the temperature.
The datasheet of the chiller specifies that the commands must be sent in hex, eg: CA 00 01 20 00 DE

Hardware wise, I have the spark hooked up to an LT1081CN RS232 Transceiver which connects to the chiller via a spliced RS232 Cable

Software wise i’m not really sure the best way to send these commands (rather new to serial communications)

Any advice on tutorials or examples would be much appreciated

@daflippymaster, can I assume you are using the Serial1 port on the Spark? Sending bytes to the port means not using the typical Serial.print() command. Instead, use Serial.write© where c is a char (uint8_t). This allows you to print a HEX value directly to the port. You could use arrays of chars for common commands:

const char command1[] = {0xCA, 0x00, 0x01, 0x20, 0x00, 0xDE};
const char command2[] = {... };

Then send the entire command using a call and function like this:

sendCommand(command1);  //Call sendCommand with address of command array

void sendCommand(const char *cmd) {
  for (int i = 0; i < sizeof(cmd); i++)
    Serial1.write(cmd[i]);
}

:smile:

2 Likes

Ah, I had forgotten that you need the 0x to specify hex.

After the command is sent, the chiller is supposed to respond with a similarly formatted answer.

Is there a special way to tell the spark to listen for a response besides Serial.read( )?
And if it is just Serial.read( ), would I need an array of chars to store this answer?

if you have a while (!serial1.available()) loop with some sort of timeout to wait for the data, then once data is available you can Serial1.read() into a char (or byte) array

1 Like

would a for loop be necessary to read the answer into an array? or will Serial1.read() take care of that?

EDIT: May have found the answer elsewhere on the forums
This is what I hope to use to send a command and read back the response

int x=0;
const char command1[] = {0xCA, 0x00, 0x01, 0x20, 0x00, 0xDE};
static char inChar=-1;
static int pos=0;
char answer[50];

void setup()
{
      Serial.begin(9600);
      Serial1.begin(9600);
}

void sendCommand(const char *cmd)
{

     for(int i = 0; i <sizeof(cmd); i++)
     {
     Serial1.write(cmd[i]);
     }

}

void loop()
{

     sendCommand(command1);
     while(Serial1.available()){

            inChar=Serial1.read();
            answer[pos]=inChar;
            pos++;
            answer[pos]=0;
     }

     for(int x=0;x<sizeof(answer);x++){
            Serial.print(answer[x]);
     }
}

any glaring issues?

after the send command is sent there may be a delay of a couple of micro’s or more for data to start coming back, so the first test of Serial1.available() will be false so the program will skip straight over it.

also I would add a timeout, something like this so your loop doesn’t hang forever waiting around. I havent checked to see if it compiles or not, but cant see anything obvious.

#define TIMEOUT 500
unsigned long timer;
int x=0;
const char command1[] = {0xCA, 0x00, 0x01, 0x20, 0x00, 0xDE};
static char inChar=-1;
static int pos=0;
char answer[50];

void setup()
{
      Serial.begin(9600);
      Serial1.begin(9600);
}

void sendCommand(const char *cmd)
{

     for(int i = 0; i <sizeof(cmd); i++)
     {
     Serial1.write(cmd[i]);
     }

}

void loop()
{
    sendCommand(command1);
    timer = millis();
    while (!Serial.available() && millis() <= timer + TIMEOUT) SPARK_WLAN_Loop();
    if (millis() >= timer + TIMEOUT) Serial.println("No Response");
    while(Serial1.available()){

            inChar=Serial1.read();
            answer[pos]=inChar;
            pos++;
            answer[pos]=0;
     }
     for(int x=0;x<sizeof(answer);x++){
            Serial.print(answer[x]);
     }
}
2 Likes

So I kind of fried the tx/rx pins on my first spark… (live and learn)

I switched to coding on an arduino nano while I waited for the replacement and got everything working fairly well.

The problem i’m having now is translating the code to be spark compatible. I’m encountering a lot of weird bugs that weren’t (and aren’t) present on the nano.

I have a switch case where all three of these functions are called. e.g.:

case 50:
  SetpointTemp();      
  MainSensorTemp();
  ExternalSensorTemp();
  break;

Here are the functions:

//FUNCTION TO DISPLAY SETPOINT TEMP

void SetpointTemp(){
  char answer[8]={""};
  Serial1.write(SetPoint,3);
  Serial1.flush(); 
  
  while(!Serial1.available());
     Serial1.readBytesUntil('\r',answer,6);
     Serial.print('\n');
     Serial.print("Setpoint Temperature: ");
     Serial.print(answer);
     Serial.println(" C");
     Serial.flush();
}

//FUNCTION TO DISPLAY INTERNAL SENSOR TEMP

void MainSensorTemp(){
  char answer2[8]={""};
  if(MachineState==0){
    Serial.println("Machine is off");
  }else{
    Serial1.write(MainT,3);
    Serial1.flush();
    while(!Serial1.available());
    Serial1.readBytesUntil('\r',answer2,6);
    Serial.print("Internal Temperature: ");
    Serial.print(answer2);
    Serial.println(" C");
    Serial.flush();
  }
}

//FUNCTION TO DISPLAY EXTERNAL SENSOR TEMP

void ExternalSensorTemp(){
  char answer3[8]={""};
  if(MachineState==0){
    Serial.println("Machine is off");
  }else{
    Serial1.write(MainT,3);
    Serial1.flush();
    while(!Serial1.available());
    Serial1.readBytesUntil('\r',answer3,6);
    Serial.print("Sensor Temperature: ");
    Serial.print(answer3);
    Serial.println(" C \n");
    Serial.flush();
  }
}

for whatever reason, when they are printed to the serial monitor, the three values seem to randomly match up with the correct label and there is never any consistency in it. Any ideas? I’ve tried adding delays in between the function calls but that had no effect.

@daflippymaster, looking at the Spark master code I noticed that Serial.flush() is an empty function and does nothing. However, Serial1.flush() does have functional code. I am not sure how that would affecting things but I just wanted to point that out.

Can you provide a sample of the output you are getting so I better understand what it looks like?

Here’s an example of the output

Setpoint Temperature:  C
Internal Temperature: 37.37 C
Sensor Temperature: 37.35 C 

Enter a number: 

Setpoint Temperature: -20.00 C
Internal Temperature:  C
Sensor Temperature: 37.27 C 

Enter a number: 

Setpoint Temperature: 37.25 C
Internal Temperature: -20.00 C
Sensor Temperature:  C 

Enter a number: 

where the setpoint is -20.00, and the internal temp is the lower of the two temperatures

try flushing the serial the other way, looks like you may have the /r from the last read in there still that’s why the blank one, then next time the value is one behind, then one behind again then a /r

change

Serial1.flush();

to this

while (Serial1.available()) Serial1.read(); //throw it away

@Hootie81, thanks! that seems to have done the trick. I’ll definitely have to remember that one.

Only issue I run into now is that it doesn’t print the menu after its connected.

I’ve got it set up like this:

int loopcount=0;
 
void loop(){
  while(loopcount==0){
      Serial.println("Menu");
      Serial.println("1. Turn On");
      Serial.println("2. Current Temperatures");
      Serial.println("3. Set Setpoint");
      Serial.println("4. Custom Program");
      Serial.println("5. Program Options");
      Serial.println("6. Turn Off");
      loopcount++;
 }

 .....more code....
}

not sure why that doesn’t work!

Here is a cut and paste from one of my apps, create a boolean called Menu and set it false. after you do something that will cause the menu to be out of the terminal viewing window you can set Menu = false; and next time the loop runs it will print the menu. I found having it all as one string like this was much much much less flash… BTW \t is a tab so it looks sweet when printed

if (!Menu) {
        Serial.println(
                "\r\n"
                "Settings Menu\r\n"
                "\t1 to Create a new DB\r\n"
                "\t2 to print all DB\r\n"
                "\t3 to Print Log File\r\n"
                "\t4 to Print User details\r\n"
                "\t5 to Set master fingerprint\r\n"
                "\t6 to Set the clock\r\n"
                "\t7 to enter DFU mode\r\n"
                "\tb to return to Main Menu\r\n"
                "\r\n");
        Menu = true;
    }

@daflippymasterm, the menu may not have “appeared” to print if your terminal connected to the Serial port was not open and ready to receive. I like what @Hootie81 suggested and you could also make it so when you hit “m” on the terminal keyboard, it puts prints out the menu. :smile:

Well turns out I had my delay() before my Serial.begin’s, after switching that around it looks like everything works perfect :smile:

You guys have been great so far, I’ll definitely be back if i’ve got any more questions.

2 Likes

So now that i’ve got the control aspect of this mostly working, I think I need a little bit of guidance for the next stage of the project, which is controlling the core from a webpage on a private server (bypassing spark cloud) and then logging data to that server so it can be graphed, etc.

I’ve read through several posts on here about this sort of thing but i’m brand new to networking so i’m having a little bit of trouble figuring out where to start.