Receiving float LM35 data via bluetooth and nano

Hi,

Are there any ways to improve how I send and received float data coming via 2 HC-05 bluetooth modules in master and slave configuration?

I have a LM35 and a HC-05 slave module connected to my nano sending float temperature data to my master HC-05 module connected to my Uno. Initially, I had a difficult time understanding serial input and outputs but I manage to program both my modules to send and receive floating temperature data from my LM35. The problem is that I end up receiving a lot of 0.00 before the actual code which is a nuisance that I have to add an if-statement in my master code to filter it. I know it’s a shortcut but I’m confuse as to how to properly received float data

Master

float state = 0;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(38400);
}

void loop() {
  // put your main code here, to run repeatedly:
   if(Serial.available() > 0){ // Checks whether data is comming from the serial port
    state = Serial.parseFloat(); // Reads the data from the serial port
   }
   if ((state != 0.00)){
   Serial.print(state);
   Serial.println("\n");
   }
}

Slave

const byte tempSensor = A1; //LM35 temp sensor
int sourceVoltPin = 5;
int state = 20;

const float celcius = 0.1039;//0.107421875;
unsigned long previousTime_0 = 0;
const long eventTime_0_temp = 500;


void setup() {
  // put your setup code here, to run once:
  analogReference(INTERNAL);
  pinMode(sourceVoltPin, OUTPUT);
  digitalWrite(sourceVoltPin, HIGH);
  Serial.begin(38400);
}

void loop() {

    unsigned long currentTime = millis();
    float temp = analogRead(tempSensor)*celcius;

    if(Serial.available() > 0){ // Checks whether data is comming from the serial port
    state = Serial.read(); // Reads the data from the serial port
  }
    if (currentTime - previousTime_0 >= eventTime_0_temp) {
    //Serial.println("Temp: ");
    //Serial.println(temp);
    Serial.print(temp);
    Serial.print(',');
    
    previousTime_0 = currentTime;
  }
}

I’ve looked into tutorials and discussions regarding this and while it works in my case, I can’t remove the feeling that I may be doing something wrong especially in the way I’m receiving data. Is there another approach to receiving float data? In some tutorials, they add #include <SoftwareSerial.h> or #include <AltSoftSerial.h> in their code, do I have to do that as well? Do I have to receive it as char type first then use atof()? If yes, how do I add that to my program in a way that it’s less confusing since the part with using char and atof() is difficult to understand?

See the serial input basics tutorial for some ideas on how to send and receive your data.

I use software serial with my HC05 project so that I can use hardware serial (USB) for program upload, debugging and monitoring variable values and program flow.

groundFungus:
I use software serial with my HC05 project so that I can use hardware serial (USB) for program upload, debugging and monitoring variable values and program flow.

When I use software serial, do I have to use a different pin for rx and tx?

Yes, you can not use pins 0 and 1 for software and hardware serial. In he following example, I use pin 4 (RX) and pin 7 (TX) for the software serial port.

Here is example code to read a LM35 on the slave and send to the master. This code uses the (modified) second example from serial input basics tutorial to receive the serial data. Use your method for reading the temperature sensor. This example is more for sending and receiving the data.

Master (receives the temperature data)

#include <SoftwareSerial.h>

SoftwareSerial bt(4, 7);

const byte numChars = 12;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup()
{
   Serial.begin(115200);
   bt.begin(38400);
}

