Can't set Menu Widget labels programatically

I’m unable to set the labels for the Menu widget from my program. When I try, the labels don’t change in the app.

void setupDropdown() {
  BlynkParamAllocated items(ws2812fx.getModeCount());
  for (int i = 0; i < ws2812fx.getModeCount(); i++){
    Serial.println(ws2812fx.getModeName(i));
    items.add(ws2812fx.getModeName(i));
   }
   Blynk.setProperty(V5,"labels",items);
}

I also tested:

   Blynk.setProperty(V5, "labels", "item 1", "item 2", "item 3");

but that didn’t update the Menu in the app either.

I’m using Blynk library 0.6.1 and app v2.26.0 on iOS

any ideas?

are you 10% certain that V5 is the correct pin number?

I don’t really use this widget, but I believe this will only ever populate the first menu item with whatever value is in items

And unless you actually used different strings for the three item placements… well, “Item x” is what the default display shows anyhow, thus I don’t think you would notice any visible changes.

image

Yes, definitely V5

1 Like

That doesn’t make sense about items only populating the first item, and not what the documentation says

1 Like

Do you have multiple devices in your project?
If so, is the auth code in the sketch the same as the one for you he device that the menu widget is attached to?

Pete.

Yes everything else works in the project, just not filling the menu from the hardware

I just had a thought. I’m connecting the ESP32 to the app via the bluetooth device, not via the network. could it be that the arduino setup routine runs before it has connected via BLE to the app, and so if I am updating the menu from the arduino setup function, it gets called too early. and never updates it?

1 Like

Sure it makes sense… although as I already mentioned, I really don’t use this widget… so I leave the experimenting up to you.

But I believe it works like this…

String items = "My Test Label ";
Blynk.setProperty(V5,“labels”,items);

… Will populate the first spot with “My Test Label”

And even if you programmatically keep changing the contents of the string items and resending it in a loop, it will only overwrite the 1st spot, not automatically fill the 2nd, 3rd, etc.

As I understand it, the only way to put a Label into spot 3 would be to also put something into spots 1 & 2 at the same time with a single command…

Blynk.setProperty(V5,“labels”, "Label 1", "Label 2", "Label 3");

Hmm… OK, looking at your code a bit closer, I see that you are trying to merge all your labels for the final command…

Personally, I would test with something much simpler first.

Either of these works as expected for me…

Blynk.setProperty(V80, "labels", "Eeny", "Meeny", "Miny", "Moe");
BlynkParamAllocated items(128); // list length, in bytes
items.add("Eeny");
items.add("Meeny");
items.add("Miny");
items.add("Moe");
Blynk.setProperty(V80, "labels", items);

Sorry, I just saw this.

Without full code to see… That depends on where in your setup, before or after the Blynk.begin(), you have these menu commands.

Of course it may also have to do with the fact the BT/BLE does have some limitations compared to a full device-network link.

thanks for the pointers @Gunner. I seem to have the Blynk.begin(auth); in the wrong spot. I’ll fix this up and test when I get home from work.

code below for reference:

#include <WS2812FX.h>
#include "/home/jason/Arduino/libraries/WS2812FX/examples/ws2812fx_esp32/ESP32_RMT_Driver.h"
#include <AceButton.h>


#define BLYNK_PRINT Serial

#define BLYNK_USE_DIRECT_CONNECT
#define BLYNK_MAX_SENDBYTES 256 // Default is 128


#include <BlynkSimpleEsp32_BLE.h>
#include <BLEDevice.h>
#include <BLEServer.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "redacted";


using namespace ace_button;

const int BUTTON_PIN = 35;



#define LED_COUNT 40
#define LED_PIN 25

#define TIMER_MS 5000

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_RGB + NEO_KHZ800);

// set up LCD
WidgetLCD lcd(V4);


unsigned long last_change = 0;
unsigned long now = 0;

//int inPin = 35;     
//int val = 0;

AceButton button(BUTTON_PIN);

void handleEvent(AceButton*, uint8_t, uint8_t);





BLYNK_WRITE(V0)
{   
  int value = param.asInt(); // Get value as integer
  if (value == 1) {
    Serial.println("button on");
    // turn LED strip on
    ws2812fx.start();

  } else {
    Serial.println("button off");
    // turn LED strip off
    ws2812fx.stop();
  }
}

BLYNK_WRITE(V1)
{
  int brightness = param.asInt();
  ws2812fx.setBrightness(brightness);
}

BLYNK_WRITE(V2)
{
  int speed = param.asInt();
  ws2812fx.setSpeed(speed);
}


BLYNK_WRITE(V5)
{   
  int mode = param.asInt() -1; // Get value as integer, subtract 1 for offset
  ws2812fx.setMode(mode);
  Serial.printf("mode: %d\n",mode);
}


