How to use buttons on esp32/arduino to control MIT app inventor aps via bluetooth?

Hello bigplik - so that is your actual issue, not what it says in your Topic Title :upside_down_face:

I'll take a quick look at your Project - how often are values sent, and are they representing the same thing, such as a temperature sensor reading?

OK, lots of things not quite right in your App Code. Can you upload the Arduino Sketch (rename from .ino to .txt) please.

The time interval of 500 milliseconds per Bluetooth read is ambitious - is it necessary? I ask because I once had a student whose App was controlling the watering of flowers. That was being done every few seconds when once a day might have been too often :koala:

1 Like

hi, there will be few variables to send them from esp32 every 30sec., I can see those values on the labels in MIT app but can't store them,
another thing is to send button position status from esp32 to MIT app, and let set change the screeen to another one when press particular button, or make some changes in the app, for now have no idea how to keep those values, I would like to use 5-7buttons and about 5 variables to send them by bluetooth, so I thought I could send different strings by SerialBT from esp32 and then decoding them on the MIT app and store/use them


#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

#ifdef __cplusplus
  extern "C" {
 #endif

  uint8_t temprature_sens_read();

#ifdef __cplusplus
}
#endif

#define BTN1 digitalRead(0)==0
#define BTN2 digitalRead(35)==0

uint8_t temprature_sens_read();

BluetoothSerial SerialBT;

void IRAM_ATTR isr() {
  SerialBT.println("A");
  detachInterrupt(0);
}

void IRAM_ATTR isr2() {
  SerialBT.println("B");
  detachInterrupt(35);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  SerialBT.begin("ESP32");
  pinMode(0,INPUT);
  pinMode(35,INPUT);
  attachInterrupt(0, isr, FALLING);
  attachInterrupt(35, isr2, FALLING);
}

void loop() {
  // put your main code here, to run repeatedly:
  attachInterrupt(0,isr,FALLING);
  attachInterrupt(35,isr2,FALLING);
  SerialBT.println((temprature_sens_read() - 32) / 1.8);     
  delay(2500);
}

another attempt, tried to use tinyDB for storage, but still not working

bth_get_arduino_data.aia (3.1 KB)

You are not using line delimiters properly ...
Standard Advice:

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.

P.S. Most devices use 9600 bps, don't ask for too much speed.

That would disconnect Bluetooth. If you want BT to stay connected, the other Screens can be Virtual Screens.

When we define virtual screens, we use one 'real' App Inventor Screen (most often Screen1). Screen-sized Vertical Arrangements on it are displayed/hidden as required - they are the Virtual Screens. This is generally a better approach for multi-screen Apps, they share data without having to "pass" it between screens and it also reduces code duplication, making the App more efficient and the code easier to follow if you have to return to it at a later date.

So, instead of separate "houses", virtual screens are "rooms" of the same "house".

Currently, you don't have the button position status in the main loop, but your idea of sending a code ('A', 'B' etc) is good, since the App has to determine what data is being sent (button status or sensor data).

So I assume you want to send several sensor values, then send a button value which tells the App what to do with the data?

I can put together an example for you - easier than listing all the things that are currently wrong. Please be patient with me as I have a few other matters to deal with first, so most likely you won't see anything until tomorrow (Chinese New Years Eve).

Using TinyDb to store the data is good and it's easy when you know how.

I'm going to assume that when the App is Exited, the Data does not need to be stored. If it does need to be stored, I can show you how to store and retrieve with TinyDB.

I have to trust that your Sketch generally works, I see you have based it on code published on Git Hub (DF Robot have similar code).
However, using delay() in the main loop can adversely affect the sensor values, so I have replaced that with a time interval test instead:

SensorDataOrCmdToApp.txt (1.4 KB)

//Sensor Data or Command To App 31/01/2022 01:29:08

#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

#ifdef __cplusplus
  extern "C" {
 #endif

  uint8_t temprature_sens_read(); //ESP32 internal temperature sensor

#ifdef __cplusplus
}
#endif

