Trouble receiving different data through serial from Arduino to Processing

Hello everyone, this is my first time using both processing and arduino and I’m having a bit of trouble with receiving data in processing.
I have a DHT11 temperature and humidity sensor I’m using with my Arduino and I’m sending the temperature (as a float) and the humidity (as an int) through the serial port. I want those two values to be written inside two different boxes but I’m having some problems on the receiving end:
a) The values I receive have a letter at the beginning of them that I need to remove in processing, since I use that letter as identification in another program
b) The temperature has  between the value and “°C”, which I think it’s because the temperature value is a float (the humidity value is received just fine)
c) I can’t figure out how to maintain the values I receive (they disappear after they’ve been received) and separate them into different strings (since I want to print the “%” and the “°C” as well) in processing so I can print them separately into the different text boxes

I have the Arduino code here:

#include <DHT.h>
#define DHTPIN 12
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);


void setup() {
  Serial.begin(9600);
  dht.begin();

}

void loop() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  int H = h;

  Serial.print("t");
  Serial.print(t);
  Serial.print("°C");
  Serial.println("\n");
  Serial.print("H");
  Serial.print(H);
  Serial.print("%");
  Serial.println("\n");
  delay(2000);
}

And I have the processing code here (please ignore the oddly shaped thermometer on the right, that’s something else I’ll try to figure out later):

import processing.serial.*;
Serial myport;
String h;
String t;
int lf = 10;

void setup() {
  size(1920, 1080);
  String portname = Serial.list()[1];
  myport = new Serial(this, portname, 9600); }
  
void draw() {
  rectMode(CENTER);
  noStroke();
  fill(255);
  rect(1460, 680, 150, 400);
  ellipse(1460, 880, 150, 150);
  ellipse(1460, 400, 300, 300);
  
  stroke(0);
  rect(960, 100 , 1000, 160);
  rect(270, 400, 400, 200);
  rect(270, 650, 400, 200); 
  rect(720, 400, 400, 200);
  rect(720, 650, 400, 200);
  


String s = "BT DHT11 Temperature Sensor";
fill(0);
textSize(50);
text(s, 600, 120);

textSize(25);
text("Temperature is", 180, 400);
text("Humidity is", 200, 650);

  while (myport.available()>0) {
    h = myport.readStringUntil(lf);
    t = myport.readStringUntil(lf);
    text(h, 700, 400);
    text(t, 700, 650);

}
delay(100);
}

I appreciate all the help, thank you in advance!

Hello,

Take a look at this topic:
Problem with the use of several sensors, arduino / processing - #5 by glv

The Arduino is sending data that is separated with commas and terminated with a line feed.
The Processing side is receiving one string with the data and separating it.

:)

Hi @Valakas

With a few tweaks your code can run alright:

  1. Your comms is using readBytesUntil(lf), and in the Ard you are explicitly doing println(’\n’). The println() is adding it’s own ‘\r\n’ and confusing things. The \r will end up in your strings in processing, and you don’t want the extra \n. Stop your Procesing sketch and look at the output with the Serial Monitor (Ard IDE ctrl-shift-m). Then change the two println to print, and look again.

  2. Don’t need ‘if (myport.available()>0)’. The readStringUntil (rbu) will wait until it has what you ask for, or return null. So try this:

      h = myport.readStringUntil(lf);
      if (h != null)
      {
        //h = h.substring(0, h.length() - 1);
        println(String.format("H:%s~", h));
      }

The output looks like this

H:t0.50°C
~
  1. See that the ~ is on the next line, because rbu is giving you the lf on the end. Uncomment that substring line and it will remove it.

  2. See that  character. In the Ard code, if you change the 'C symbol to e.g. X the  disappears. Clearly what Ard C++ gives you for 'C doesn’t translate to 'C in Processing. Any character set expert care to explain that? The simple answer would be not to send the units from the Ard, but put them on in Processing.

  3. Put in a similar piece of code for the temperature. See that you have your h and t swapped over. Ard is sending t first, Processing reading h first. Just swap the reading order. Is reliable just to use the values in the order you expect them to be transmitted? Usually it will work, because when the Processing connects to Ard, the Ard resets. Something may happen later and things get out of step, and your numbers will be swapped. Various ways around that e.g. use one rbu statement, look at what arrived, is it ‘t’ or ‘H’ and process accordingly. Another way is to send one string with two values separated by comma, and lf on the end. In Procesing lift out the two values.

  4. Usually ‘delay’ is not used in draw, put frameRate(10) in setup. I don’t know if it makes any real difference, just the normal way.

  5. Why is it flashing? Your Processing code is repeatedly running draw, and drawing the rects each time. Only when something is received from Ard does it write the values. Most of the time you just get the blank rectangles. So only draw the rects when you have a new value.

      h = myport.readStringUntil(lf);
      if (h != null)
      {
        h = h.substring(0, h.length() - 1);
        println(String.format("H:%s~", h));
        fill(255);
        stroke(0);
        rect(720, 400, 400, 200);
        fill(0);
        text(h, 700, 400);
      }

You can do the same for t. Now the whole thing needs a tidy-up, but it should be working.

Hello Richard!

Thank you for your help, I managed to make a steady and reliable serial connection thanks to your tips!

If I can ask you one more thing: I want to fill the thermometer I have on the right to different levels using the temperature value I receive from the Arduino. I still haven’t tried anything and I’m definitely gonna look work on it, but do you have any tips for doing this?

Thank you in advance!

Edit: nevermind, I managed this using the map() function and it works. However, since the temperature doesn’t change much, the changes in the thermometer fill are imperceptible. I’ll attach the code:

t = myport.readStringUntil(lf);
if (t != null) {
  t = t.substring(1, t.length() - 2);
  println(String.format("%s~", t));
  fill(255);
  stroke(0);
  rect(720, 400, 400, 200);
  fill(0);
  text(t+"°C", 700, 400);
  noStroke();
  fill(255);
  rect(1460, 565, 150, 400);
  fill(255,0,0);
  ellipse(1460, 840, 260, 260);
  T = float(t);
  w = map(T, 0, 50, 150, 500);
  rect(1460, 655, 100, w);

Suggestions to make slight changes more visible?

Yes, temperature doesn’t vary much in the short term. Maybe graphs of readings over last day/week?

I’m looking for short term though, since I’m not gonna keep the device active for long at times. Maybe reducing the target range in map()? Or maybe there’s some other way to make a .1°C variation into a 10 or 20 pixel variation?