2

I'm using an arduino to log the temperature from ten PT100s in real time.

My code works fine over short intervals (e.g. 10 minutes), but over longer intervals (e.g. 2-7 hours), specifically on the 63rd temperature logged, Matlab doesn't pick up the full string from the serial print It doesn't matter what sample rate i set it at (I have tried 2.5 mins, 1 min and 5 mins), it always stops working at the 63rd piece of data - specifically the y variable from fscanf only has 2 values in it - one normal looking temperature value and 2.

I changed the code so that when the y string isn't the expected 10 temperature values, it just plots 10 NaN values and keeps going. From this point onwards, it fails to log 10 temperature values exactly once every 4 samples, no matter what I set the sample rate to.

clear all;
clc;
delete(instrfindall); %pre-emptively close all ports
b = serial('COM7','BaudRate',1000000); % COM is the COM port of the Arduino
 %flush input buffer
flushinput(b);

fopen(b);  % initiate arduino communication


%% Create a figure window to monitor the live data
Tmax = 24*60*60; % Total time for data collection (s)
figure,
grid on,
xlabel ('Time (s)'), ylabel('Tempeature (K)'),
%axis([0 Tmax+1]),

%% Read and plot the data from Arduino
Ts = 150; % Sampling time (s)
ii = 0;
dataa = 0;
datab = 0;
t = 0;
tic % Start timer
mData = [];
while toc <= Tmax
    ii = ii + 1;
    %% Read buffer data

    datab = fscanf(b);
    y = strsplit(datab, ',')
    if(length(str2double(y))<10)
        disp("Output length mismatch");
        y = NaN(10,1);
        t1(ii,1) = str2double(y(1));
        t2(ii,1) = str2double(y(2));
        t3(ii,1) = str2double(y(3));
        t4(ii,1) = str2double(y(4));
        t5(ii,1) = str2double(y(5));
        t6(ii,1) = str2double(y(6));
        t7(ii,1) = str2double(y(7));
        t8(ii,1) = str2double(y(8));
        t9(ii,1) = str2double(y(9));
        t10(ii,1) = str2double(y(10));
    else
        t1(ii,1) = str2double(y(1));
        t2(ii,1) = str2double(y(2));
        t3(ii,1) = str2double(y(3));
        t4(ii,1) = str2double(y(4));
        t5(ii,1) = str2double(y(5));
        t6(ii,1) = str2double(y(6));
        t7(ii,1) = str2double(y(7));
        t8(ii,1) = str2double(y(8));
        t9(ii,1) = str2double(y(9));
        t10(ii,1) = str2double(y(10));
        %sTemp = smooth(data,25);
        %% Read time stamp
        % If reading faster than sampling rate, force sampling time.
        % If reading slower than sampling rate, nothing can be done. Consider
        % decreasing the set sampling time Ts

        t(ii) = toc;
        if ii > 1
            T = toc - t(ii-1);
            while T < Ts
                T = toc - t(ii-1);
            end
        end
        t(ii) = toc;
        grid on
        grid minor
        %% Plot live data
        if ii > 1
            x = [t(ii-1) t(ii)];
            %the two values output by the arduino when the sensor is not
            %attached are 38.98 and 1261.79 - changed these values to 0 using
            %logic
            y1 = [(t1(ii-1)*(t1(ii-1)~=30.98)*(t1(ii-1)~=1261.79)) (t1(ii)*(t1(ii)~=30.98)*(t1(ii)~=1261.79))];
            y2 = [(t2(ii-1)*(t2(ii-1)~=30.98)*(t2(ii-1)~=1261.79)) (t2(ii)*(t2(ii)~=30.98)*(t2(ii)~=1261.79))];
            y3 = [(t3(ii-1)*(t3(ii-1)~=30.98)*(t3(ii-1)~=1261.79)) (t3(ii)*(t3(ii)~=30.98)*(t3(ii)~=1261.79))];
            y4 = [(t4(ii-1)*(t4(ii-1)~=30.98)*(t4(ii-1)~=1261.79)) (t4(ii)*(t4(ii)~=30.98)*(t4(ii)~=1261.79))];
            y5 = [(t5(ii-1)*(t5(ii-1)~=30.98)*(t5(ii-1)~=1261.79)) (t5(ii)*(t5(ii)~=30.98)*(t5(ii)~=1261.79))];
            y6 = [(t6(ii-1)*(t6(ii-1)~=30.98)*(t6(ii-1)~=1261.79)) (t6(ii)*(t6(ii)~=30.98)*(t6(ii)~=1261.79))];
            y7 = [(t7(ii-1)*(t7(ii-1)~=30.98)*(t7(ii-1)~=1261.79)) (t7(ii)*(t7(ii)~=30.98)*(t7(ii)~=1261.79))];
            y8 = [(t8(ii-1)*(t8(ii-1)~=30.98)*(t8(ii-1)~=1261.79)) (t8(ii)*(t8(ii)~=30.98)*(t8(ii)~=1261.79))];
            y9 = [(t9(ii-1)*(t9(ii-1)~=30.98)*(t9(ii-1)~=1261.79)) (t9(ii)*(t9(ii)~=30.98)*(t9(ii)~=1261.79))];
            y10 = [(t10(ii-1)*(t10(ii-1)~=30.98)*(t10(ii-1)~=1261.79)) (t10(ii)*(t10(ii)~=30.98)*(t10(ii)~=1261.79))];
            %replace zero values with nan so they will not be plotted
            y1(y1==0) = nan;
            y2(y2==0) = nan;
            y3(y3==0) = nan;
            y4(y4==0) = nan;
            y5(y5==0) = nan;
            y6(y6==0) = nan;
            y7(y7==0) = nan;
            y8(y8==0) = nan;
            y9(y9==0) = nan;
            y10(y10==0) = nan;
            line(x, y1, 'Color', 'red')
            line(x, y2, 'Color', 'blue')
            line(x, y3, 'Color', 'black')
            line(x, y4, 'Color', 'magenta')
            line(x, y5, 'Color', 'green')
            line(x, y6, 'Color', 'blue')
            line(x, y7, 'Color', 'red')
            line(x, y8, 'Color', 'cyan')
            line(x, y9, 'Color', 'black')
            line(x, y10, 'Color', 'magenta')
            legend ('T1','T2','T3','T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10')
            drawnow
        end
    end
