info for app arduino/android communication

3247 views
Skip to first unread message

Nicola C.

unread,
Jul 25, 2016, 7:22:10 AM7/25/16
to MIT App Inventor Forum
Hello everyone!

I have a question about an app that I'm writing.

I have to send via bluetooth, through Arduino, the two sensors reading (DHT22 and BMP180) and visualiazzarli on the monitor screen. So everything is right, I managed to do what I want. But if I want to send the reading of DHT22 sensor in a label, and that of the BMP180 to another label, how do I?

I enclose the block diagram of my app

Thank you
appinventor.JPG

Ghica

unread,
Jul 25, 2016, 7:52:43 AM7/25/16
to MIT App Inventor Forum
Nicola,
Can you show what a typical message that you receive would look like?

The idea is that you split the text using the text blocks in two parts, for example split: http://appinventor.mit.edu/explore/ai2/support/blocks/text.html#split
Or, if you receive the values comma separated, then you could use: http://appinventor.mit.edu/explore/ai2/support/blocks/lists.html#listfromcsvrow

If you would like more help, you could post the part of the sketch that generates the messages.
Cheers, Ghica.

Nicola C.

unread,
Jul 25, 2016, 8:44:23 AM7/25/16
to MIT App Inventor Forum
here is the sketch. I colored differently blocks of text that I want to share. Can you help me because not understand how to do?


void loop()
{
 
  while (!BTconnected)                      // verifico se è attiva una connessione tra modulo bluetooth e smartphone/tablet. Se attiva                                             // procedo con il resto del programma
  {
    if ( digitalRead(BTpin) == HIGH)  {
      BTconnected = true;
    };
  }
  
  Serial.println("HC-05 è connesso");       // messaggio di avvenuta connessione 
   
  if ((millis() - tempo) > 5000) {          // intervallo di chiamata lettura sensori  ogni 5s
 
  delay(dht.getMinimumSamplingPeriod());    // chiamata sensori per richiesta lettura
  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();
 
  pressione = bmp.GetPressure() / 100.0;
  temperatura = bmp.GetTemperature();

  /*aggiungo 9 hPa x ogni 100 m di altitudine del luogo d'ubicazione della stazione meteo, 
  allo scopo di traslare la pressione letta alla corrispettivo valore di pressione slm. 
  Es. la stazione si trova a 100 m slm aggiungere 9, se si trova a 200 m slm aggiungere 18 e così via */

  pressione_slm = pressione + 21.6;                            
  temp_media_sens = (temperature + temperatura) / 2;           // faccio la media della temperatura letta dai due sensori
 
  bluetooth.print("Umidita' = ");
  bluetooth.print(humidity);
  bluetooth.println(" %");
  bluetooth.print("Pressione SLM = ");
  bluetooth.print(pressione_slm);
  bluetooth.println(" hPa");
  bluetooth.print("Temperatura = ");
  bluetooth.print(temp_media_sens);
  bluetooth.println(" C");
 
  tempo = millis();
      }
  
}

Abraham Getzler

unread,
Jul 25, 2016, 11:11:48 AM7/25/16
to MIT App Inventor Forum
I see from your Arduino code that you are using println() at the end of each reading,
and sending identifying text before each reading.

That's helpful.

There's a Delimiter facility in the Designer's BlerTooth client component that will
(with proper blocks) feed you only one reading at a time, between one LF and the next LF.

Set your BTClient Delimiter to decimal 10 to use LF as the delimiter.
(See an ASCII table to confirm)

Define a global variable, IncomingData, iniially blank text.

Also, in Clock1 Timer, code:
 IF BTlient1.Isconnected THEN
    IF BTlient1.BytesAvailable > 0 THEN
        set global IncomingData to BTlient1..ReceiveText(-1)
(notice I asked for -1 bytes.  This means ask for everything up till the next delimiter, LF in this case.  See the block tool tip for confirmation)
        If global IncomingData contains 'Pressure' THEN
             set LabelPressure.Text to IncomingData 
        ELSEIf global IncomingData contains 'Temperature' THEN
             set LabelTemperature.Text to IncomingData 
        ELSEIf global IncomingData contains 'Humidity' THEN
             set LabelHumidity,Text to IncomingData 
        ELSE 
             set LabelCrapData,Text to IncomingData 


