-
Notifications
You must be signed in to change notification settings - Fork 639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple Virtual Analog Ports #2620
Comments
So, from the sensor configuration side, it would be enough to just provide it with TYPE of analog source and PIN / CHANNEL / some-kind-of-a-name-for-ID ? Right now something similar is happening with GPIO pins and. e.g., relays w/ mcp pins, rfb pins, sonoff pins. Relay config asks for a certain TYPE of a pin, provider gives out a pin handler that API consumer promises to then use for reads & writes. I do not really like the word 'virtual' here, as it does continue to use real hardware channel and just requires some extra work before doing so :) Source does change, though.
fwiw cd4052b pdf linked describes a general purpose multiplexer, so generic pin read & write can also use those as inputs & outputs and not just analog. |
Hi;
AnalogSensor.h
Names are tentative |
Yes, multiplexing is general, but my main restriction is that there is only one analog port. |
Right, sensor specific code is possible. What I mean is to separate things ever so slightly. Just to play around with this... You can already override // in any .cpp file, global namespace
int multiplexer_read(uint8_t pin) {
???
}
extern "C" int analogRead(uint8_t pin) {
switch (pin) {
case A0: // 17
return system_adc_read();
case 0 ... 7: // or some other unused numbers in the 0...255 range
return multiplexer_read(pin);
}
return 0;
} Extend NTCSensor code to allow PIN value changes, make a setup() code to instantiate multiplexer and then change What I meant is to integrate multiplexer system-wide, not sensor specifically.
|
Nice. It's not really necessary modify AnalogSensor, extending and overriding NTCSensor is enough; anyway I like modify AnalogSensor because my idea was support multiple analog sensor in general, not only ntc sensors (MICS2710 sensor for example)
No much. It is related to the class DigitalPin?
I think I understand your idea, but it seems to me that making this extension for the entire system is too complex. The problem is that there are sensors that use more than one port, but for relays, buttons, and analog sensor, yes, because they use only one port. |
Now I think I'm understanding your idea; I didn't know about providers support. To multiplex buttons I propose two new types of providers Then, to define a digital multiplexed button, say, number 5, you would specify the following entries in the configuration btnProv5=3 Ok, but what code should be modified/extended? button.cpp? |
Not quite the same as e.g. MCP support flag. It adds extra type for pin, but button continues to use GPIO provider and digital reads. espurna/code/espurna/config/hardware.h Line 5158 in ac01afc
espurna/code/espurna/config/hardware.h Lines 5161 to 5162 in ac01afc
espurna/code/espurna/config/hardware.h Lines 5175 to 5176 in ac01afc
btnMuxAddress aka 'Multiplexer channel to which the hardware is connected' is btnGpio. Since the main use-case is digital access
Analog buttons in this case also re-use the same config, changing btnProv to analog would still be able to access type and pin number which in turn would use a different proxy class to read specific MUX channel on ADC |
On the other hand, to extend not only buttons, but also relays or LEDs (in general, to use a multiplexer as output), I think it is necessary to use not only a multiplexer, but also a buffer; this buffer is enabled using the additional port |
Hi. Apologies, but I've been rethinking these ideas and I think:
Following up on this last idea, a perhaps simple way for future analog sensors to make use of multiplexing is to use a special encoding to specify their "pin" when calling analogRead(uint8_t pin): To configure the analog multiplexer as a whole, the keys you proposed can be used, except muxComGpio (the analog multiplexer output must always be connected to pin A0 of the microcontroller). |
Also true. Still, generic input support is a possibility? It does run into the case of not-the-best-tool-for-the-job, yes. Suppose, such multiplexer api can be cut out from allowing OUTPUTs, limiting pin abstraction to INPUTs only. Expander, shift registers, etc. can be allowed to support both.
Ah. So, the Arduino side supports both by checking whether input is Note that analogRead replacement is intended for 'variant' / 'board' / 'only-works-on-this-hw' override. e.g. https://github.com/esp8266/Arduino/blob/ccea72823ac50290bc05c67350d2be6626e65547/variants/wifi_slot/analogRead.cpp#L6 I do still lean to the idea of separating mux + analog and just analog through gpio type... But, still have to think about it some more. |
Well, here is my first attempt. Note that I added not only support for multiple NTCs but also for multiple Emon sensors (current support for multiple emon sensors requires additional hardware more complex than a simple multiplexer). I think this would be a good general scheme to support any other type of analog sensor in which more instances are required. New variables of preprocessor: AnalogMux_SUPPORT New settings: Files: AnalogMux.h
NTCMuxSensor.h
EmonAnalogMuxSensor.h
|
Ah...
sensor.cpp:2619
|
Hi. a more concrete version: AnalogMux.h
NTCMuxSensor.h
I think the code is almost usable, although I'm not sure if I'm using the APIs correctly. Any suggestion is appreciated. |
Well, these days I realized two things:
I think using ADS1115 should be the standard way to expand analog inputs, possibly at AnalogSensor level. |
ADC noise not related to power / specific board / lack-of stable power input? Does current ADS1115 work?:) I do remember tweaking read loops at some point, and non-working bitmask for old configs, but i don't really remember whether it was tested. Plus, not sure I have the part around rn |
I tested it with the code where AnalogSensor calculated the averages wrong; with your latest modifications and using several samples per access it will probably generate less variations.
The code I read is related to an Emon sensor; I don't know if it works well, but accessing ADS1115 seems relatively simple. |
Well, this is my last idea: delegate all the analog reads to a separate class, which is independently configured (in runtime) and potentially supports several devices that generate analog reads (one of which is ESP8266 itself), each of which may have several channels/pins. On the other hand, an additional field must be added to AnalogSensor, input_device_id; When you want to do the analog reading, AnalogSensor delegates it to the new class (AnalogInputs).
Next week I'm going to buy an ADS1115 and I'm going to try to make a usable version. |
Note that most of the time in the current code, object handle is passed directly and consumer only cares about the interface not the detail that there is some kind of 'object' / 'device' id included. But not to repeat myself, I am returning to the 'port' analogy from above
I do also wonder how much of a difference there is between the genuine part and cheaper CJ-..., GY-... , etc. variants |
I don't understand what you mean by "the genuine part and cheaper CJ-..., GY-... , etc. variants" |
Try searching e.g. aliexpress, chips are ADS1x15 analogues |
Right, this is the implementation. Should the reader remember the id internally to pass it along to the analoginputs? In sensor class, I mean. Or terminal |
Hello, just recently I had time to advance the code. TODO: |
analog_inputs.h
|
sensor.cpp in load()
|
RawAnalogSensor.h
|
AnalogSensor.h modifcations
public methods
new members
|
My current problem is what to do in
How to implement a time out? |
As a guess, For non-blocking... just check the clock? Otherwise, see espurna/code/espurna/system_time.h Line 114 in 1366713
espurna/code/espurna/network.cpp Lines 128 to 133 in 1366713
|
I think so, in one shot mode the reading time is inversely proportional to the datarate plus a small additional time needed to exit sleep mode (although I would have to investigate this further).
Would the following code work?
Although I find it not very energy efficient... Using blockingDelay is probably a better solution. |
If Lines 193 to 202 in 1366713
(and note that duration:: types are all unsigned underneath; delta between durations / time points is always a positive number)
|
Nice. As for energy efficiency (the loop is continuously executing i2c reads...), I looked at blockingDelay and it seems to me that it simply ends up executing delay(); wouldn't the following code be more or less equivalent (and simpler):
|
Correct, but it also depends what you would prefer more - readability of the name The reason for the |
Okay. Incidentally, I was reading that the delay should only be used in the main loop (and not, for example, interrupt routines). Does the sensor code always run in the main loop? I think in general yes, but I have my doubts if it cannot be executed in the interrupt routine or TCP/IP stack code from the execution of commands in the debug terminal (I seem to remember that there was a command to, for example, read the ADC of Esp8266). Btw, the previous code was wrong, I think this one would work:
|
Sensor methods are ok for delay()s, so are terminal commands possibly calling something with delay()s Both yield() and delay() are indeed made to only work within setup() & loop(). Though, calling them outside of that context would crash the board, so I'd expect that occurrence would be pretty easy to spot. fwiw, unless you are manually writing tcp / udp servers or clients with espasynctcp or using lwip callbacks, you won't happen within networking task |
Description
Hello. It's been a while since I wrote something. Greetings to everyone.
Motivation: The ESP8266 has only one analog port, which does not allow measuring more than one analog sensor. Personally, I need to measure multiple temperatures using NTC sensors (the digital sensors supported by Espurna haven't worked well for me); but beyond that, this modification would allow the use of multiple analog sensors of any kind (pressure sensors, humidity sensors, etc.).
Proposal: Allow Espurna to use "multiple virtual analog ports" with the help of an external analog multiplexer and the use of digital ports.
The general idea can be seen here:
https://www.youtube.com/watch?v=OgaeEiHemU4
or here (9.2 Typical Application):
https://www.ti.com/lit/ds/symlink/cd4052b.pdf?ts=1726728167254
I suppose the main modification should be made in AnalogSensor, allowing several instances of it, each associated with different "virtual analog ports." What AnalogSensor should do is: before reading the real analog input (pin 0), set the corresponding input of the multiplexer, wait for a small delay, and then read the analog value (see _rawRead() and analogRead(pin)).
At the configuration level, to enable this functionality, one should set something like:
#EnableVAP=1 // enables virtual analog ports
#DVAP= 1 or 2 or 3 // Number of digital ports connected to the multiplexer
#DVAP0= digital port to use for specifying bit 0 of the multiplexer port address
#DVAP1= digital port to use for specifying bit 1 of the multiplexer port address
#DVAP2= digital port to use for specifying bit 2 of the multiplexer port address
With these modifications, it would be possible to read from up to 8 analog devices.
Solution
No response
Alternatives
No response
Additional context
No response
The text was updated successfully, but these errors were encountered: