Arduino get not the whole number sending from App Inventor

Hi
Hope to find any help from you.
With App Inventor I readout via bluetooth the temp and humidity from a Arduino with sensor. It works fine. When I send a number, for example 21, to set a limit for the temp to switch on a relays, I get the following problem:

SerialMonitor is reading:

25;46
25;46
25;46
...

That is ok and it split it into 25 for temp and 46 for hum.
When I send 21 for example, I see on SerialMonitor:

25;46
25;46
225;46 (reading the first number only)!
25;46
125;46 (reading the second number only)!
25;46
...

Does anybody know why the number (21) is not receiving together?
(Sorry for my English).

Мабуть, тому, що 21 передається не як одне число, а як два окремі символи: "2" та "1"

1 Like

Show Arduino and App Inventor code.

Hi Juan_Antonio
Here the Arduino code:

#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include "dht.h"
#define dataPin A0
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
dht DHT;

int temp;
int hum;
char incoming_value = 0;

void setup()
{
Serial.begin(9600);
Serial.println("Ready");
pinMode(13, OUTPUT);
digitalWrite(13, LOW);

lcd.begin(16,2);
lcd.setCursor(0,0);
delay(2000);
lcd.clear();
}

void loop()
{
if(Serial.available())
{
incoming_value = Serial.read();
Serial.print (incoming_value);
Serial.print(";");
if(temp < incoming_value){ digitalWrite(13, HIGH);}
if(temp > incoming_value){ digitalWrite(13, LOW);}
}
int readData = DHT.read11(dataPin);

hum = DHT.humidity;
temp = DHT.temperature;

lcd.setCursor(0,0);
lcd.print("Humidity: ");
lcd.print(hum);
lcd.print(" %");

lcd.setCursor(0,1);
lcd.print("Temp: ");
lcd.print(temp);
lcd.print((char)223); //degree symbol
lcd.print("C ");

Serial.print(temp); //send Temperature to MIT App
Serial.print(";");
Serial.print(hum); //send Humidity to MIT App
Serial.println(";");
delay(1000);
}

Here the blocks from App Inventor (hope you can read it):

Please see the Delimiter article in FAQ

Be sure to use println() at the end of each message to send from the sending device, to signal end of message. Do not rely on timing for this, which is unreliable.

In the AI2 Designer, set the Delimiter attribute of the BlueTooth Client component to 10 to recognize the End of Line character.
BlueToothClient1_Properties
Also, return data is not immediately available after sending a request,
you have to start a Clock Timer repeating and watch for its arrival in the Clock Timer event. The repeat rate of the Clock Timer should be faster than the transmission rate in the sending device, to not flood the AI2 buffers.

In your Clock Timer, you should check

  Is the BlueTooth Client still Connected?
  Is Bytes Available > 0?
     IF Bytes Available > 0 THEN
       set message var  to BT.ReceiveText(-1) 

This takes advantage of a special case in the ReceiveText block:

ReceiveText(numberOfBytes)
Receive text from the connected Bluetooth device. If numberOfBytes is less than 0, read until a delimiter byte value is received.

If you are sending multiple data values per message separated by | or comma, have your message split into a local or global variable for inspection before trying to select list items from it. Test if (length of list(split list result) >= expected list length) before doing any select list item operations, to avoid taking a long walk on a short pier. This bulletproofing is necessary in case your sending device sneaks in some commentary messages with the data values.

1 Like

Thank you vy much AGB for your help.

Did read and set the DelimiterByte to 10, and Serial.print to Serial.println in Arduino code. But it's the same effect when I print 18:

...
25
;
42
;
1 (first number of 18)
;
25
;
42
;
8 (second number of 18)
;
25
;
42
...

Well, I think this project is too difficult for me. Of course I can implement a static threshold in the Arduino code, no problem. But it would have been nice if I could set the switch-on temperature for the relay via the AppInventor. That way I would be flexible.
Unfortunately, I haven't found a tutorial for this yet.

Anyway thanks a lot for helping.

@Hagi

Use String instead of Byte.

If you have Clock, remember that the Interval must be less than the Arduino Delay.

Here are several examples.

Hello Hagi

"BytesAvallableToReceive" is a true/false flag.
You are also complicating the local variable initialization :upside_down_face:
Since the Clock Timer is effectively a loop, I would suggest using Global variables, then they are initialized only once, but that is minor.