In my Clock routine, I did not trim off the identifier text before dropping it into a label.
You can do that using a text split at '=" and selecting item 2 of the result.

Look in the text blocks group for the "contains" block.

ABG

Nicola C.

unread,
Jul 25, 2016, 12:10:52 PM7/25/16
to MIT App Inventor Forum
Thanks Abraham, but unfortunately I did not understand. For example, the variable IncomingData I define it in Arduino?

You could draw me blocks of code?

Abraham Getzler

unread,
Jul 25, 2016, 12:28:04 PM7/25/16
to MIT App Inventor Forum
Global variables come from the brown Variables section in the AI2 blocks editor.

See the Bluetooth and Arduino section of this FAQ for plenty of examples ...

ABG

Nicola C.

unread,
Jul 25, 2016, 3:14:01 PM7/25/16
to MIT App Inventor Forum
I identified the variable, but I can not go because I can not understand the flow of operations to do and I can not find all the blocks. Some help?

Nicola C.

unread,
Jul 26, 2016, 3:38:12 AM7/26/16
to MIT App Inventor Forum
Hello,
They are blocked as an image attachment. I do not know how to set this line:

 If global IncomingData contains 'Pressure' THEN

then I did not understand how to set the last else:

 set LabelCrapData,Text to IncomingData 

Thanks

Nicola 
Immagine.JPG
bt_meteo_copy.aia

Nicola C.

unread,
Jul 26, 2016, 7:12:12 AM7/26/16
to MIT App Inventor Forum
Abraham, I corrected the above code, I attach a picture.
Can you tell me if it is correct and that is what you mean? Also could you explain better this step:

There's a Delimiter facility in the Designer's BlerTooth client component that will
(with proper blocks) feed you only one reading at a time, between one LF and the next LF.

Set your BTClient Delimiter to decimal 10 to use LF as the delimiter.
(See an ASCII table to confirm)

Thanks
Immagine.JPG
bt_meteo_copy.aia

Abraham Getzler

unread,
Jul 26, 2016, 12:48:14 PM7/26/16
to mitappinv...@googlegroups.com
I have corrected your BlueTooth ReceiveText block to ask for -1 bytes.
I also moved label updating logic to trigger only if data is available, to prevent premature label erasure.

See attached blocks and .aia file.
You can use the Backpack to copy across projects.
Load the backpack in one project, then switch to the destination project,
then pull from the backpack there.

See http://www.asciitable.com/ around decimal 10 for the connection between Line Feed (New Line) and decimal 10.

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

I see you set the Delimiter to 10 in the Designer,
so with the new blocks you should be ready to test.

I do not have BlueTooth equipment, so I could not test.
I am working from common understanding of data transfer.

Let us know how it works out?


Timer.png
bt_meteo_ABG.aia
BlueToothClient1_Properties.PNG

Abraham Getzler

unread,
Jul 26, 2016, 12:49:40 PM7/26/16
to MIT App Inventor Forum
By the way, I also renamed Button4 to btnDisconnect, for clarity.
ABG

Nicola C.

unread,
Jul 26, 2016, 2:46:14 PM7/26/16
to MIT App Inventor Forum
Wow, thanks a lot Abraham, your app so it works correct almost completely. Only the reading of "Pressione_SLM" is translated in the label crapdata. Because?
I show a screenshot.

Nicola
Screenshot_2016-07-26-20-40-48.png

Abraham Getzler

unread,
Jul 26, 2016, 3:00:29 PM7/26/16
to MIT App Inventor Forum
Your text for comparison of pressures doesn't exactly match what was being sent (". " vs "_" after the word Press).

Just check for "SLM" or for "Press" and you should be okay.

ABG eagle-eyes.


Nicola C.

unread,
Jul 26, 2016, 3:07:33 PM7/26/16
to MIT App Inventor Forum
False alarm Abraham, everything works perfectly (there was an error in the sketch side Arduino) .Sorry. Just one question, but the last else, the one with the label crapdata it is essential? You can remove? If I do I do?