void loop()
{

   recvWithEndMarker();
   showNewData();
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (bt.available() > 0 && newData == false)
   {
      rc = bt.read();
      //Serial.print(rc);
      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

void showNewData()
{
   if (newData == true)
   {
      Serial.print("Temperature = ");
      float tempC = atof(receivedChars);
      Serial.println(tempC);
      newData = false;
   }
}

Slave (sends temperature data)

#include <SoftwareSerial.h>

const byte sensorPin = A1;

SoftwareSerial bt(4, 7);

void setup()
{
   Serial.begin(115200);
   bt.begin(38400);   
}

void loop()
{
   static unsigned long timer = 0;
   unsigned long interval = 1000;
   if (millis() - timer >= interval)
   {
      timer = millis();
      unsigned int vout = analogRead(sensorPin);
      float tempC = (vout * 500.00) / 1023;
      Serial.print("temp C = ");
      Serial.println(tempC);
      bt.println(tempC);      
   }
  
}

groundFungus:
Master (receives the temperature data)

#include <SoftwareSerial.h>

SoftwareSerial bt(4, 7);

const byte numChars = 12;
char receivedChars[numChars];  // an array to store the received data

boolean newData = false;

void setup()
{
  Serial.begin(115200);
  bt.begin(38400);
}

void loop()
{

recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker()
{
  static byte ndx = 0;
  char endMarker = ‘\n’;
  char rc;

while (bt.available() > 0 && newData == false)
  {
      rc = bt.read();
      //Serial.print(rc);
      if (rc != endMarker)
      {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars)
        {
            ndx = numChars - 1;
        }
      }
      else
      {
        receivedChars[ndx] = ‘\0’; // terminate the string
        ndx = 0;
        newData = true;
      }
  }
}

void showNewData()
{
  if (newData == true)
  {
      Serial.print("Temperature = ");
      float tempC = atof(receivedChars);
      Serial.println(tempC);
      newData = false;
  }
}

In your master code, what does the “recvWithEndMarker()” function do?
What is the purpose having “Serial.begin(115200)” and “bt.begin(38400)”? Is the “Serial.begin(115200)” for the serial connection to arduino and “bt.begin(38400)” for pins 4 and 7?

Serial.begin(115200) starts the hardware serial port. The bt.begin(38400) starts the software serial port. The software serial port uses pins 4 and 7.

The recvWithEndMarker() function reads each character as it arrives and adds it to the receivedChars string (character array) until the end marker (\n or line feed) is received. Then a flag is set to tell the main program that new data is available.

groundFungus:
Serial.begin(115200) starts the hardware serial port. The bt.begin(38400) starts the software serial port. The software serial port uses pins 4 and 7.

Ohh, I get it. Thanks for this

groundFungus:
The recvWithEndMarker() function reads each character as it arrives and adds it to the receivedChars string (character array) until the end marker (\n or line feed) is received. Then a flag is set to tell the main program that new data is available.

Does it separate the string from the float or does it compiles each character to an array then sends it as a string to showNewData() function?

I also tried using the master code you provided to my module and nothing is being printed in the serial monitor. Is there a step that I'm missing?

The only change I did was changing my rx and tx pin to pin 4 and 7.

Did you use the slave code that I posted to send data? Did you set both of the HC05s to use software serial?

The posted master and slave code was tested on 2 Uno's with (paired) HC05 modules and is known to work.

Can you post schematics to show your wiring of the master and slave.

Yes, once the end marker is received, the data goes to the showNewData function where the string is converted to a float number (atof) and displayed.

groundFungus:
Did you use the slave code that I posted to send data? Did you set both of the HC05s to use software serial?

The posted master and slave code was tested on 2 Uno's with (paired) HC05 modules and is known to work.

It did run, at first I was getting gibberish text and I thought it was my connections. My baud rate in my serial monitor was 38400 but when I change the baud rate to 115200, the gibberish became the expected output.

Why is the baud rate of the serial monitor at 115200 when the baud rate of the HC-05 modules are at 38400? Does the temp data receive by the HC-05 become arduino data first before being printed in the serial monitor at the baud rate arduino is at?

1. Build the following setup (Fig-1) among UNO, HC05-M, NANO, HC05-S, and LM35.


Figure-1:

2. UNO and NANO will be communication using BTs being connected by Software Serial Ports (SUART) as the Hardware Serial Ports are engaged with IDE/Serial Monitor/PC. Note that SUART Ports work well at 9600 Bd.

3. Check that HC05-M of UNO is paired with HC05-S of NANO.
4. Upload the following sketch in UNO (the Receiver). (tested without BT)

#include<SoftwareSerial.h>
SoftwareSerial SUART(10, 11);  //SRX = DPin-10, STX = 11
char myData[20];

void setup()
{
  Serial.begin(115200);
  SUART.begin(9600);
}

void loop()
{
  byte n = SUART.available();
  if(n != 0)   //ASCII codes data bytes are arriving from transmitter
  {
    byte m = SUART.readBytesUntil('\n', myData, 20); //save in arry
    myData[m] = '\0'; //null-byte as last element in array myData[].
    Serial.print("Showing received Temp: ");
    Serial.println(myData);    //show received temp on Serial Monitor
    //---------------------------------------------------------------QQ
    Serial.print("Showing computed Temp: ");
    float myTemp = atof(myData);  //ASCII coded temp into float temp
    Serial.println(myTemp, 1); //show computed temp on Serial Monitor with 1-digit after decimal point
    memset(myData, 0, 20);     //put 0s in all locations of myData[]
    Serial.println("=============================");
  }
}

5. Upload the following sketch in NANAO (the Transmitter).

#include<SoftwareSerial.h>   //include this Library for the functions/methods of SUART Port
SoftwareSerial SUART(10, 11);         //constructor: SRX = DPin-10, STX = 11

void setup() 
{
  Serial.begin(115200);   //bits/sec for Hardware UART Port
  SUART.begin(9600);     //bit/ses for Software UART Port (SUART Port); it works well at this speed
  analogReference(INTERNAL);  //volatge at Vref pin of ADC is 1.1V
}

void loop() 
{
  
  float myTemp = (float)100*(1.1/1023.0)*analogRead(A1);  //myFloat holds temp in 32-bit IEEE-754 format
  Serial.println(myTemp, 1);  //show temperature on Serial Monitor of NANO with 1-digit after decimal point
  SUART.print(myTemp, 1);   //sends 4-byte ASCII codes of temp of this fromat: xx.x to UNO
  SUART.print('\n');              //send 0x0A to UNO as terminating charcater
  delay(1000); //1 second delay
}

6. Check that Serial Monitor of UNO shows temperature being sent by NANO and gets updated by 1-sec.
sm91.png
Figure-2:

sm91.png

refer_pin:
Why is the baud rate of the serial monitor at 115200 when the baud rate of the HC-05 modules are at 38400? Does the temp data receive by the HC-05 become arduino data first before being printed in the serial monitor at the baud rate arduino is at?

Because the hardware serial port can manage that speed so why go slower? Software serial can't.