Try something like this example:

1 Like

Attached is your Sketch with some corrections.

GetVals.txt (1.8 KB)

#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include "dht.h"
#define dataPin A0
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
dht DHT;

int temp;
int hum;
int readData;
char incoming_value = 0;
unsigned long lgUpdateTime;

void setup()
{
         Serial.begin(9600);
         //Serial.println("Ready");
         pinMode(13, OUTPUT);
         digitalWrite(13, LOW);
         
         lcd.begin(16,2);
         lcd.setCursor(0,0);
         delay(2000);
         lcd.clear();
         
         lgUpdateTime = millis();
}

void loop()
{
         //Excute loop every 10 seconds
	     if((millis() - lgUpdateTime) > 10000) 
         {
               lgUpdateTime = millis();

               if (Serial.available() > 0)
               {
                         incoming_value = Serial.read();
                         //Serial.print (incoming_value);
                         //Serial.print(";");

                         if(temp < incoming_value){ digitalWrite(13, HIGH);}
                         if(temp > incoming_value){ digitalWrite(13, LOW);}
               }

               readData = DHT.read11(dataPin);
                    hum = DHT.humidity;
                   temp = DHT.temperature;
         
               lcd.setCursor(0,0);
               lcd.print("Humidity: ");
               lcd.print(hum);
               lcd.print(" %");
               
               lcd.setCursor(0,1);
               lcd.print("Temp: ");
               lcd.print(temp);
               lcd.print((char)223); //degree symbol
               lcd.print("C ");
         
               Serial.print(temp); //send Temperature to MIT App
               Serial.print(";");
               Serial.print(hum);  //send Humidity to MIT App
               Serial.println();
         }
}

Depending on which Arduino you have, you may not need to use the SoftwareSerial lib.

1 Like

... and here is how the Bluetooth related blocks should look on Screen Initialization. Also note that the ErrorOccurred Block is very useful. I have also included the Activity Starter method of enabling Bluetooth.

BT_List.aia (5.2 KB)

1 Like

Ohh...thank you Chris. Now I've a lot to do this weekend :blush:.
Give me little time... :pray:

He's provided a .aia, all you have to do is download it and upload it :upside_down_face:.

Yes, have seen, thanks!
I've been in front of the screen for hours. I have to take a break, my eyes are getting tired. I'll get back to you soon with the results.
Have a nice weekend....

1 Like

Somehow I can't get your code to work. But thank you very much for your effort.
I now have the code so far that it works for me. I can control the setpoint temperature up and down. This works. But now I get the following error:

Here the new code:

Temp_Hum.txt (1.6 KB)

temp_hum.aia (488.0 KB)

This was your Clock1.Timer event:

This is the standard advice for handling line delimiters in BlueTooth:

Please see the Delimiter article in FAQ

Be sure to use println() at the end of each message to send from the sending device, to signal end of message. Do not rely on timing for this, which is unreliable.

In the AI2 Designer, set the Delimiter attribute of the BlueTooth Client component to 10 to recognize the End of Line character.
BlueToothClient1_Properties
Also, return data is not immediately available after sending a request,
you have to start a Clock Timer repeating and watch for its arrival in the Clock Timer event. The repeat rate of the Clock Timer should be faster than the transmission rate in the sending device, to not flood the AI2 buffers.

In your Clock Timer, you should check

  Is the BlueTooth Client still Connected?
  Is Bytes Available > 0?
     IF Bytes Available > 0 THEN
       set message var  to BT.ReceiveText(-1) 

This takes advantage of a special case in the ReceiveText block:

ReceiveText(numberOfBytes)
Receive text from the connected Bluetooth device. If numberOfBytes is less than 0, read until a delimiter byte value is received.

If you are sending multiple data values per message separated by | or comma, have your message split into a local or global variable for inspection before trying to select list items from it. Test if (length of list(split list result) >= expected list length) before doing any select list item operations, to avoid taking a long walk on a short pier. This bulletproofing is necessary in case your sending device sneaks in some commentary messages with the data values.

(You ignored it once already.)

P.S. here is a corrected version ...

P.S. These blocks can be dragged directly into your Blocks Editor workspace.

1 Like

Hi AGB

Thank you very much for pointing that out. I had actually overlooked that, sorry. Now everything works as it should, thanks to all for your patient and professional help! I was able to learn a lot again...!