Thank you very much for your availability. If you can to please the final part of the app name will ABG :)

Abraham Getzler

unread,
Jul 26, 2016, 3:20:57 PM7/26/16
to MIT App Inventor Forum
the last else, the one with the label crapdata it is essential? You can remove? If I do I do?


Do you remove the batteries from your smoke detector when there is no smoke?
You can use a Notifier instead, but keeping the test is a good safety feature
to speed up diagnosis if things go wrong.
 
Thank you very much for your availability. If you can to please the final part of the app name will ABG :)
 
I only added the ABG for version control, to give you two separate versions to work from.
I don't need any credit in your app.

ABG

Nicola C.

unread,
Jul 27, 2016, 3:33:01 AM7/27/16
to MIT App Inventor Forum
Perfect I did Abrahm.

Now you dispose of the individual sensor readings, I'd like to save the data with the TinyDB tool and create a graph to show the trend of temperature, pressure etc etc.

Do you know if it is a possible thing, and if there is any tutorial?

Thanks again

Nicola

Abraham Getzler

unread,
Jul 27, 2016, 1:54:37 PM7/27/16
to MIT App Inventor Forum
 I'd like to save the data with the TinyDB tool and create a graph to show the trend of temperature, pressure etc etc.

Do you know if it is a possible thing, and if there is any tutorial?


TinyDB is only needed if you want to save readings between one run and the next, or to pass data to another screen.

See this FAQ, specifically the sections on Lists, Lists of Lists, TinyDB tutorials,  and Graphs.

You would need a Start/Stop button, a Graph button, and Save and Load buttons to control TinyDB saving/loading.
You will also need two global variables:  
  Readings, initially CREATE EMPTY LIST, and
  StartMS, initially 0.

Readings could be a list of lists, (a table), with one row per reading:
(millliseconds, temp, pressure, humidity)
where milliseconds counts time since the Start button click, and the other 3 items are the readings at that time.

The entire table could be stored under a single TinyDB tag, "READINGS".

The Start/Stop button click routine would be:
 if btnStartStop.Text = "Start THEN
    enable Clock1
    set btnStartStop.Text to "Stop"
    set StartMS = MillisecondsFromInstant(Clock1.Now())
    set global Readings = empty list
ELSE
    set btnStartStop.Text to "Start"
    disable Clock1

