GUI-O with Nano 33 BLE and the ArduinoBLE Library
-
@VNB Hi.
I have not tested this (don't have Arduino Nano 33 BLE), so I don't guarantee correctness of the code (it compiles fine). It should get you started though (I suggest using serial to debug). Please give some feedback.
Best regards,
kl3m3n/* GUI-O BLE example (Nano 33 BLE) */ #include <ArduinoBLE.h> const int ledPin = LED_BUILTIN; // set ledPin to on-board LED const int maxMsgLength{256}; BLEService guioService("0000FFE0-0000-1000-8000-00805F9B34FB"); // create service // create gui-o (string) characteristic and allow remote device to read and write BLEStringCharacteristic guioCharacteristic("0000FFE1-0000-1000-8000-00805F9B34FB", BLERead | BLEWrite | BLENotify | BLEIndicate, maxMsgLength); void setup() { Serial.begin(9600); while (!Serial); pinMode(ledPin, OUTPUT); // use the LED as an output // begin initialization if (!BLE.begin()) { Serial.println("starting Bluetooth® Low Energy module failed!"); while (1); } // set the local name peripheral advertises BLE.setLocalName("GUI-O_BLE"); // set the UUID for the service this peripheral advertises: BLE.setAdvertisedService(guioService); // add the characteristics to the service guioService.addCharacteristic(guioCharacteristic); // add the service BLE.addService(guioService); // assign event handlers for connected, disconnected to peripheral BLE.setEventHandler(BLEConnected, [](BLEDevice central) -> void { Serial.println("Connected!"); }); BLE.setEventHandler(BLEDisconnected, [](BLEDevice central) -> void { Serial.println("Disconnected!"); }); // assign event handlers for characteristic guioCharacteristic.setEventHandler(BLEWritten, parseGuioMsg); // start advertising BLE.advertise(); Serial.println("Bluetooth® device active, waiting for connections..."); } void loop() { // poll for Bluetooth® Low Energy events BLE.poll(); } /***************************/ /* IMPLEMENT YOUR GUI HERE */ /***************************/ void sendMsg(const String &msg) { guioCharacteristic.writeValue(msg); delay(50); } void parseGuioMsg(BLEDevice central, BLECharacteristic characteristic) { const uint8_t* value = characteristic.value(); const int length = characteristic.valueLength(); const String msg(reinterpret_cast<const char*>(value), length); if(msg.startsWith("@init")) { Serial.println("GUI-O app is requesting INITIALIZATION!"); // clear screen and set background sendMsg("@cls\r\n"); sendMsg("@guis BGC:#FFFFFF\r\n"); delay(100); // initialize simple example GUI sendMsg("|LB UID:title X:50 Y:15 TXT:\"Simple light switch\" FFA:\"font8\" FSZ:3.5\r\n"); sendMsg("|LB UID:tap_me X:50 Y:70 TXT:\"TAP ME!\" FFA:\"font8\" FSZ:3 FFA:\"font5\"\r\n"); sendMsg("|CB UID:brightness X:50 Y:50 W:90 BTH:5 HAH:8 HAW:8 VIS:0 STA:135 ENA:45 FGC:#000000 SFGC:#FFFF00 BGC:#CBCBCB\r\n"); sendMsg("|IM UID:light_off X:50 Y:50 IP:\"https://i.imgur.com/3VbsS0Z.png\" VIS:1\r\n"); sendMsg("|IM UID:light_on X:50 Y:50 IP:\"https://i.imgur.com/gNdck9A.png\" VIS:0\r\n"); } else if(msg.startsWith("@light_off")) { Serial.println("GUI-O app is requesting LIGHT ON!"); // "drive GUI-O app" sendMsg("@light_off VIS:0\r\n"); sendMsg("@light_on VIS:1\r\n"); sendMsg("@brightness VIS:1 VAL:100\r\n"); // led enable digitalWrite(ledPin, HIGH); } else if(msg.startsWith("@light_on")) { Serial.println("GUI-O app is requesting LIGHT OFF!"); // "drive GUI-O app" sendMsg("@light_off VIS:1\r\n"); sendMsg("@light_on VIS:0\r\n"); sendMsg("@brightness VIS:0 VAL:0\r\n"); // led disable digitalWrite(ledPin, LOW); } else if(msg.startsWith("@brightness")) { const int idx = msg.indexOf(' '); if(idx > 0) { const int val = msg.substring(idx + 1).toInt(); if(val >= 0 && val <= 100) { Serial.print("GUI-O app is requesting LIGHT BRIGHTNESS: "); Serial.println(val); // led drive analogWrite(ledPin, static_cast<uint8_t>(val * 2.55)); } } } }
-
YES, it works. Thank you so much!
There were two minor problems.
1.) The Slider Control knob always stayed at 100% even if it is set to a low brightness. That was fixed by adding the following instruction in the "led drive" section.
sendMsg("@brightness VIS:1 VAL:val\r\n");2.) Once the brightness is adjusted then the Nano Yellow LED STAYS on at the selected brightness even though the "on" and "off" light bulb image toggles okay and Serial Monitor correctly displays "GUI-O app is requesting LIGHT ON!" and "GUI-O app is requesting LIGHT OFF!". That was fixed by always keeping the 'ledPin' in the 'analog' mode by changing digitalWrite(ledPin, HIGH); to analogWrite(ledPin, 0); and digitalWrite(ledPin, LOW); to analogWrite(ledPin, 255);
The modified code is below.
Thanks again for GREAT service!
Vince/* GUI-O BLE example (Nano 33 BLE) original file is "ButtonLED_GUI-O.ino" The 'Button LED' example found in 'File-Examples-ArdunioBLE-Peripheral-ButtonLED' was modified by kl3m3n to work with the Nano 33 BLE Sense board and ArduinoBLE.h library. Operation: * Click TAP HERE to toggle Nano 33 Yellow LED On/Off. * When the LED is ON a Slider control is displayed and will adjust the Brightness of LED. * Brightness is not remembered so toggling the LED Off and back On will always select 100% brightness. */ #include <ArduinoBLE.h> const int ledPin = LED_BUILTIN; // set ledPin to on-board LED const int maxMsgLength{256}; BLEService guioService("0000FFE0-0000-1000-8000-00805F9B34FB"); // create service // create gui-o (string) characteristic and allow remote device to read and write BLEStringCharacteristic guioCharacteristic("0000FFE1-0000-1000-8000-00805F9B34FB", BLERead | BLEWrite | BLENotify | BLEIndicate, maxMsgLength); void setup() { Serial.begin(9600); while (!Serial); pinMode(ledPin, OUTPUT); // use the LED as an output // begin initialization if (!BLE.begin()) { Serial.println("starting Bluetooth® Low Energy module failed!"); while (1); } // set the local name peripheral advertises BLE.setLocalName("GUI-O_BLE"); // set the UUID for the service this peripheral advertises: BLE.setAdvertisedService(guioService); // add the characteristics to the service guioService.addCharacteristic(guioCharacteristic); // add the service BLE.addService(guioService); // assign event handlers for connected, disconnected to peripheral BLE.setEventHandler(BLEConnected, [](BLEDevice central) -> void { Serial.println("Connected!"); }); BLE.setEventHandler(BLEDisconnected, [](BLEDevice central) -> void { Serial.println("Disconnected!"); }); // assign event handlers for characteristic guioCharacteristic.setEventHandler(BLEWritten, parseGuioMsg); // start advertising BLE.advertise(); Serial.println("Bluetooth® device active, waiting for connections..."); } void loop() { // poll for Bluetooth® Low Energy events BLE.poll(); } /***************************/ /* IMPLEMENT YOUR GUI HERE */ /***************************/ void sendMsg(const String &msg) { guioCharacteristic.writeValue(msg); delay(50); } void parseGuioMsg(BLEDevice central, BLECharacteristic characteristic) { const uint8_t* value = characteristic.value(); const int length = characteristic.valueLength(); const String msg(reinterpret_cast<const char*>(value), length); if(msg.startsWith("@init")) { Serial.println("GUI-O app is requesting INITIALIZATION!"); // clear screen and set background sendMsg("@cls\r\n"); sendMsg("@guis BGC:#FFFFFF\r\n"); delay(100); // initialize simple example GUI sendMsg("|LB UID:title X:50 Y:15 TXT:\"Simple light switch\" FFA:\"font8\" FSZ:3.5\r\n"); sendMsg("|LB UID:tap_me X:50 Y:70 TXT:\"TAP ME!\" FFA:\"font8\" FSZ:3 FFA:\"font5\"\r\n"); sendMsg("|CB UID:brightness X:50 Y:50 W:90 BTH:5 HAH:8 HAW:8 VIS:0 STA:135 ENA:45 FGC:#000000 SFGC:#FFFF00 BGC:#CBCBCB\r\n"); sendMsg("|IM UID:light_off X:50 Y:50 IP:\"https://i.imgur.com/3VbsS0Z.png\" VIS:1\r\n"); sendMsg("|IM UID:light_on X:50 Y:50 IP:\"https://i.imgur.com/gNdck9A.png\" VIS:0\r\n"); } else if(msg.startsWith("@light_off")) { Serial.println("GUI-O app is requesting LIGHT ON!"); // "drive GUI-O app" sendMsg("@light_off VIS:0\r\n"); sendMsg("@light_on VIS:1\r\n"); sendMsg("@brightness VIS:1 VAL:100\r\n"); // led enable analogWrite(ledPin, 255); } else if(msg.startsWith("@light_on")) { Serial.println("GUI-O app is requesting LIGHT OFF!"); // "drive GUI-O app" sendMsg("@light_off VIS:1\r\n"); sendMsg("@light_on VIS:0\r\n"); sendMsg("@brightness VIS:0 VAL:0\r\n"); // led disable analogWrite(ledPin, 0); } else if(msg.startsWith("@brightness")) { const int idx = msg.indexOf(' '); if(idx > 0) { const int val = msg.substring(idx + 1).toInt(); if(val >= 0 && val <= 100) { Serial.print("GUI-O app is requesting LIGHT BRIGHTNESS: "); Serial.println(val); // led drive analogWrite(ledPin, static_cast<uint8_t>(val * 2.55)); sendMsg("@brightness VIS:1 VAL:val\r\n"); // Added to make CB show where I adjust brightness } } } } ``
-
@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
2.) Once the brightness is adjusted then the Nano Yellow LED STAYS on at the selected brightness even though the "on" and "off" light bulb image toggles okay and Serial Monitor correctly displays "GUI-O app is requesting LIGHT ON!" and "GUI-O app is requesting LIGHT OFF!". That was fixed by always keeping the 'ledPin' in the 'analog' mode by changing digitalWrite(ledPin, HIGH); to analogWrite(ledPin, 0); and digitalWrite(ledPin, LOW); to analogWrite(ledPin, 255);
Ok, my mistake. The
digitalWrite
overrides theanalogWrite
, disabling the PWM.@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
1.) The Slider Control knob always stayed at 100% even if it is set to a low brightness. That was fixed by adding the following instruction in the "led drive" section.
sendMsg("@brightness VIS:1 VAL:val\r\n");This is strange and requires further investigation... It seems that the
@light_on
is called - this can be the only reason that sets the slider value to 100... Something is not working correctly.@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
sendMsg("@brightness VIS:1 VAL:val\r\n");
This sends the literal "val", not the actual brightness value.
I suggest you put some Serial.print's at the beginning of the message parsing function to see what happens.
Best regards,
kl3m3n -
I agree something strange is happening. As suggested I added a bunch of Serial prints but the program flow looks correct to me.
For example I added code to print “Just set CB to 100%” as shown below:
sendMsg("@light_off VIS:0\r\n");
sendMsg("@light_on VIS:1\r\n");
sendMsg("@brightness VIS:1 VAL:100\r\n");
Serial.println("Just set CB to 100%");
which like you said is the only instruction where the CB slider gets set back to 100.However when I touch CB (at 50% for example) it changes the brightness and prints
GUI-O app requesting Brightness change!
GUI-O app is requesting LIGHT BRIGHTNESS: 50
just like it should but it never prints
Just set CB to 100%
even though the CB knob instantly jumps back to 100 when I release it.When I toggle the LED off it prints:
GUI-O app is requesting LIGHT OFF!
and when I toggle the LED back on it prints:
GUI-O app is requesting LIGHT ON!
Just set CB to 100%
just like it should. The problem persists and is puzzling.Here is another symptom which may help. When I add the “fix” instruction
sendMsg("@brightness VIS:1 VAL:val\r\n");
then the first time I change the brightness the CB knob always jumps back to 100 but from then on it works correctly and the knob remains at the position I select. If I toggle the LED off and back on then again the first time I use the CB control the knob always jumps back to 100 but from then on it works correctly.CONCLUSION: When the CB knob incorrectly jumps back to 100 the only instruction that sets CB back to 100 never gets executed. Is there any “hidden” code that gets executed, maybe parts of the Event Handlers or something?
Let me know if there is a specific test you would like me to try.
Thank you, Vince
-
@VNB Hi!
Can you open GUI-O and navigate to "Settings->Info" and tap on "Powered by GUI-O version" 10 times. At the bottom, a new menu (Developer mode) should appear. From this menu, you can enable "Log incoming messages".
You can then repeat the procedure with Arduino Nano and exit the GUI-O application when done. Then you can open the GUI-O files folder (best viewed on PC) and check the contents of the incoming log file. Does the log show setting the CB value to 100 (or higher, but gets limited at 100) when the CB widget "jumps" to 100?
Note that the log file is overwritten on next GUI-O start.
Don't forget to disable logging when done.
Best regards,
kl3m3n -
@kl3m3n
Here are the test results you requested. Everything looks normal to me and there does not appear to be any reason for the CB control to snap back to 100% but it always does.1.) Reset Nano, and serial prints:
Bluetooth device active, waiting for connections...2.) Start GUI on phone and serial prints:
Connected!3.) Click large center connect button of GUI on phone and serial prints:
Parsing . . .
GUI-O app is requesting INITIALIZATION!
and phone displays the Light Off image4.) Click TAP ME! and serial prints:
Parsing . . .
GUI-O app is requesting LIGHT ON!
Just set CB to 100%
and phone displays Light On image and CB control at 100%.5.) Tap near the center of CB control and when release the serial prints:
Parsing . . .
GUI-O app requesting Brightness change!
GUI-O app is requesting LIGHT BRIGHTNESS: 45
and the phone displays the CB control at 45% as long as I hold it but when I
release it the LED reduces brightness like it should but the CB control snaps back to 100%.6.) Trying a 2nd time, tap lower on CB control and when release the serial prints:
Parsing . . .
GUI-O app requesting Brightness change!
GUI-O app is requesting LIGHT BRIGHTNESS: 16
and the phone displays the CB control at 16% as long as I hold it but
when I release it the LED reduces brightness but the CB control snaps back to 100%.7.) Trying a 3rd time, tap low on CB control and when release the serial prints:
Parsing . . .
GUI-O app requesting Brightness change!
GUI-O app is requesting LIGHT BRIGHTNESS: 5
and the phone displays the CB control at 5% as long as I hold it but
when I release it the LED reduces brightness but the CB control snaps back to 100%.8.) Exit the GUI on the phone and serial prints:
Disconnected!9.) Using PC Explorer open in_messages.log file to get:
[2023-09-20T09:13:57.992] @init
[2023-09-20T09:13:57.996] @cls
[2023-09-20T09:13:58.023] @guis BGC:#FFFFFF
[2023-09-20T09:13:58.180] |LB UID:title X:50 Y:15 TXT:"Simple light switch" FFA:"font8" FSZ:3.5
[2023-09-20T09:13:58.239] |LB UID:tap_me X:50 Y:70 TXT:"TAP ME!" FFA:"font8" FSZ:3 FFA:"font5"
[2023-09-20T09:13:58.295] |CB UID:brightness X:50 Y:50 W:90 BTH:5 HAH:8 HAW:8 VIS:0 STA:135 ENA:45 FGC:#000000 SFGC:#FFFF00 BGC:#CBCBCB
[2023-09-20T09:13:58.340] |IM UID:light_off X:50 Y:50 IP:"https://i.imgur.com/3VbsS0Z.png" VIS:1
[2023-09-20T09:13:58.395] |IM UID:light_on X:50 Y:50 IP:"https://i.imgur.com/gNdck9A.png" VIS:0
[2023-09-20T09:14:05.913] @light_off 1
[2023-09-20T09:14:05.913] @light_off VIS:0
[2023-09-20T09:14:05.943] @light_on VIS:1
[2023-09-20T09:14:06.004] @brightness VIS:1 VAL:100
[2023-09-20T09:14:12.333] @brightness 45.8
[2023-09-20T09:14:15.932] @brightness 16.7
[2023-09-20T09:14:19.772] @brightness 5.4To me the Log shows everything is working correctly but the CB control on the phone always jumps back to 100%.
I have 14 sec video of above but it won't let me upload it (too big).Hope this helps
Vince -
@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
[2023-09-20T09:13:57.992] @init
[2023-09-20T09:13:57.996] @cls
[2023-09-20T09:13:58.023] @guis BGC:#FFFFFF
[2023-09-20T09:13:58.180] |LB UID:title X:50 Y:15 TXT:"Simple light switch" FFA:"font8" FSZ:3.5
[2023-09-20T09:13:58.239] |LB UID:tap_me X:50 Y:70 TXT:"TAP ME!" FFA:"font8" FSZ:3 FFA:"font5"
[2023-09-20T09:13:58.295] |CB UID:brightness X:50 Y:50 W:90 BTH:5 HAH:8 HAW:8 VIS:0 STA:135 ENA:45 FGC:#000000 SFGC:#FFFF00 BGC:#CBCBCB
[2023-09-20T09:13:58.340] |IM UID:light_off X:50 Y:50 IP:"https://i.imgur.com/3VbsS0Z.png" VIS:1
[2023-09-20T09:13:58.395] |IM UID:light_on X:50 Y:50 IP:"https://i.imgur.com/gNdck9A.png" VIS:0
[2023-09-20T09:14:05.913] @light_off 1
[2023-09-20T09:14:05.913] @light_off VIS:0
[2023-09-20T09:14:05.943] @light_on VIS:1
[2023-09-20T09:14:06.004] @brightness VIS:1 VAL:100
[2023-09-20T09:14:12.333] @brightness 45.8
[2023-09-20T09:14:15.932] @brightness 16.7
[2023-09-20T09:14:19.772] @brightness 5.4Try this:
@init
@cls
@guis BGC:#FFFFFF
|LB UID:title X:50 Y:15 TXT:"Simple light switch" FFA:"font8" FSZ:3.5
|LB UID:tap_me X:50 Y:70 TXT:"TAP ME!" FFA:"font8" FSZ:3 FFA:"font5"
|CB UID:brightness X:50 Y:50 W:90 BTH:5 HAH:8 HAW:8 VIS:0 STA:135 ENA:45 FGC:#000000 SFGC:#FFFF00 BGC:#CBCBCB
|IM UID:light_off X:50 Y:50 IP:"https://i.imgur.com/3VbsS0Z.png" VIS:1
|IM UID:light_on X:50 Y:50 IP:"https://i.imgur.com/gNdck9A.png" VIS:0
@light_off 1
@light_off VIS:0
@light_on VIS:1
@brightness VIS:1 VAL:50
@brightness VAL:45.8
@brightness VAL:16.7
@brightness VAL:5.4...VAL:... is missing.
-
@gammda Hi gammda,
I’m not sure what you mean. There is nothing listed under “Try this”
but thank you.
Vince -
@VNB For what it is worth in the original code (above) if I replace the incomplete/incorrect instruction
sendMsg("@brightness VIS:1 VAL:val\r\n");
with the following
sendMsg("@brightness VIS:1 VAL:"+ String(val) + "\r\n");
then everything works and the CB knob does NOT jump back to 100% and all is well.
-
@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
There were two minor problems.
1.) The Slider Control knob always stayed at 100% even if it is set to a low brightness. That was fixed by adding the following instruction in the "led drive" section.
sendMsg("@brightness VIS:1 VAL:val\r\n");The code:
@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
sendMsg("@brightness VIS:1 VAL:val\r\n");
is not correct (as you've already pointed out), since the val is a non-numeric string that GUI-O cannot convert to numeric string.
This is correct:
@VNB said in GUI-O with Nano 33 BLE and the ArduinoBLE Library:
sendMsg("@brightness VIS:1 VAL:"+ String(val) + "\r\n");
as the String constructor converts the val into numerical representation.
This code should not be necessary, since the value originates from CB, which should already have the correct position. The issue seems to originate from somewhere else, but I cannot see the problem...
Regards,
kl3m3n