Buffering issues with HC-05

Hello everyone!
I'm a beginner at arduino and bluetooth things. I'm trying to make a project that reads thermometer temperatures and graphs them in real time, at the same time, a .csv file is saved to the local device memory with the read values. All works fine, except that the readings are slow sometimes, when I start to increase or lower the temperature, aberrant values appear on the received text, which are visualized both in the graphs and in the spreadsheet. That's shown below.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>

// Pino ao qual o barramento dos sensores está conectado
#define ONE_WIRE_BUS 4

String trocaDados;

// Configura o objeto OneWire para comunicar com qualquer dispositivo OneWire
OneWire oneWire(ONE_WIRE_BUS);
SoftwareSerial bluetooth(2, 3);

// Passa a referência do objeto OneWire para o objeto DallasTemperature
DallasTemperature sensors(&oneWire);

// Número máximo de sensores que você espera conectar
#define MAX_SENSORS 10

DeviceAddress sensorAddresses[MAX_SENSORS];

// PORTAS DIGITAIS DOS LEDS
int numSensors;
int ledSens1 = 5;
int ledSens2 = 6;
int ledLeit = 7;

void setup() {
  // Inicia a comunicação serial
  bluetooth.begin(9600);
  Serial.begin(9600);
  Serial.println("Inicializando...");

  // Configura os pinos dos LEDs como saída
  pinMode(ledSens1, OUTPUT);
  pinMode(ledSens2, OUTPUT);
  pinMode(ledLeit, OUTPUT);

  // Inicia a biblioteca DallasTemperature
  sensors.begin();

  // Procura por sensores no barramento
  numSensors = sensors.getDeviceCount();
  Serial.print("Número de sensores encontrados: ");
  Serial.println(numSensors);

  // Armazena os endereços dos sensores encontrados
  for (int i = 0; i < numSensors && i < MAX_SENSORS; i++) {
    if (sensors.getAddress(sensorAddresses[i], i)) {
      Serial.print("Sensor ");
      Serial.print(i + 1);
      Serial.print(" encontrado com endereço: ");
      printAddress(sensorAddresses[i]);
      Serial.println();
    } else {
      Serial.print("Sensor ");
      Serial.print(i + 1);
      Serial.println(" não encontrado.");
    }
  }
}

void loop() {
  trocaDados = "";

  // Solicita leitura de temperatura de todos os sensores
  sensors.requestTemperatures();
  
  // Verifica a presença dos sensores e acende os LEDs correspondentes
  if (sensors.getAddress(sensorAddresses[0], 0)) {
    digitalWrite(ledSens1, HIGH);
  } else {
    digitalWrite(ledSens1, LOW);
  }

  if (sensors.getAddress(sensorAddresses[1], 1)) {
    digitalWrite(ledSens2, HIGH);
  } else {
    digitalWrite(ledSens2, LOW);
  }

  // Exibe as temperaturas lidas
  for (int i = 0; i < numSensors && i < MAX_SENSORS; i++) {
    float endTemp = sensors.getTempC(sensorAddresses[i]);
    if (endTemp > -55 && endTemp < 200) {
      Serial.print("Temperatura do Sensor ");
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(endTemp);
      Serial.println(" °C");

      trocaDados += String(endTemp, 2);
      if (i != numSensors - 1) {
        trocaDados += ",";
      }
    }
  }

  Serial.println(trocaDados);
  bluetooth.println(trocaDados);

  // Acende o LED de leitura durante a leitura
  digitalWrite(ledLeit, LOW);
  delay(100);
  digitalWrite(ledLeit, HIGH);
}

// Função para imprimir o endereço de um sensor
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

Can someone help me to fix those mesures?



QTA00.aia (6.4 KB)

For the benefit of the board, here are your blocks:

I see from your .aia that you have a BlueTooth Delimiter of 10, and a 10 millisecond Clock Timer, and you are reading one line at at a time, so that part's okay.

I couldn't tell from your sketch how many sensors you were sending per line, but if there were two per line, you were parsing them correctly.

I did not see this event block in your blocks, however:
component_event

It's necessary to help coordinate those Append to File operations you were machine gunning off the 10 ms input stream.

I'm guessing that green arrow highlight of yours is where one file write stepped on the heels of the previous file write, which did not have time to complete.

A more robust technique would be to take each line of text that you would have appended directly to the file, and add it to the end of a global list (initially empty list), and use a text JOIN With Separator \n block to convert the list into a full CSV text that you could write to the file in a single shot. That would eliminate the timing problem.

It would also guarantee a \n after each reading, which I am not convinced the File Append block is giving you.

Also, I see you are being selective about the incoming values, only accepting those in the range -10 to 200, and using the prior reading if out of range.

With that approach, you could end up with a clipping effect in your data collection, and lose information about how far out of range the data went.

You could run the unclipped data through a separate routine to clip it, to get the best of both worlds.

Here are my suggested revisions:





QTA00.aia (6.8 KB)

First of all, thanks a lot for your help! And these blocks actually ran pretty well, the sheets didn't have any aberrant values at all, even though I stressed the sensors.
The only problem that remains now is the lag in the registration of the measured values. Do you know any way to "keep the time running" and make the registered values respect this? Let me be more clear, if the software is able to record 1 reading at 2 seconds, fail to do this at the following 3 seconds and successfully record a reading at the 5th second, I want the sheet to have the first measurement at 2 seconds and the second one just at 5 seconds, what gives me 2 lines inside the sheet.
I need to do this because I want to maintain a strict timing.
I see that the big problem is that most of the received values are incomplete, so the program won't read them due to the is number? block. How can I overcome this?

You would need to make changes upstream for this.

For completeness, you would need to include these 3 items in each message:

  • Originating timestamp (unix milliseconds?)
  • thermometer identifier (i?)
  • reading for that thermometer

Use commas between items, and a \n at the end (println()) to ease message reception and parsing.

That puts a little more burden on the graphing code, since it is now receiving a spatter. The AI2 charts component has such an option.

Thanks for the advice! I tried using a timestamp at each message sent by the Arduino. I made an approximation of the time taken for each loop, and it worked fine. Now I just have to figure out how to print the exact time between each print, because they're not regular due to the termometers.

If you use an AI2 line or scatter chart, you can add a ChartData subcomponent for each thermometer.

If you remember when you started data collection, you can use seconds or milliseconds from the start of recording as your x value for each (x,y=temperature) pair .

The points on the different ChartData lines won't line up vertically because the data arrives out of sync, but you still get to see how the lines on the graph vary relative to each other.