In Clock1.Timer, extra code would:
(in section that runs only if new data has arrived)
(get reading)
    initialize local variables:
     ms = MillisecondsFromInstant(Clock1.Now()) - global StartMS
     temp = 2nd item in split (temp reading, "=")
     press = 2nd item in split (press reading, "=")
     humidity = 2nd item in split (humidity reading, "=")
  add item (Make list(ms, temp, press, humidity) to global Readings list

The Save and Load buttons would be single TinyDB blocks, using the aforementioned tag, for Readings.

The graph routine in the FAQ works on two lists, x and y, which you would have to strip out from the Readings table with loops.

ABG

Nicola C.

unread,
Jul 27, 2016, 2:55:31 PM7/27/16
to MIT App Inventor Forum
I try, thank you, but it seems very complex!

Nicola C.

unread,
Jul 29, 2016, 5:07:11 AM7/29/16
to MIT App Inventor Forum
ok, I give up, the chart is too complicated for me.

Is there a way to automatically save the last 5, 10 readings of the three parameters:

- pressure
- temperature
- humidity

and then recall them with a single button, and show them in a canvas?

Thank you

Nicola C.

unread,
Jul 29, 2016, 8:35:11 AM7/29/16
to MIT App Inventor Forum
Abrahm then, I try to move on.

The goal is to read and store the previous 5/10 readings from the three sensors (humidity, temperature and pressure). To do this I used the tiny component db. I hope it is right. About it only uses one or three?

Then at the bottom of the screen I placed 3 buttons, one per sensor. When I press the corresponding button, through a canvas I want to see the readings.

I am attaching the image of the block (to be multiplied x 3) and .aia file. Tell me what you think please.

Thank you
Immagine.JPG
bt_meteo_ABG_copy.aia

Ghica

unread,
Jul 29, 2016, 12:36:30 PM7/29/16
to MIT App Inventor Forum
Nicola,
The way you are trying to store the data is that you are storing only ONE value. You need to use a list, retrieve the list add the latest data to it. I made a procedure that saves the latest 10 values read. And a call to it for each type of data in your timer routine. Then, when you press the button, it dispalys the 10 values in a label (the last is shown first).
When you have this ok for all your data, think of a way to display a graph. The whole idea of having success in programming is doing little pieces at a time.
And try to learn something about lists:
Chapter 19 of the App Inventor book:
http://www.appinventor.org/bookChapters/chapter19.pdf

Displaying a list:
http://ai2.appinventor.mit.edu/reference/other/displaylist.html

Cheers, Ghica

bt_meteo_ABG_copy_GvEB.aia

Abraham Getzler

unread,
Jul 29, 2016, 1:12:29 PM7/29/16
to MIT App Inventor Forum
Here's a YouTube video with links to source code for a real time graph.

Learn lists first, though.

ABG

Nicola C.

unread,
Jul 29, 2016, 3:07:42 PM7/29/16
to MIT App Inventor Forum
wow, thanks a lot Ghica, your intervention was decisive. I see that you save the list to a label and not in a canvas. Because?

Also I would like to ask you if it is possible, and how, to enter a condition, type of Arduino millis -> if millis () - time> 24 h (last BT connection) saves the data in the list, so that the last 10 readings, correspond to the last 10 days.

1000 Thanks!

Nicola C.

unread,
Jul 29, 2016, 4:22:16 PM7/29/16
to MIT App Inventor Forum
I thought, is it right to put a when clock after the when button?
Thanks

Ghica

unread,
Jul 29, 2016, 5:14:21 PM7/29/16
to MIT App Inventor Forum
Because labels are for text, on a canvas you could draw a graph. For now you are not able to do the graph, because you do not know whether the data you receive are right. Once you checked that, you could start to figure out how to do the graph.

I do not understand the rest of your questions. You want to save the data of ten days?? Not possible with the setup you have now. You are sending data from the Arduino every 5 seconds, that would be 12x60x24x10 = 172800 readings in10 days, times 3 for all data. Actually, your phone could probably handle this amount of data, but how are you going to draw it? What do you want to use it for?
Cheers, Ghica

Nicola C.

unread,
Jul 30, 2016, 1:18:09 AM7/30/16
to mitappinv...@googlegroups.com
Now Arduino sends data every 5 seconds (because they are in testing and I need to figure out if it works), but I intend to increase this range to 120 seconds or more. The idea is to store the TinyDB reading component only once every 24 hours no matter how many times you open the app in the day.

This is because, to have an idea about the trend of the weather must think in days.

However, I duplicate the code for the other buttons / sensors, and everything works fine. Your code is correct.

I added a clock2 in the project and set a time to enable true with 86400000 ms (24H). Does it make sense?

Thank you
Immaginetimer.jpg

Ghica

unread,
Jul 30, 2016, 11:54:49 AM7/30/16
to MIT App Inventor Forum
Nicola,
A timer works only when your app is active, and the time starts at the time you enable it. So, a timer for 24 hours would mean that you would need your app to be running permanently and not in the background.
I suppose that you want to use your phone sometimes for other purposes too. So you need to find another solution.

With the present App Inventor, your app cannot run in the background. There is an extension by Taifun which allows you to send a notification at a specific time, so that is something you could try, but that still needs your app in the background. http://puravidaapps.com/notification.php (there is a test version of App Inventor that offers services, but it is not ready).

Another problem you have is at what time of the day are you going to measure your Arduino data? If one day you measute at 9 in the morning and the next at 9 in the evening you will have a strange set of data in the end.
And, how to make sure that you set the data in the TinyDB only once per day?
Cheers, Ghica.


Nicola C.

unread,
Jul 30, 2016, 12:14:51 PM7/30/16
to mitappinv...@googlegroups.com
the data in Arduino are always available. passed the first if statement on the presence of at least one of connected smartphones, sensors read every few seconds according to another if based on millis function. I thought I was using about 120/180 seconds because I think that no one will hold the app turned on longer than this time. Then once back in the background, and the Bluetooth connection will be lost, stops Arduino sketch. Everything works well.

Why would that TinyDB save a reading per day (does not matter what time, as this depends on who uses the app) is because it is more interesting to know how the data have fluctuated in the previous 10 days.

I thought, if it is impossible to reason as a timer instead you can make a comparison with the day of the week. A bit like a wired RTC works with Arduino. I fetch the current date and compared. App inventor, can you?

Nicola

Abraham Getzler

unread,
Jul 30, 2016, 6:43:19 PM7/30/16
to MIT App Inventor Forum
If your Arduino device is better able to stay up for 10 days than your Android device,
why not pile up all the data in the Arduino device and blast it all out on
request from the Android device?

I don't know how long a single BlueTooth message can get, though.

You would have to decide on a set of column, row, and message-end markers,
like "," NL, "|" ?

ABG

Abraham Getzler

unread,
Jul 30, 2016, 6:49:58 PM7/30/16
to MIT App Inventor Forum
Alternatively, if you have a Web Server and WiFi capability in your device,
you could collect and periodically write full hour's readings into multiple files
available for download by date/hour using the Web block.
ABG


Ghica

unread,
Jul 31, 2016, 5:04:24 AM7/31/16
to MIT App Inventor Forum
Abraham,
One of the most used Arduino boards, the Arduino Uno has a whopping 32 kB of flash memory, just enough to load your sketch. The new Arduino 101 has 196 kB.
This is not a whole lot of space to store temperature readings and if power is lost, you lose everything.

If Nicola would want to build a scientific weather station, he would do better to use a Raspberry Pi, which has a Linux operating system, megabytes of memory and storage possibilities via USB. He could use an USB connection to the Arduino, or Bluetooth, or Wifi (but that would require a Wifi module on the Arduino board, a network, etc. He could even attach his sensors directly to the Pi.
This requires a completely different set of skills and there is no way to play around with App Inventor, although, on the Pi there is Scratch, which is closely related.

Nicola, what you could do, is the following:
Replace your storeData procedure by this one below.

What it does is, instead of storing a single value for each reading, it stores a list with as first element the today date and as second element the value. But before storing it, it checks whether there is already a value for the date, and if there is, the value is not stored. This insures that you get 10 values for different dates. But if you skip a day opening the app, there will be no value for that day.
I leave it to you to display the data in a nice way.
Cheers, Ghica.


Ghica

unread,
Jul 31, 2016, 5:28:13 AM7/31/16
to MIT App Inventor Forum
Just a remark: before using the new procedure, you should clear the tags you used for the TinyDB, or use other ones, like humidita_con_data etc.
Cheers, Ghica.

Nicola C.

unread,
Jul 31, 2016, 1:22:04 PM7/31/16
to MIT App Inventor Forum
wow Ghica hello and thank you again for your help. This code is just what I wanted. In fact I do not need a scientific weather station but something that gives you an idea of the type of day that you are getting. When I finish the project, the idea is to give the app to all who live in condos in my building.

But unfortunately doing exactly as you suggested, changing the name to 3 tag of tiny component, the function to record 10 data does not work, I just get on the field related to the set ibl.dati to text then nothing.

I have some doubts:

as a clock, I expected a second clock, I was right? and designer side settings I left the default settings.

I attach the file .aia

Thank you
bt_meteo_ABG_GvEB.aia

Ghica

unread,
Jul 31, 2016, 3:14:12 PM7/31/16
to MIT App Inventor Forum
You do not need a second clock, you do not need another timer event, just its calculation facilities.
(By the way, you also do not need 4 notifiers. One is enough)

Your blocks look all fine to me. Realize that you must wait 10 days to see 10 items of data. Today it will store only one. Therefore you will see only one.
What were you exacly seeing? Can you click with your right mouse button on one of the TinyDB.GetValue blocks, and choose DoIt and tell what you see?

I cnanot really test your app, because I do not have an Arduino with the same setup.
Cheers, Ghica.

Nicola C.

unread,
Jul 31, 2016, 3:19:01 PM7/31/16