arduino to arduino serial without blocking sensor data communication

For my solar control I need to send sensor data in the form of ints and floats between 2 arduinos. I am using Robin2’s method as the modbus and PID control needs to have a fast loop time to work well.

I am trying to get the data transmission working using 2 leonardos and a 10K thermistor as a sensor. Using Serial.print I can get the data to transmit and display correctly however I need to send numbers greater than 255 which I understand is not possible with Serial.print. I can get Serial.write to sent the data and display correctly on the RX arduino however I cannot get the sensor data to transmit correctly - only chars typed into a string. So my problem is how to get the sensor data to transmit from the TX arduino to the RX arduino and parse correctly.

TX code with 10K sensor and timer:

#include <elapsedMillis.h>
//=============================================================================control panel
# define sensorArrayReadingDelay  5
elapsedMillis timer0;                                           // temperature sensor sample interval (msec)
#define interval 1000                                           // the interval in mS 
//===============================================================================10k thermistor declarations
#define floorOutTempPin          A0                              // thermistors analog pins 
int floorOutTemp;
//===============================================================================TX
int testInt = 123456;
float testFloat = 123.45;
//=================================================================================
//int *ptr;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////setup
void setup() {
  timer0 = 0;                                                       // clear the timer at the end of startup
  Serial.begin(9600);
  Serial1.begin (9600);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////loop
void loop() {

  if (timer0 > interval) {
    timer0 -= interval;                                               //reset the timer
    takeSensor1Reading ();                                             //takeSensorReading = function
    Serial.println (floorOutTemp);
    Serial1.write ('<');
    Serial1.write ("text,12345,1234.56");
    //Serial1.write ("text,&testInt,1234.56");
    Serial1.write ('>');
  }
}
//==================================================================================10K sensor reading functions
void takeSensor1Reading () {                           // floor outlet sensor

#define nominalThermistorResistance    10000           // resistance at nominal temperature C = 10000 kohm  
#define nominalTemperatureResistance   25              // temperature for nominal resistance = 25 C
#define numberOfSamples                50              // # of samples for smoothing
#define betaCoefficient                3850            // The beta coefficient of the thermistor SAS-10 = 3850
#define fixedResistorValue             10000           // resistance of fixed resistor = 10000 kohm

  float tempF;
  int TempF;
  int samples[numberOfSamples];
  uint8_t i;
 // int floorOutTemp;
  float average;
  //smoothing temperature sensor / temperature calculation
  for (i = 0; i < numberOfSamples; i++) {              // take N samples in a row, with a slight delay
    samples[i] = analogRead(floorOutTempPin);
    delay (sensorArrayReadingDelay);
  }
  average = 0;
  for (i = 0; i < numberOfSamples; i++) {
    average += samples[i];
  }
  average /= numberOfSamples;                         // average all the samples out
  average = 1023 / average - 1;                        // convert the average ADC value to resistance
  average = fixedResistorValue / average;
  //=====================================================convert resistance to temperature
  float steinhart;
  steinhart = average / nominalThermistorResistance;             // (R/Ro)
  steinhart = log(steinhart);                                    // ln(R/Ro)
  steinhart /= betaCoefficient;                                  // 1/B * ln(R/Ro)
  steinhart += 1.0 / (nominalTemperatureResistance + 273.15);    // + (1/To)
  steinhart = 1.0 / steinhart;                                   // Invert
  steinhart -= 273.15;                                           // convert to C
  steinhart *= 1.8;
  steinhart += 32;                                               // convert to F
  tempF = steinhart;
  tempF = tempF - ((tempF - 75) / 15);                           // calibration calculation to fit resistance curve
  tempF = tempF -= 1;                                            // fudge factor
  TempF = (int)tempF;
  floorOutTemp = TempF;
}

RX code with lcd

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
//---------------------------------------------------------------------------------------------------------LCD
LiquidCrystal_I2C lcd1(0X20, 20, 4);              // set the LCD address to 0X20 for a 20 chars and 4 line display for lcd
//----------------------------------------------------------------------------------------------------------RX
// Receive with start- and end-markers combined with parsing
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use by strtok() function
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;
boolean newData = false;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////SETUP
void setup() {
  lcd1.init ();                                   // lcd setUp LCD1 display
  lcd1.backlight ();
  lcd1.display ();
//---------------------------------------------------------------------------------------------------------Searial
  Serial.begin(9600);
  Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
  Serial.println("Enter data in this style <text,12,24.7>  ");
  Serial.println();

  Serial1.begin(9600);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////LOOP
void loop() {
  lcd1.setCursor (0, 0 );
  lcd1.print ("This is a test");

  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() replaces the commas with \0
    parseData();
    showParsedData();
    newData = false;
  }
}
//============
void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}
//============
void parseData() {
  // split the data into its parts
  char * strtokIndx; // this is used by strtok() as an index
  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ",");
  floatFromPC = atof(strtokIndx);     // convert this part to a float
}
//============
void showParsedData() {
  Serial.print("Message ");
  Serial.println(messageFromPC);
  Serial.print("Integer ");
  Serial.println(integerFromPC);
  Serial.print("Float ");
  Serial.println(floatFromPC);

  lcd1.setCursor (0, 1 );
  lcd1.print ("Message ");
  lcd1.setCursor (10, 1 );
  lcd1.print (messageFromPC);
  lcd1.setCursor (0, 2 );
  lcd1.print ("Integer ");
  lcd1.setCursor (10, 2 );
  lcd1.print (integerFromPC);
  lcd1.setCursor (0, 3 );
  lcd1.print ("Float ");
  lcd1.setCursor (10, 3 );
  lcd1.print (floatFromPC);
}

What I can’t do is get TX variable floorOutTemp to transmit and dynamically update to the RX arduino.

I will be grateful for any help as I have pretty much deadended on this problem. I have removed much of my whitespace as others have not liked it in the past.

Thanks for any replies
Will

These

    Serial1.write ('<');
    Serial1.write ("text,12345,1234.56");
    //Serial1.write ("text,&testInt,1234.56");
    Serial1.write ('>');

should all be Serial1.print()

…R

Hi Robin2,

Thanks for the reply. I read a comparison of Serial.print and Serial.write in this topic -

http://forum.arduino.cc/index.php?topic=42603.0

and they stated -

"According to the documentation, Serial.print(value, BYTE) converts the value to the ASCII character that corresponds to value, and sends that character. Therefore, it is valid only for values that are in the range 0 to 255.

Serial.write, on the other hand, streams the bit pattern for value. Therefore, it will send any one-byte value as is."

I will try Serial.print in my solar control sketch instead of Serial.write and see how it works. Sometimes I have to transfer int data values which are in the 4000+ range.

I am very impressed with your work coding the Serial Input Basics topic. Thank You for helping me and others with this subject.

Will

In a way you have got the concept back to front.

It is Serial.write() that sends the value (0-255) of a byte as binary data.

Serial.print converts a number (byte, int, long) into its ascii representation. For example this

int myVal = 12345;
Serial.print(myVal);

will produce the characters "12345" and that is the sort of thing my recvWithStartEndMarkers() expects.

There are certainly times when it can be useful to send binary data. And, for example, the value 12345 would have to be sent as 2 bytes and the receiving program would have to be designed to interpret the two bytes correctly. However unless there is a real need to do it like that it is much easier to debug programs that send data in human readable format.

...R

Reworked my RX and TX sketches last night and they are working great. The data is parsing and the sensors are transmitting very well.

Thank You Robin2

Will