I'm trying to send a simple string from MIT App inventor to Arduino 33 using the BLE1, but this code is not working and the Arduino is not receiving anything.
The other side of communication (Arduino -> App) works, so I know it's not an issue with the Bluetooth connection. I've attached the picture of the app code and the Arduino code.
Any help would be appreciated. Thanks!
Here's your .ino file in a more board-friendly format:
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <ArduinoBLE.h>
#include <SPI.h>
// Define TFT connections
#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
// Initialize TFT
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// char array to print to the screen
char sensorPrintout[4];
// initialize global variable for UV
float uv_reading = 0;
// change this to however many samples you want per day
// end goal: data cap of 1440, only sample for it once a minute
const int data_cap = 4;
const int week_days = 7;
// initialize global array for UV data storage per day
int uv_daily_store[data_cap];
// keep track of position in daily store
int minute = 0;
// initialize global array for UV data storage per week
int uv_weekly_store[week_days];
// initialize variable to keep track of what day it is
int day = 0;
int lastUvReading = -1; // Store last value
int connCheck = 1; //check if connected
// Set up BLE
BLEService sensorService("180c"); // Custom BLE Service
BLEStringCharacteristic sensorCharacteristic("2A56", BLERead | BLENotify, 20); // BLE Characteristic
BLEStringCharacteristic receiveCharacteristic("2A56", BLEWrite, 20); //receive data
void setup() {
Serial.begin(115200);
tft.initR(INITR_BLACKTAB); // Initialize ST7735 with black tab settings
tft.fillScreen(ST77XX_BLACK); // Clear screen with black
tft.setTextSize(8); // Set text size
// BLE Integration
if (!BLE.begin()) {
Serial.println("Starting BLE failed!");
while (1);
}
BLE.setDeviceName("UVNano"); // Change peripheral name
BLE.setLocalName("UVNano"); // Change local name
BLE.setAdvertisedService(sensorService);
sensorService.addCharacteristic(sensorCharacteristic);
sensorService.addCharacteristic(receiveCharacteristic);
BLE.addService(sensorService);
receiveCharacteristic.setEventHandler(BLEWritten, onReceive);
sensorCharacteristic.writeValue("Waiting...");
BLE.advertise();
Serial.println("Bluetooth Ready and Advertising");
}
void loop() {
// Read UV
UVRead();
// BLE Device Connection Logic
BLEDevice central = BLE.central(); // Wait for connection
if (central & (connCheck ==0)) {
Serial.print("Connected to ");
Serial.println(central.address());
connCheck = 1;
}
if(!central){
connCheck = 0;
}
}
void BLElive(){
UVRead();
//if (uv_reading != lastUvReading) {
String value = "UV Index: " + String(uv_reading);
sensorCharacteristic.writeValue(value);
Serial.print('UV Live works');
Serial.print('Bluetooth UV test: ');
Serial.print(uv_reading);
// Serial monitor after sending to Bluetooth for debugging
Serial.print("Sent to Bluetooth: ");
Serial.println(value);
}
void BLEstore(){
String week_vals;
for(int i=0; i<(week_days-1); i++){
week_vals += String(uv_weekly_store[i]) + " ";
}
sensorCharacteristic.writeValue(week_vals);
Serial.print('UV Stored works');
Serial.print('UV test: ');
Serial.print(uv_reading);
// Serial monitor after sending to Bluetooth for debugging
Serial.print("Sent to Bluetooth: ");
Serial.println(week_vals);
}
// Function triggered when data is received
void onReceive(BLEDevice central, BLECharacteristic characteristic) {
String receivedValue = receiveCharacteristic.value();
Serial.print("Received via BLE: ");
Serial.println(receivedValue);
//int storageType = receivedValue.toInt();
// Add logic for how to handle the received value
// "0" for live, "1" for stored
if (receivedValue == "0") {
delay(1000);
BLElive();
} else if (receivedValue == "1") {
delay(1000);
}
}
// reads UV and stores UV index as global variable uv_reading
// outputs UV index onto LCD
void UVRead(){
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 3.3V):
float voltage = sensorValue*3.3/1023.0;
// calculate UV index
float uv_reading_raw = voltage*10;
uv_reading = round(uv_reading_raw);
Serial.print("Voltage: ");
Serial.print(voltage);
Serial.print(" | UV Index: ");
Serial.println(uv_reading);
// only print if changed (to reduce flickering)
if(uv_reading != lastUvReading){
// Choose text color based on value
uint16_t textColor;
if (uv_reading < 3) {
textColor = ST77XX_GREEN; // Green for UV < 3
} else if (uv_reading < 6) {
textColor = ST77XX_YELLOW; // Yellow for UV = 4, 5
} else if (uv_reading < 8) {
textColor = ST77XX_ORANGE; // Orange for UV = 6, 7
} else if (uv_reading < 11) {
textColor = ST77XX_RED; // Red for UV = 8, 9, 10
} else {
textColor = ST77XX_MAGENTA; // Purple for Extreme UV >10
}
// Clear previous text
tft.fillScreen(ST77XX_BLACK); // Clear screen with black
itoa(uv_reading, sensorPrintout, 10); // Convert integer to string
// Get the text width using getTextBounds() to correctly center the text
int16_t x, y;
uint16_t textWidth, textHeight;
tft.getTextBounds(sensorPrintout, 0, 0, &x, &y, &textWidth, &textHeight);
// Center the text based on the width of the text
x = (128 - textWidth) / 2; // 128 is screen width
tft.setTextColor(textColor);
tft.setCursor(x, 50); // Set cursor position for centered text
tft.print(sensorPrintout); // Display UV index
}
lastUvReading = uv_reading;
// store the data (change later to only store once a minute)
UVStore();
// Update every 1 second
delay(1000);
}
// store the UV data into daily array
void UVStore(){
uv_daily_store[minute] = uv_reading;
if(minute<(data_cap-1)){
minute++;
}
// if whole day is stored (NEEDS MORE STUFF HERE)
else{
UVDaily();
}
}
// call to convert the array of data from the whole day into a daily average
void UVDaily(){
float daily_sum = 0;
float daily_average = 0;
for(int i=0; i<data_cap; i++){
daily_sum += uv_daily_store[i];
}
daily_average = daily_sum/data_cap;
uv_weekly_store[day] = daily_average;
//reset uv_daily_store array
minute = 0;
//go to next day in uv_weekly_store array
if(day<(week_days-1)){
day++;
}
// if the whole week is stored (NEEDS MORE STUFF HERE)
else{
Serial.print("Out of data storage");
Serial.print('Weekly data:');
for(int i = 0; i<week_days; i++){
Serial.print(uv_weekly_store[i]);
Serial.print(", ");
}
// day = 0;
}
}
Hopefully, one of our BLE experts will spot something.
The BLE experts are out to vacation, I guess, so here's a guess for you.
Your receive code does not have a case for when the received text does not match either '0' or '1'.
Open yourself up to surprise.
// Function triggered when data is received
void onReceive(BLEDevice central, BLECharacteristic characteristic) {
String receivedValue = receiveCharacteristic.value();
Serial.print("Received via BLE: ");
Serial.println(receivedValue);
//int storageType = receivedValue.toInt();
// Add logic for how to handle the received value
// "0" for live, "1" for stored
if (receivedValue == "0") {
delay(1000);
BLElive();
} else if (receivedValue == "1") {
delay(1000);
}
}
Here's your latest blocks image, in case an expert notices.