How do you use a Wheatstone Bridge to calculate Resistance using Bluetooth?

Your Clock Timer should be polling the BlueTooth input stream and adding each incoming value from the Arduino along with the current SystemTime to a two column table (list of lists), the same way my sample code was taking current Slider thumb values.

How many items per message are arriving in the BlueTooth data stream?
You have not shown the new code.

Your last code shows two variables (differential voltage and rUnknown arriving with an elapsed time.

I have no idea how to convert those to ppm.

You're the expert.

There is a list block to take a table (list of lists) and convert it into a CSV text of a table.
The File component can be used to write text to a file.

The Chart or ChartData component might have blocks to retrieve those.
Assigning a value to a Label.Text or Textbox.Text should be no problem for you by now, once you have the value.

If you want to get min and max from lists, check my sample graph for the calls to Min In List and Max In List.

If you want min and max from columns of a table, use the list block that can make a new list out of an old list by selecting a column from each row.

1 Like

I find it helpful to document a program before coding it, to such detail that you could hand off that document to a coder.

Imagine that I had no clue how your scheme works.

Explain it to me step by step with real numbers and formulas.

You will need to do this for your PhD oral defense, so it will not be wasted effort.

1 Like

Thanks for advice
Actually the meaning from this work to learn new skills, so I am doing it myself.
I will provide the scheme of my app and the new Arduino code that I did

#include <Wire.h>
#include <Adafruit_ADS1X15.h>
#include "BluetoothSerial.h"
#define ADS1115_ADDRESS 0x48
#define NUM_SAMPLES 10
// --- BRIDGE AND ADC CONSTANTS (UPDATED FOR 30k RESISTORS) ---
const float V_EXCITATION = 3.3;
// Resistor values are now 30000.0 Ohms (30k)
const float R1 = 30000.0;
const float R2 = 30000.0;
const float R3 = 30000.0;
#define ADS1115_GAIN GAIN_TWO
const float FSR = 2.048;
const float ADC_MAX_COUNT = 32767.0;
// V_REF_CENTER is the voltage at AIN0 (the stable reference point: R3 / (R1 + R3))
const float V_REF_CENTER = V_EXCITATION * (R3 / (R1 + R3)); // 3.3 * (30k / 60k) = 1.65 V
// --- GLOBAL OBJECTS ---
Adafruit_ADS1115 ads;
BluetoothSerial SerialBT;
// --- FUNCTION PROTOTYPES (Simplified parameters) ---
float readDifferentialVoltage();
float calculateUnknownResistance(float differentialVoltage);
// Note: We keep the original parameters in the function calls to loop for simplicity, 
// but only use the rUnknown value inside the print functions.
void printConsoleResults(float elapsedTimeSeconds, float differentialVoltage, float rUnknown);
void printBluetoothData(float elapsedTimeSeconds, float differentialVoltage, float rUnknown);
unsigned long startTime = 0;
//=============================================================================
void setup() {
    // 1. Initialize Console Serial
    Serial.begin(115200);
    delay(1000);
    Serial.println("\n--- ESP32 + ADS1115 Corrected Bridge Measurement (30k) ---");
    // 2. Initialize Bluetooth Serial
    SerialBT.begin("Belal_GasSensor");
    Serial.println("Bluetooth device 'Belal_GasSensor' started.");
    // 3. Initialize ADS1115
    if (!ads.begin(ADS1115_ADDRESS)) {
        Serial.println("Failed to initialize ADS1115. Check wiring.");
        while (1);
    }
    ads.setGain(ADS1115_GAIN);
    Serial.print("V_REF_CENTER (V(AIN0)): ");
    Serial.println(V_REF_CENTER, 4); // Should print 1.6500 V
    startTime = millis();
    Serial.println("\nConsole Stream (R_Unknown only):");
    Serial.println("R_Unknown (Ohms)"); // Simplified Header
    Serial.println("----------------");
}
//=============================================================================
void loop() {
    unsigned long currentTime = millis();
    unsigned long elapsedTimeMillis = currentTime - startTime;
    // Calculate elapsed time in seconds (still needed for accurate timing in the loop logic)
    float elapsedTimeSeconds = elapsedTimeMillis / 1000.0; 
    float differentialVoltage = readDifferentialVoltage();
    float rUnknown = calculateUnknownResistance(differentialVoltage);
    // Output to both streams
    printConsoleResults(elapsedTimeSeconds, differentialVoltage, rUnknown);
    printBluetoothData(elapsedTimeSeconds, differentialVoltage, rUnknown);
    delay(100); // 0.1 second (100 ms) delay between samples
}
//=============================================================================
float readDifferentialVoltage() {
    long sumCounts = 0;
    for (int i = 0; i < NUM_SAMPLES; i++) {
        sumCounts += ads.readADC_Differential_0_1();
        delay(5);
    }
    float avgCounts = sumCounts / (float)NUM_SAMPLES;
    return avgCounts * (FSR / ADC_MAX_COUNT);
}
//=============================================================================
float calculateUnknownResistance(float differentialVoltage) {
    // 1. Find the voltage at the sensor node (AIN1)
    float V_AIN1 = V_REF_CENTER - differentialVoltage;

    if (V_AIN1 <= 0.0) {
        return 9999999.0;
    }
    
    // 2. Calculate R_UNKNOWN
    float denominator = V_EXCITATION - V_AIN1;

    if (denominator <= 0.0001) {
        return 9999999.0;
    }
    return R2 * V_AIN1 / denominator;
}
//=============================================================================
void printConsoleResults(float elapsedTimeSeconds, float differentialVoltage, float rUnknown) {
    // Console output: R_Unknown only
    Serial.println(rUnknown, 2);
}
//=============================================================================
void printBluetoothData(float elapsedTimeSeconds, float differentialVoltage, float rUnknown) {
    // Bluetooth output: R_Unknown only
    if (SerialBT.hasClient()) {
        SerialBT.println(rUnknown, 2);
    }
}

First of all, thank you so much for helping me. My target from this project is to learn and improve my work; as you know, additional skills can increase the offers in the future.


I connected the Wheatstone bridge to R1= 30k Ohms, R2= 30 k Ohms, R3= 30 k Ohms, R4= 30 k Ohms, so the unknown resistance is also 30k Ohms
The ESP32 is reading the accurate value of resistance.

Belalv5 (2).aia (1.9 MB)

I see inconsistency between your Arduino code and your output stream.

Your Arduino code stops at just one reading per line:


It omits the first and second input parameters.
It looks like your source code was cut short.

Your terminal output shows 3 readings per line, separated by semicolons (';').
image

Be sure to split at ';' if building a table line by line from your input.

The clearest block images are those generated using the AI2 Helper mass download browser extension at

1 Like

Thanks, the photo with green numbers was before I changed the code to only unknown resistance; please check my app chart, and you will find that I only receive the resistance.

You know the difference between .TextColor and .Text?

Check the tool tips.


Same deal here.

1 Like

Sorry, Yes I know the difference
Thanks


What magician's hat did you pull Rair and RG (not Rg) out of?
The rising readings extraction process is supposed to be based on the just calculated R0.Text and Rg.Text values.

Also, R(any suffix) is supposed to be a resistance value in your naming scheme, right?

Then why do you call a time difference a name starting in R, and overlapping with the maximal resistance value of the graph?

1 Like

Sorry here, during designing I confused the textbox and label text; I will modify them.

A word about naming things in programs.

Unlike math, where you are constantly making diagrams on blackboards or precious scraps of paper, where space is limitted and your target audience is capable of remembering, for example, that V is for Voltage, and they don't have the patience to listen to you spell out the full name, computer code has a different set of priorities.

Computer code requires readability, redundancy, and self evidency in its variable and component names. There's lots of room on the screen for full names that include type (Label/Textbox/List/...), Unit Of Measure (Volts/Ohms/Seconds/...), context (First/Maximum/Total/Input/Output...), and semantics (Name/Address/PhoneNumber/...).

You only need to set a name once , in the Designer of Blocks Editor' global or local variable init blocks. From then on, the full name is available through pallettes and pulldowns, and via typeblocking.

That makes the code much less ambiguous and less error prone, exposing errors as common sense violations.

It makes code easier to read and to visually debug.

1 Like

I apologize for this; I have only been using the MIT app for about a week or 10 days, and prior to that, I had no experience with it. I will follow your advice. Thanks.

http://www.appinventor.org/book2

1 Like

Please I have one more question after tried many times

Now I can adjust the min and max of the axes, but I need to make the x-axis as time to count by seconds to have resistance vs time, but it is the same. Also, I got R from ESP32, but I need the normal clock to count the time in seconds or milliseconds.

I showed you these blocks before.

You must keep a global variable startMS with the value of Clock1.SystemTime for when you started taking readings.

The current number of seconds from start is the round of (Clock1.SystemTime - startMS) / 1000.

In the email copy of your post, there were blocks that don't appear in your board post, where you use the Clock Seconds(Instant) block. That's the wrong block to use, becuase it just shows the digital clock Seconds (00-59) of the current Instant.

Further block help would require a current aia export.


Thanks for your kind reply.
I removed it, but it's still the same, and also the stop button is not working to start analyzing the graph, so should I set it to disconnect the BLE?

Post your new aia export.

Belalv6_2.aia (1.1 MB)
Thanks.
Please, screen 4 is working on ai companion, but when I download the APK file, it crashes; this is only for screen 4.
For the header of the gauge, I followed the advice, but it has the same issue as it is going to another position, including the project you mentioned before about the gauge, as it has the same problem.
https://groups.google.com/g/mitappinventortest/c/k20NEzXSBy8/m/XzQis0IBBwAJ

I am unable to download your aia file onto my desktop PC, because Windows Defender identifies it as having

Trojan:Script/Wacatac.B!ml

Upload the aia file to code.appinventor.mit.edu with an anonymous login, and send me the reentry code.