Sliders do not report value "0"


#1

I have a project with five sliders controlling an RGBW strand of LEDs. Four of the sliders control the four color channels; the fifth is a multiplier that I use to control overall brightness.

These LED strands take color channel values from 0:255, but to make things more user (non-techie) friendly, I’ve set up my sliders to run from 0:100 with an increment of 0.5. When my ESP receives this value, it multiplies this as a percentage to get the proper 0:255 value to pass to the LED driver.

What I have found is that none of the sliders will actually send a value of 0 when the slider is all the way to the left. I figured this was either an edge case (where the lower limit, whatever it may be, is never sent) or, more likely, a Boolean error (where the slider must have a non-zero value for the value for the value to be sent.

I ruled out the edge case by setting the lower limit to -0.5 on one slider. With the slider all the way to the left, my ESP does receive a
value of -0.5. However, when I slide it slightly right to zero, that value never gets sent (or received; I can’t tell which :slight_smile: )

This is on Chrome browser on a Macbook. ESP Wemos D1 mini as device node.

All of the receiver “functions” (I assume they’re macros) follow this format:

// Channel 11 will be used to set the R value. Passed as a %; stored as 
// a 0-255 value
CAYENNE_IN(11) {
  Serial.print("Received on channel 11: ");
  Serial.print(getValue.asString());
  Serial.print(" == ");
  Serial.println(getValue.asInt());

  double dValue = getValue.asDouble();
  R = dValue * 255/100.0;
  //colorWipe(strip.Color(R*brightness, G*brightness, B*brightness, W*brightness), 0);
  colorSet(strip.Color(R*brightness/100.0, G*brightness/100.0, B*brightness/100.0, W*brightness/100.0));
}

#2

Hey again @beerreason,

I simplified this problem down a little bit and I’m not having any trouble reporting a value of 0 from my slider widgets. Here is what I tried (using an Arduino Uno but since we’re not doing anything device specific here I don’t think it matters)

#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
  
// If you're not using the Ethernet W5100 shield, change this to match your connection type. See Communications examples.
#include <CayenneEthernet.h>

// Cayenne authentication token. This should be obtained from the Cayenne Dashboard.
char token[] = "myAuthToken";

void setup()
{
  Serial.begin(9600);
  Cayenne.begin(token);
}

void loop()
{
  Cayenne.run();
}

CAYENNE_IN(2) {
  Serial.print("Received on channel 2: ");
  Serial.println(getValue.asInt());
} 

Using this, I created a slider with range -10 to 10 and step value of 1. I’m able to see the value set on the slider output to the serial monitor (with a caveat – everything is multiplied by 1023 since this issue is still open, but can be worked around easily enough in code by dividing it out). Here is the result from my setting the slider to 0, then 1, then 2, then 3 and back to 0 again


#3

Sorry, not working for me. Did you try a range from 1:100 with increment of 0.5? I also see that you’re using getValue.asInt(), and not .asDouble() – this might be the biggest difference between the two tests, now that I study my own output more closely.

Here’s my project:

And here’s my serial port output:

Notice that the getValue.asInt() returns a zero when the .asDouble() returns 0.5. I’m using a double so that my slider can show 0:100% but I can get better granularity than just 101 integer values. Where you see it returning 0.5 (double) or 0 (int), I also around the same time tried moving the slider to the zero point, but my code didn’t receive the update until I moved it slightly away from zero.

I can provide the full .ino if it would help, but I think you need to rerun your test with .asDouble() and take a look at what happens there.

Thanks!


#4

Hi again.

So I noticed from the server connected to at the top of your log that you were using the Cayenne Arduino MQTT library (as opposed to the Cayenne Arduino library) which I was using in my initial test. This explains why you weren’t seeing everything multiplied by 1023 like I was – so apologies if I confused you there :slight_smile:

However, even after switching to the MQTT library, switching my code to getValue.asDouble(), and making my slider go from 0 to 100 with a step of 0.5, I’m seeing expected results. (In fact better, since there is no confusing multiplication by 1023).

Here is my output from setting the slider to 2, 45.5, 0, 18, 0.5, 0, 100:

And my code (basically just the example code with the fake sensor data stripped out for simplicity, and with the CAYENNE_IN(10) block added to print the result to serial):

//#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial
#include <CayenneMQTTEthernet.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "MY_MQTT_USERNAME";
char password[] = "MY_MQTT_PASSWORD";
char clientID[] = "MY_MQTT_CLIENTID";

unsigned long lastMillis = 0;

void setup() {
	Serial.begin(9600);
	Cayenne.begin(username, password, clientID);
}

void loop() {
	Cayenne.loop();
}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
	CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
	//Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

CAYENNE_IN(10) {
  Serial.print("Received on channel 10: ");
  Serial.println(getValue.asDouble());
}

I would be interested in your code just to see if anything else could be going on there, or if this could be a more subtle bug. At the same time, I’d be curious if mine suffices to allow you set the slider to 0 and actually get a zero value back in response.


#5

Thanks – sorry I’ve been out of touch for a few days; I’ll try your code tonight if possible.

However, as I think about it, we might be looking on the wrong end. What I’m seeing is that my CAYENNE_IN() receiver function just never even gets called when the slider is on zero, so I’m not sure it matters that much what I have inside the {}, right? In other words, now I’m back to suspecting something more on the dashboard end, not the ESP8266.

Last week I tried to trace through the preprocessor #define macros that create the receiver functions, but couldn’t find anything helpful.


#6

Update 1:
I tried accessing the web dashboard on my Android tablet. First, I used the Chrome browser. I set the White channel of my LED strand to somewhere between 50-100. Then I slid the “brightness” multiplier all the way down to zero. To my surprise, the strand went completely dark. I then slid the brightness up, and it came back on.

The more interesting part is that this was NOT repeatable. Every time I slid it to zero after that, it would not zero-out the brightness.

Next, I tried the Firefox browser with the same results! The first time I slid the brightness slider to zero, my strand went black. After sliding it back up and then down again, it would not go back to zero.

The only way to completely turn off the LED strand in this scenario is to turn down each color channel to a really low value (like 2 or 3) and then move the brightness slider down to a really low value. Because the LED driver software takes an 8-bit integer, and I’m multiplying my color channel value with my brightness value, the resulting value gets rounded/truncated to zero. Yes, it works, but it’s not a friendly workaround if I just want to slide my dimmer to zero.


#7

Update 2:
The code you sent does not compile for the ESP8266 Wemos D1 mini. I’m on Arduino 1.6.8 on a Macbook, ESP board package 2.3.0-rc2

If I change the
#include <CayenneMQTTEthernet.h>
to
#include <CayenneMQTTESP8266.h>
it compiles. The error I get is really long, but it starts with the following.
NOTE: When I compile your code with the #include that works, the slider still does not report a zero value.

Arduino: 1.6.8 (Mac OS X), Board: "WeMos D1 R2 & mini, 80 MHz, 230400, 4M (3M SPIFFS)"

In file included from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTEthernetClient.h:21:0,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTEthernet.h:23,
                 from /Users/wte/Documents/Arduino/CayenneTest/Slider_no_zero_test1/Slider_no_zero_test1.ino:3:
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneArduinoMQTTClient.h: In instantiation of 'static void CayenneArduinoMQTTClient::publishData(CayenneTopic, unsigned int, const T&, const char*, const char*) [with T = const __FlashStringHelper*; CayenneTopic = CayenneTopic]':
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneArduinoMQTTClient.h:125:66:   required from here
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneArduinoMQTTClient.h:333:3: error: call of overloaded 'add(const char*&, const __FlashStringHelper* const&)' is ambiguous
   values.add(subkey, data);
   ^
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneArduinoMQTTClient.h:333:3: note: candidates are:
In file included from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTClient/CayenneMQTTClient.h:24:0,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMessage.h:32,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneHandlers.h:29,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneArduinoDefines.h:128,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneArduinoMQTTClient.h:21,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTEthernetClient.h:21,
                 from /Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTEthernet.h:23,
                 from /Users/wte/Documents/Arduino/CayenneTest/Slider_no_zero_test1/Slider_no_zero_test1.ino:3:
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTClient/../CayenneUtils/CayenneDataArray.h:106:15: note: void CayenneMQTT::DataArray<BUFFER_SIZE, MAX_VALUES>::add(const char*, int) [with int BUFFER_SIZE = 64; int MAX_VALUES = 4] <near match>
   inline void add(const char* unit, const int value) {
               ^
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTClient/../CayenneUtils/CayenneDataArray.h:106:15: note:   no known conversion for argument 2 from 'const __FlashStringHelper* const' to 'int'
/Users/wte/Documents/Arduino/libraries/CayenneMQTT/src/CayenneMQTTClient/../CayenneUtils/CayenneDataArray.h:121:15: note: void CayenneMQTT::DataArray<BUFFER_SIZE, MAX_VALUES>::add(const char*, unsigned int) [with int BUFFER_SIZE = 64; int MAX_VALUES = 4] <near match>
   inline void add(const char* unit, const unsigned int value) {
               ^

#8

My test was with an Arduino Uno, I didn’t think the hardware difference would matter in this case, but perhaps that is the hint here. I have an ESP around here I need to solder some pins onto then I can test on the same platform.

I don’t suspect this would matter either, but I’m on Arduino IDE version 1.8.1 (the latest is actually 1.8.3 and can be downloaded here: https://www.arduino.cc/en/Main/Software. Just in the interest of standardizing our tests. I’ll report back as soon as I get a chance to run that.


#9

Sounds good. I’ll upgrade the IDE on my end.

You really should try the Wemos D1 mini! No pin headers to solder, USB-to-serial is built in, 5V-to-3.3V built in, very low cost, lots of great shields to expand with. Now the ESP32 is starting to catch on as well, with similar shields/accessories.

However, I am still inclined to think that we’re barking up the wrong tree – that it might be the front end that never sends the zero value, rather than the back end that doesn’t process it, even after receiving it. But we’ll see…