end
fclose(b);

The actual results are below. Any help is really appreciated!

(https://www.mathworks.com/matlabcentral/answers/uploaded_files/235007/Capture.png)

(https://www.mathworks.com/matlabcentral/answers/uploaded_files/235006/Capture1.png)

(edit: the images are from mathworks because I posted the same question there last week but didn't receive any responses)


#include <Adafruit_MAX31865.h>
#include<SPI.h>
#include <Wire.h>



// Use software SPI: CS, DI, DO, CLK
//Adafruit_MAX31865 max_1 = Adafruit_MAX31865(A0,12,11,13);
//Adafruit_MAX31865 max_2 = Adafruit_MAX31865(2,12,11,13);
//Adafruit_MAX31865 max_3 = Adafruit_MAX31865(3,12,11,13);
//Adafruit_MAX31865 max_4 = Adafruit_MAX31865(4,12,11,13);
//Adafruit_MAX31865 max_5 = Adafruit_MAX31865(5,12,11,13);
//Adafruit_MAX31865 max_6 = Adafruit_MAX31865(6,12,11,13);
//Adafruit_MAX31865 max_7 = Adafruit_MAX31865(7,12,11,13);
//Adafruit_MAX31865 max_8 = Adafruit_MAX31865(8,12,11,13);
//Adafruit_MAX31865 max_9 = Adafruit_MAX31865(9,12,11,13);
//Adafruit_MAX31865 max_10 = Adafruit_MAX31865(10,12,11,13);

// use hardware SPI, just pass in the CS pin
Adafruit_MAX31865 max_1 = Adafruit_MAX31865(A0);
Adafruit_MAX31865 max_2 = Adafruit_MAX31865(2);
Adafruit_MAX31865 max_3 = Adafruit_MAX31865(3);
Adafruit_MAX31865 max_4 = Adafruit_MAX31865(4);
Adafruit_MAX31865 max_5 = Adafruit_MAX31865(5);
Adafruit_MAX31865 max_6 = Adafruit_MAX31865(6);
Adafruit_MAX31865 max_7 = Adafruit_MAX31865(7);
Adafruit_MAX31865 max_8 = Adafruit_MAX31865(8);
Adafruit_MAX31865 max_9 = Adafruit_MAX31865(9);
Adafruit_MAX31865 max_10 = Adafruit_MAX31865(10);


// The value of the Rref resistor. Use 430.0 for PT100 and 4300.0 for PT1000
#define RREF      430.0
// The 'nominal' 0-degrees-C resistance of the sensor
// 100.0 for PT100, 1000.0 for PT1000
#define RNOMINAL  100.0
float kelvin1;
float kelvin2;
float kelvin3;
float kelvin4;
float kelvin5;
float kelvin6;
float kelvin7;
float kelvin8;
float kelvin9;
float kelvin10;

void setup() {
  Serial.begin(115200);
  Wire.begin();


  //Serial.println("Adafruit MAX31865 PT100 Sensor Test!");
  max_1.begin(MAX31865_4WIRE);  // set to 2WIRE or 4WIRE as necessary
  max_2.begin(MAX31865_4WIRE);
  max_3.begin(MAX31865_4WIRE);
  max_4.begin(MAX31865_4WIRE);
  max_5.begin(MAX31865_4WIRE);
  max_6.begin(MAX31865_4WIRE);
  max_7.begin(MAX31865_4WIRE);
  max_8.begin(MAX31865_4WIRE);
  max_9.begin(MAX31865_4WIRE);
  max_10.begin(MAX31865_4WIRE);
}


void loop() {

  uint16_t rtd1 = max_1.readRTD();
  uint16_t rtd2 = max_2.readRTD();
  uint16_t rtd3 = max_3.readRTD();
  uint16_t rtd4 = max_4.readRTD();
  uint16_t rtd5 = max_5.readRTD();
  uint16_t rtd6 = max_6.readRTD();
  uint16_t rtd7 = max_7.readRTD();
  uint16_t rtd8 = max_8.readRTD();
  uint16_t rtd9 = max_9.readRTD();
  uint16_t rtd10 = max_10.readRTD();

  //  Serial.print("RTD value: "); Serial.println(rtd);
  float ratio1 = rtd1;
  ratio1 /= 32768;
  float ratio2 = rtd2;
    ratio2 /= 32768;
    float ratio3 = rtd3;
    ratio3 /= 32768;
    float ratio4 = rtd4;
    ratio4 /= 32768;
    float ratio5 = rtd5;
    ratio5 /= 32768;
    float ratio6 = rtd6;
    ratio6 /= 32768;
    float ratio7 = rtd7;
    ratio7 /= 32768;
    float ratio8 = rtd8;
    ratio8 /= 32768;
    float ratio9 = rtd9;
    ratio9 /= 32768;
    float ratio10 = rtd10;
    ratio10 /= 32768;

  kelvin1 = (max_1.temperature(RNOMINAL, RREF)) + 273;
  kelvin2 = (max_2.temperature(RNOMINAL, RREF))+273;
    kelvin3 = (max_3.temperature(RNOMINAL, RREF))+273;
    kelvin4 = (max_4.temperature(RNOMINAL, RREF))+273;
    kelvin5 = (max_5.temperature(RNOMINAL, RREF))+273;
    kelvin6 = (max_6.temperature(RNOMINAL, RREF))+273;
    kelvin7 = (max_7.temperature(RNOMINAL, RREF))+273;
    kelvin8 = (max_8.temperature(RNOMINAL, RREF))+273;
    kelvin9 = (max_9.temperature(RNOMINAL, RREF))+273;
    kelvin10 = (max_10.temperature(RNOMINAL, RREF))+273;

  //Serial.print("Ratio = "); Serial.println(ratio1,8);
  Serial.print(kelvin1);
  Serial.print(", ");
  Serial.print(kelvin2);
    Serial.print(", ");
    Serial.print(kelvin3);
    Serial.print(", ");
    Serial.print(kelvin4);
    Serial.print(", ");
    Serial.print(kelvin5);
    Serial.print(", ");
    Serial.print(kelvin6);
    Serial.print(", ");
    Serial.print(kelvin7);
    Serial.print(", ");
    Serial.print(kelvin8);
    Serial.print(", ");
    Serial.print(kelvin9);
    Serial.print(", ");
    Serial.print(kelvin10);
    Serial.print(", ");


  Serial.println();

  /*
      // Check and print any faults
      uint8_t fault = max_1.readFault();
      if (fault) {
        Serial.print("Fault 0x"); Serial.println(fault, HEX);
        if (fault & MAX31865_FAULT_HIGHTHRESH) {
          Serial.println("RTD High Threshold");
        }
        if (fault & MAX31865_FAULT_LOWTHRESH) {
          Serial.println("RTD Low Threshold");
        }
        if (fault & MAX31865_FAULT_REFINLOW) {
          Serial.println("REFIN- > 0.85 x Bias");
        }
        if (fault & MAX31865_FAULT_REFINHIGH) {
          Serial.println("REFIN- < 0.85 x Bias - FORCE- open");
        }
        if (fault & MAX31865_FAULT_RTDINLOW) {
          Serial.println("RTDIN- < 0.85 x Bias - FORCE- open");
        }
        if (fault & MAX31865_FAULT_OVUV) {
          Serial.println("Under/Over voltage");
        }
        max_1.clearFault();
      }
  */
  delay(50);

}

  • 1
    A tip: don't use variables as `t1, t2, t3` etc. This is called dynamic variable naming, and [will eventually get you into trouble](https://stackoverflow.com/a/32467170/5211833). Instead, use a single variable `t`, and give that a 3rd dimension, or, if the matrices are not the same size, use cells or structs. This will result in less hand-copying of lines, more readable code, faster code, and less hard to find bugs. – Adriaan Aug 27 '19 at 09:28
  • 2
    Whenever I see an issue near a power of 2 (e.g, the 16th/32nd/64th/... *thing*), I start wondering if there is a memory issue somewhere. It's good that you've isolated your issue to concerning every 63rd sample, I suspect somewhere your buffer runs out of space and resets (or something similar), I say this without knowing anything about reading from a serial Arduino port! – Wolfie Aug 27 '19 at 09:30
  • 1
    Why are you using a `1000000` baudrate ? From the arduino doc: `Supported baud rates are 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, 57600, and 115200.` Also I would avoid using the maximal baudrate if it's not necessary. – obchardon Aug 27 '19 at 10:10
  • @obchardon because my supervisor suggested it to see if it made a difference. the problem was the same at lower baud rates – Amy Fawcett Aug 27 '19 at 10:12
  • So as explained by @Wolfie there is probably a memory issue. You should also post your arduino code. – obchardon Aug 27 '19 at 10:33
  • You are performing quite some floating point calculations on the Arduino, but are not using these variables (`ratio1` etc.) after they are calculated. What happens if you remove this? Use baud rate `115200`. In general, avoid performing floating point calculations on Arduino's, especially if you are transferring data to a pc, which can handle this much better. – rinkert Aug 27 '19 at 11:57
  • Do you know for sure if the problem is with Matlab, or whether the Arduino just starts to send zeros after a long time? (easy check just using a serial monitor for a couple hours) If the problem is reading the sensors on the Arduino, you could implement a watchdog timer (/trigger the watchdog), which will reset the Arduino. – rinkert Aug 27 '19 at 12:09
  • @rinkert it's definitely matlab, the Arduino is still outputting data once the problem starts occurring (I checked) – Amy Fawcett Aug 27 '19 at 12:29

1 Answers1

2

So, I checked out @Wolfie's suggestion (and found that an Arduino nano's buffer is 64 bits, fitting this theory) and added

flushinput(b);

after reading the values from the serial input, to flush the input buffer. Just tested it out and it works perfectly - thanks for your help!

  • 1
    Glad I could help! Once you hit these problems a couple of times, you begin to develop a wariness towards 2^n (or 2^n-1 for 0-based systems) – Wolfie Aug 27 '19 at 15:17