phoddie / node-red-mcu

Node-RED for microcontrollers
129 stars 18 forks source link

Wemos D1 Mini Analogue input noisy #101

Closed colinl closed 1 year ago

colinl commented 1 year ago

I am experimenting with the analogue input sensor node on a Wemos D1 Mini. With a flow with only an inject (repeating every two seconds), analog and MQTT Out nodes I am seeing that the signal received is noisy. Running with a straight short on the input I am seeing values that are either 0.00782 or 0.01270. Scaling back to the original ADC values those map to 8 and 13. Mostly the value is 8 but occasionally flicks up to 13 for one or a few samples. Occasionally I also see 7 or intermediate values. If I apply a voltage I see a similar absolute amplitude noise, again flicking between the two values. Slowing the sample rate down makes no difference, neither does speeding it up, until it crashes if I go too fast (less that about 0.7 seconds).

Downloading an Arduino sketch performing the same task to the same device, I see a solid 7 from the ADC with the input shorted, and with a voltage applied I again see a solid reading

phoddie commented 1 year ago

Analog inputs are often noisy. It is common to do some filtering.

Downloading an Arduino sketch performing the same task to the same device, I see a ... solid reading

The Arduino ESP8266 implementation of analogRead simply calls system_adc_read. The Moddable SDK ECMA-419 analog read does the same. Not obvious what is different.

colinl commented 1 year ago

I know about noise on analogue inputs. I have been using the analogue input on these devices for a couple of years. It isn't noise. Unless something in the running of the code is coupling noise into the ADC hardware. That doesn't seem likely, the Arduino code is driving MQTT just the same as the mcu code is.

phoddie commented 1 year ago

I know about noise on analogue inputs.

I imagined that was the case. Not everyone reading this thread may share your experience.

I have been using the analogue input on these devices for a couple of years. It isn't noise.

I am open to ideas about why the same API in flash is behaving differently in these two different runtimes.

colinl commented 1 year ago

Well unfortunately I think you must be correct. The code basically just calls the system function so it is difficult to see how it can go wrong. It isn't random noise as on startup it is consistently stable for about 10 seconds before it starts moving about. Perhaps it is something like noise in the regulated voltage caused by the increased processor load, wifi, etc, and for the first ten seconds the smoothing caps can supply the power and keep it stable. Perhaps the much simpler code in the arduino code, which is basically just a loop reading the ADC and posting it to MQTT, is able to be supplied by the regulator more easily. Whatever, it means that I can't use this for the application I was hoping to use it for, which is a pity.

phoddie commented 1 year ago

Since you have something that does appear to work more reliably, I'd like to understand that better. At the moment, I have text descriptions but not code or versions. Would you share the sketch and the version number of the Arduino ESP8266 port that you are using?

If your theory that the increased load of Node-RED is the cause, then running a simple Moddable SDK should match your output. Let's try. The example at $MODDABLE/examples/pins/analog is a good starting point. It uses a screen, but let's just reduce main.js to:

import Analog from "pins/analog";
import Timer from "timer";

Timer.repeat(() => {
    trace(Analog.read(0) + "\n");
}, 100);

How does that output compare?

colinl commented 1 year ago

version number of the Arduino ESP8266 port

It says 1.8.3 at the top of Help About, but I think that may not be what you are after. I can't find anything specifically about the port version.

Here is the sketch, I added .txt on the end to keep github happy.

I will see if I can get the example to go. I haven't done anything directly in Moddable.

colinl commented 1 year ago

Hmm, that didn't appear to upload the file. Trying again. analog_test.ino.txt

colinl commented 1 year ago

The example you suggested gives me a stable 9, with an occasional 10 thrown in.

phoddie commented 1 year ago

Thanks for the example sketch. Actually, very interesting reading for me. But, no particular clue about analog behaviors.

The test result is helpful. There is some known interaction between Wi-Fi and analog on ESP8266. This example has Wi-Fi off, so that may explain why it is stable. Let's try with Wi-Fi enabled:

Noisier?

colinl commented 1 year ago

There is some known interaction between Wi-Fi and analog on ESP8266.

Yes, that is it. Now I get virtually identical results as when I run the test flow, including the 10 second stable readings at the start, then alternating a few seconds high, a few seconds low and so on. It is interesting that I don't see that with the Arduino sketch even though it is actively using the wifi to publish to MQTT.

phoddie commented 1 year ago

That's very helpful, thank you.

I think there is code buried in the Arduino implementation to try to reduce the noise on Analog caused by Wi-Fi. I need to study that more carefully and see if it has changed since the version of Arduino we're pinned to.

phoddie commented 1 year ago

Just adding some notes... like all thing ESP8266, the available information is strange. This Espressif page talks about analog on ESP8266 and ESP32. This note about ESP8266 is relevant:

Please use adc_read() for ADC acquisition when Wi-Fi is on. To ensure data stability, you need to use function esp_wifi_set_ps(WIFI_PS_NONE) to turn off Wi-Fi Modem-sleep mode

That function is part of their RTOS for ESP8266, which is not used on the Arduino side.

I'm also able to reproduce roughly the behavior you describe - it isn't quite 10 seconds of stable readings here, but maybe 6 or 7.

No solution yet... but steps.

colinl commented 1 year ago

Did you note that I am using a old version of the Arduino IDE? I can update and try again if that would be helpful, though that may mean I can't get back again of course.

phoddie commented 1 year ago

Did you note that I am using a old version of the Arduino IDE? I can update and try again if that would be helpful, though that may mean I can't get back again of course.

Thanks for pointing that out. At the moment, I don't think the Arduino IDE version is a contributing factor. But I will keep it in mind.

The Espressif documentation references esp_wifi_set_ps. That function doesn't exist in the runtime we are using. However, it appears to be an alias for wifi_set_sleep_type -- both control the Wi-FI modem sleep behavior -- which is available. There are some forum posts which seem to confirm they are functionally equivalent, FWIW.

I did a quick experiment that seemed to generate clean analog results. But, it was a quick experiment and our hardware is different. So... maybe you could try too? In the file $MODDABLE/modules/network/wifi/esp/modwifi.c, add the following after line 153.

wifi_set_sleep_type(NONE_SLEEP_T);
colinl commented 1 year ago

Brilliant, with that line in it is solid as a rock. I have even added this test into the flow running the ds18b20s so there is asynchrous wifi activity (sensor values via mqtt) going on at the same time. That is with the input shorted. I can't test it connected to anything until I have completed the DS18B20 tests.

phoddie commented 1 year ago

Lucky guess. ;)

Thank you for verifying that. I'll merge the change.

colinl commented 1 year ago

I have tested with the latest moddable and node-red-mcu from git and it is working well. I am getting basically solid readings, with occasional +-1 bit noise, and that might be real voltage fluctuations. I will close this as fixed. Great stuff.

phoddie commented 1 year ago

Awesome. Thank you!