Receiving strings through BLE fails frim the second time

Hi all,

I am trying to develop a basic app that will receive the results of water quality parameters from an Arduino (Bluno via BLE. I can connect my app to the device, and it works every time I write from the app to the device. But when I am trying to receive the data from the device - it works for the first piece of data and then fails for the rest.
These are my block:




This is my Arduino code:


#include "DO_prob.h"
#include "TDS_prob.h"
#include "EC_prob.h"
#include "pH_prob.h"
#include "ORP_prob.h"
#include "TEMP_prob.h"
#include <EEPROM.h>
#include <avr/pgmspace.h>
EC_prob ec;
pH_prob ph;
TDS_prob tds;
DO_prob DO;
ORP_prob ORP;
TEMP_prob temp;

// Defining sensors pins (analogs and digitals)
#define DO_PIN A0
#define EC_PIN A1
#define pH_PIN A2
#define TDS_PIN A3
#define turb_PIN A4
#define ORP_PIN A5
#define temp_PIN 5
#define VREF 5000    //for arduino uno, the ADC reference is the AVCC, that is 5000mV(TYP)

// More definitions
float voltagePH, voltageEC, voltageTDS, voltageDO, phValue, ecValue, tdsValue, doValue, orpValue, temperature;
String userinput; // variable to store the user input
#define ReceivedBufferLength 20
char receivedBuffer[ReceivedBufferLength + 1];    // store the serial command
byte receivedBufferIndex = 0;

#define SCOUNT  30           // sum of sample point
int analogBuffer[SCOUNT];    //store the analog value in the array, readed from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0, copyIndex = 0;
float averageVoltage = 0;

// Setup some libraries and serial
void setup() {
    Serial.begin(9600);
    //BTserial.begin(9600);
    ec.begin();
    ph.begin();
    tds.begin();
    DO.begin();
    temp.begin();
}

// Main code
void loop() {
    userinput = UserInput();
    if (userinput.equals("1")) { // User is looking to calibrate
        userinput = UserInput();
        if (userinput.equals("1")) { // User wants to calibrate pH
            ph.Calibration();
        }
        else if (userinput.equals("2")) { // User wants to calibrate ec
            ec.Calibration();
        }
        else if (userinput.equals("3")) { // User wants to calibrate tds
            tds.Calibration();
        }
        else if (userinput.equals("4")) { // user wants to calibrate do
            DO.Calibration();
        }
        else if (userinput.equals("5")) {// user wants to calibrate orp
            ORP.Calibration();
        }

    }
    else if (userinput.equals("2")) { // User is looking to measure

        userinput = UserInput();
        if (userinput.equals("1")) { // User wants to measure temp
            temp_measurment();
        }
        else if (userinput.equals("2")) { // User wants to measure pH
            ph_measurment();
        }
        else if (userinput.equals("3")) { // User wants to measure ec
            ec_measurment();
        }
        else if (userinput.equals("4")) { // user wants to measure trub
            turb_measurment();
        }
        else if (userinput.equals("5")) { // User wants to measure TDS
            tds_measurment();
        }
        else if (userinput.equals("6")) { // User wants to measure DO
            do_measurment();
        }
        else if (userinput.equals("7")) { // User wants to measure all
          // TO DO
        }
        else { Serial.println("Try again. Make sure you insert the number of the measurement");
        Serial.println();
        }
    }
    else if (userinput.equals("3")) { // User is looking to measure all in at once         
        
        userinput = UserInput();  // Temperature ,^C
        delay(7000);
        temperature = temp.readTemperature();
        Serial.println(String(temperature));
        
        userinput = UserInput(); // Dissolved oxygen ,mg/L
        delay(5000);
        doValue = DO.readDO((analogRead(DO_PIN) / 1024.0 * 5000), temperature);
        Serial.println(String(doValue));
        
        userinput = UserInput(); // pH
        delay(5000);
        phValue = ph.readPH((analogRead(pH_PIN) / 1024.0 * 5000), temperature);
        Serial.println(String(phValue));
        
        userinput = UserInput(); // Electrical conductivity ,ms/cm
        delay(5000);
        ecValue = ec.readEC((voltageEC = analogRead(EC_PIN) / 1024.0 * 5000), temperature);
        Serial.println(String(ecValue));
        
        userinput = UserInput(); // Turbidity ,NTU
        delay(5000);
        float voltage = analogRead(turb_PIN) * (5.0 / 1024.0);
        float turbidity = -1120.4 * ((voltage) * (voltage)) + 5742.3 * (voltage)-4352.9;
        Serial.println(String(turbidity));
        
        userinput = UserInput(); // Total dissolved solids ,ppm
        delay(5000);
        tdsValue = tds.readTDS((analogRead(TDS_PIN) / 1024.0 * 5), temperature);
        Serial.println(String(tdsValue));

        userinput = UserInput(); // ORP TO DO
        delay(5000);
        orpValue = ORP.readORP();
        Serial.println(String(orpValue));
        delay(5000);
    }
}

// Function to read the user's input
char UserInput() {
    while (Serial.available() == 0) {}
    char input = Serial.read();
    Serial.println(input);
    return input;
}

Label2 is just for debugging, so I can see in real-time if it works. For the TempMeasure I get the correct string. After that, I get the String that was sent for the previous measurement (DOMeasure receives "0",pHMeasure receives "1", etc.)

Any ideas about what can it be?

Any ideas?
I am feeling lost :slight_smile:

I don't use BLE, but I frequently read other peoples' BLE posts.

Maybe these questions will move you along ...

  • I see you are Using serviceUUID and CharacteristicUUID in your AI2 BLE blocks, but I don't see any reference to them in your Arduino code, just read and println calls. Is there some extra chip receiving your serial traffic and handling the BLE details?
  • I see you using half a dozen Clock Timers to try to catch responses from different single digit queries, using BLE ReadString calls. Can those Clock Timers be fighting each other over control of your BLE request/response cycle?
  • I see you do a BLE Register For Strings call in Clock1.Timer. BLE users typically Register for Strings just once, and handle the incoming strings in the BLE StringsReceived Event. Repeating the Register calls has caused problems in the past.
  • I see you have a BLE When STrings Received event, but all you do in it is store the incoming strings in a global variable but you don't initiate any processing of the incoming data, neither with nor without any memory of what type of request was last issued to the Arduino.

I recommend ...

  • Adding a Label (\n = new line) or ListView and accumulating a log of what requests you issued and what responses arrived, with timestamps.

  • Reducing your number of Clocks or insuring that at most only one of them is ever enabled at a time, for simplicity.

  • Stop issuing BLE ReadStrings, and do your incoming data handling only in the BLE StringsReceived Event. You would need a global variable remembering the last issued BLE request, to guide your response handling.

Do you need sample logging code for AI2?

Thanks for the response!

I have a lot of clocks because I am trying to read one probe at a time. However, I did try to ensure that only one runs at a time, so I don't think it is this.

it would be great if you could share a sample code primarily related to the third proposal (stop issuing BLEReadStrings

@ABG, I might get wrong the way the app reads BLE strings. I thought you needed to use the BLE Readstrings to start the BLE StringsRecieved. But from your response, it seems that it's not compulsory...

Here is my current BLE collection.

Also check the Tutorials section of this board for Juan Antonio samples.