unsigned long lgUpdateTime;

#define BTN1 digitalRead(0)==0
#define BTN2 digitalRead(35)==0

uint8_t temprature_sens_read();

BluetoothSerial SerialBT;

void IRAM_ATTR isr() {
  SerialBT.println("A");
  detachInterrupt(0);
}

void IRAM_ATTR isr2() {
  SerialBT.println("B");
  detachInterrupt(35);
}

void setup() {
// put your setup code here, to run once:

         lgUpdateTime = millis();
         Serial.begin(115200);
         SerialBT.begin("ESP32");
         pinMode(0,INPUT);
         pinMode(35,INPUT);
         attachInterrupt(0, isr, FALLING);
         attachInterrupt(35, isr2, FALLING);
}

void loop() {
// put your main code here, to run repeatedly:

         attachInterrupt(0,isr,FALLING);
         attachInterrupt(35,isr2,FALLING);

	     if(millis() - lgUpdateTime > 2000) //Loop approx every 2 seconds
         {
                   lgUpdateTime = millis();
                   SerialBT.println((temprature_sens_read() - 32) / 1.8);     
         }
}

So here is a basic App Inventor Project which uses Virtual Screens.

I don't know what you intend to do with the sensor data (a chart?). In this example it is streamed onto the Main Screen and If Virtual ScreenB is opened, the data populates a ListView (Which could instead be anything you require). Each sensor value received is added to a comma separated string and the display refreshed.

Given that Bluetooth and Location must be on, they are dealt with by the code.

The Data is set to be read and processed every 1600 milliseconds. That's already faster than the human eye can tolerate.

I'm unable to conduct tests here as my test 'lab' is mothballed, but the Project is based on my template that many people have successfully customised to suit their requirements. An exception being the enabling of Bluetooth and Location, previously done via Activity Starter but the latest App Inventor version has that covered (hopefully!).

Edit: Not being prompted for BT or Loc on my phone :thinking:

Updated file:

BT_Receive_Data.aia (9.5 KB)

Thank you so much Chris, I will test your code and app, and let you know how it work for my app.
btw. I am ok with virtual screens, just I need to use physical buttons because I want to use my app at bike, where I use a gloves and would much easier for me to use buttons for controlling my app than use phone screen.

1 Like

Chris, I did check your code and app,
It looks like you can change screens by buttons on the phone screen,
but still can't change them by phisical esp32 buttons,
your app display values from buttons on the Data in label but not changing screens like your B or C screen buttons in the MITapp

Hi Pawel

Do you mean, when an esp32 button is pressed, the result of that button press is displayed in the App? Not good, because the code should detect that it's a command and not data...... :thinking:

......you are using the updated Sketch?

Let's try a Sketch that only has the button code (no sensor read) and an App that just puts whatever it receives into the label 'Label_Data_Received_VirtualScreenA' . Then we will know if "B" and "C" actually get sent to the App.

BT_Test_Cmnd_Receipt.aia (9.8 KB)

CmdToApp.txt (926 Bytes)

Hi Chris,
it's not change anything, same story, can see value of the button when pressed,
but it doesn't change screens in the app

Need more detail about the result Pawel.

The test App does not do anything other than put everything it receives into a Label, nothing else. How about a screenshot?

Edit: Or swap the Label Component with a TextBox, which will allow you to copy the result to the clipboard - then you can paste it into an email to yourself, then on your PC copy the content of the email to this Forum Topic :sunglasses:

Hi Chris,

app does not do anything other than shows information on the label, thats it,
no screen change, and I also tried to catch that value from serialBT, but can't
put that into new variable

text box only shows the same values, A or B, depend what I press

OK, that is the exact purpose of the test, test passed.

Have you, with the original versions of my files, seen sensor data in the label 'Label_Data_Received_VirtualScreenA' ?

Right - Project v2, Sketch v2 :grin:

BT_ReceiveDataAndCmnds2.aia (15.1 KB)

SensorDataOrCmdToApp2.txt (1.4 KB)

Build the App as an APK for testing.