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

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.

It still shows values in data_in window but not in cmd_in, not changing screens at all

So, we get either the Commands or the Data, but not both?

What are the values in the data-in Label?

Hi again Pawel

I think we can use entirely different code in the Sketch to handle the buttons + sensor data. I need to know what your exact hardware model is and a drawing or photo of the setup.

See this by Juan, Section 6:

Hi Chris, sorry for delay, covid :frowning: , I'll let you know about my project soon,
mainly I just send data by serial print from arduino, I send more detail in a few days

i've got some functionality to change state on the screen by buttons, but it takes even to 10sec. which is too much

#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

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

BluetoothSerial SerialBT;

void IRAM_ATTR isr() {
  SerialBT.println(1);
}

void IRAM_ATTR isr2() {
  SerialBT.println(0);
}

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32_work");
  pinMode(0,INPUT);
  pinMode(35,INPUT);
  attachInterrupt(0, isr, FALLING);
  attachInterrupt(35, isr2, FALLING);
}

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

bth_get_arduino_data_2.aia (3.1 KB)

Your Clock is set at 3000 ms in AI2, way too slow.

Also, you are sending with println('1') and println('0') into a BT component with Delimiter=10, so your blocks should be text-oriented.

Current blocks:

Standard Delimiter 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.

1 Like