void setupDropdown() {
  BlynkParamAllocated items(ws2812fx.getModeCount());
  for (int i = 0; i < ws2812fx.getModeCount(); i++){
    Serial.println(ws2812fx.getModeName(i));
    items.add(ws2812fx.getModeName(i));
   }
   //Blynk.setProperty(V5,"labels",items);
   Blynk.setProperty(V5, "labels", "item 1", "item 2", "item 3");
   Blynk.setProperty(V6, "labels", "item 1", "item 2", "item 3");

}

void setup() {
  Serial.begin(115200);
  Serial.print("initialising\n");
  ws2812fx.init();
  ws2812fx.setBrightness(100);
  rmt_tx_int(RMT_CHANNEL_0, ws2812fx.getPin()); // assign ws2812fx1 to RMT channel 0
  ws2812fx.setCustomShow(myCustomShow);
  ws2812fx.setSpeed(200);
  ws2812fx.setColor(0x007BFF);
  ws2812fx.setMode(FX_MODE_STATIC);
  ws2812fx.start();
  Blynk.virtualWrite(V0,HIGH);

  //pinMode(inPin, INPUT);        // sets the digital pin 7 as input
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  button.setEventHandler(handleEvent);

  Blynk.setDeviceName("LED Hat");

//  Blynk.begin(auth, ssid, pass);
  Blynk.begin(auth);

  Blynk.setProperty(V1,"min",BRIGHTNESS_MIN);
  Blynk.setProperty(V1,"max",BRIGHTNESS_MAX);
  Blynk.setProperty(V2,"min",SPEED_MIN);
  Blynk.setProperty(V2,"max",SPEED_MAX);
  Blynk.virtualWrite(V1,ws2812fx.getBrightness());
  Blynk.virtualWrite(V2,ws2812fx.getSpeed());
//  lcd.clear();
//  lcd.print(0,0,"12345678901234567890");
//  lcd.print(0,1,"11111111111111111111");
  
//  lcd.print(0,0,ws2812fx.getModeName(ws2812fx.getMode()));

  setupDropdown();
}

void loop() {
  now = millis();

  ws2812fx.service();
  button.check();
  Blynk.run();
//  Blynk.virtualWrite(V1,ws2812fx.getBrightness());
//  Blynk.virtualWrite(V2,ws2812fx.getSpeed());

}

// Custom show functions which will use the RMT hardware to drive the LEDs.
// Need a separate function for each ws2812fx instance.
void myCustomShow(void) {
  uint8_t *pixels = ws2812fx.getPixels();
  // numBytes is one more then the size of the ws2812fx's *pixels array.
  // the extra byte is used by the driver to insert the LED reset pulse at the end.
  uint16_t numBytes = ws2812fx.getNumBytes() + 1;
  rmt_write_sample(RMT_CHANNEL_0, pixels, numBytes, false); // channel 0
}


void handleEvent(AceButton* /* button */, uint8_t eventType,
      uint8_t /* buttonState */) {
  switch (eventType) {
    case AceButton::kEventPressed:
      ws2812fx.setMode((ws2812fx.getMode() + 1) % ws2812fx.getModeCount());
      last_change = now;
      Serial.printf("button pressed");
      Serial.printf("mode: %d ", ws2812fx.getMode());
      Serial.print(ws2812fx.getModeName(ws2812fx.getMode()));
      Serial.printf("\n");
      //lcd.clear();
      //lcd.print(0,0,ws2812fx.getModeName(ws2812fx.getMode()));
      lcd.clear();
      lcd.print(0,0,"12345678901234567890");
      lcd.print(0,1,"11111111111111111111");
   
      break;
    case AceButton::kEventReleased:
//      digitalWrite(LED_BUILTIN, LED_OFF);
      break;
  }


}

I was following the example for SetProperty MultiValue on github

https://github.com/blynkkk/blynk-library/blob/master/examples/More/SetProperty/SetProperty_MultiValue/SetProperty_MultiValue.ino#L45-L49

    BlynkParamAllocated items(128); // list length, in bytes
    items.add("New item 1");
    items.add("New item 2");
    items.add("New item 3");
    Blynk.setProperty(V1, "labels", items);

Yes, I saw that.

Can you test with a simple sketch (Blynk Blink type) and basic commands like I tried… see if that works or not?

I also recommend trying with both BLE and WiFi to see if that is part of the issue.

Sorry, I forgot to mention that I did test with a simple example with the same result.

However that was before my discovery of having the Blynk.begin(auth) in the wrong spot. I’ll do more testing tonight.

thanks

I finally resolved this. The problem was that I thought BlynkParamAllocated items(x); would allocate x menu entries, but in fact it seems to allocate total bytes to store all the text for the menu entries.

1 Like