-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
docs: Specify new machine.ADC and machine.ADCBlock classes #4213
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
Conversation
Why there's need for duplicate functions? Just read_mv() should be enough and will work on any port. (Btw, cc3200 is very good port to have in the mainline, should not be dropped.) And that's if "ADC" really should be able to read volts, instead of just doing generic analog to digital conversion. And was mentioned in previous discussions, "read" is a stream interface verb, if there's another easy alternative, it should be used, and here |
Well, there's no pattern of this "Block" suffix in the machine API, while the issue of "basic" vs "advanced" control of peripherals definitely exists. And makes sense to consider whether this "Block" naming would scale. For example, why not use "ADCExt"? |
docs/library/machine.ADCBlock.rst
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remember this pattern for the next time I2C/SPI API is discussed. Because with I2C, it should be the same - there should be a way to create an "I2C connection" object, over which normal stream interface works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I2C doesn't work with a stream interface because it's inherently a message based bus.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I2C doesn't work with a stream interface because it's inherently a message based bus.
There's nothing in stream interface per se which precludes it working with a stream of messages. It's a simple, powerful, reusable, composable abstraction. (Though yes, currently, mostly stream of bytes mode is well exercised with it. And yes, there're potential drawbacks with too much generalization and packing too much semantics in one interface, but issues with inconsistent design is far more numerous and obvious.)
Because
As talked about in #3943 (comment), a lot of actual ADCs provide a calibrated reading, and this seems the natural way to get such a calibrated value (and if it's not calibrated automatically then it would need to be done manually in the code to make sense of the measured value).
Read was chosen because it is an obvious choice: it's making a reading of the voltage, doing an action. "Get" implies that it's just a constant value that can be retrieved, and that getting twice in a row would yield the same value (which it won't). Using read keeps things more consistent because there's no need to remember if this particular class uses read, or get, or something else. Everything uses read, no need to think, muscle memory typing it is the same. If there was an extension added to read multiple values at once (eg over time, like stm32 has And |
Because it's not an extension to ADC. ADCBlock is supposed to represent an actual entity, the ADC converter block itself. Really ADC and ADCBlock should be ADCChannel and ADC respectively (like it is currently in cc3200), but I wanted to make it simpler for the vast majority of cases where only the "channel" is needed, and for ports that don't want to/can't expose the concept of ADCBlock. So ADC is an endpoint that reads values, and ADCBlock is the super-entity that "contains" ADC's. On some MCUs there can be multiple ADCBlock's, each representing one of the converters. |
Ok, sounds good. But another question isn't answered - is it a new pattern reusable across machine API, or just random adhoc case for ADC? |
Well, "main" and "convenience" contradict each other. "Main" should be something which is consistent and reusable across ports, and "convenience" can go into "from easy_hw import *".
Yes, that's the point - everyone will use it, and it won't be usable on non-FP ports. And (AFAIK) it's the first case of adding float func to machine API, and opens black hole with this stuff. And I'm not aware of any C low-level lib/HALs with return floats, and the promise was that MicroPython tries to not be much worse than C (and yes, using floats is worse - more overhead, slower operation). |
Why suddenly? "Get" is a standard accessor name, there's an "ADC" block, it maintains a current value, you use "get" to get it.
Easy to remember - "read" is reserved for streams and stream-likes, everything else tries to use "get".
That's exactly a danger of too much generalization, where it may lead to confusion or at least less clarity. |
(I obviously don't try oppose it in any way, just trying to provide a all-rounded review, including "devil's advocate" one. Because fairly speaking, nobody else cares how it's designed. The biggest issue IMHO is tainting machine API with floats. I'd bring an argument that if there's desire for cuteness, there's already CircuitPython API as an alternative, so it only makes to stick with "efficiency" requirement of the original machine API.) |
It could be reused for PWM and DAC, with PWMBlock and DACBlock. PWMBlock is very similar to Timer though. I guess anything that has the concept of "channel" could have a block that represents a combination of "channels". An alternative to ADCBlock would be to both:
See #4237 for a proposal about |
2f70c7b
to
744a29e
Compare
raspberrypi: implement os.urandom
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block.
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves micropython#6129. Part-resolves micropython#3943.
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves micropython#6219. Part-resolves micropython#3943.
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves micropython#6219. Part-resolves micropython#3943.
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves micropython#6219. Part-resolves micropython#3943.
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves micropython#6219. Part-resolves micropython#3943.
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves
Rework the ADC implementation to use the micropython#4213 API (mostly) adding support for calibrated voltage readings and the ADC2 block. Resolves
26ba500
to
644df4e
Compare
The new ADC methods are: init(), read_uv() and block(). The new ADCBlock class has methods: init() and connect(). See related discussions in micropython#3943, micropython#4213. Signed-off-by: Damien George <[email protected]>
644df4e
to
4d2f487
Compare
I've updated this based on discussion in #7788. The updated API looks like this: ADC(id, *, sample_ns, atten) # create ADC object
ADC.init(*, sample_ns, atten) # initialise
block = ADC.block() # get the associated ADCBlock
val = ADC.read_u16() # read value between 0-65535
val = ADC.read_uv() # read uV, integer
ADCBlock(id, *, bits) # create ADC peripheral object
ADCBlock.init(*, bits) # initialise
adc = ADCBlock.connect(channel) # connect to a channel
adc = ADCBlock.connect(source) # connect up a pin or other object
adc = ADCBlock.connect(channel, source) # connect a channel to a pin |
The new ADC methods are: init(), read_uv() and block(). The new ADCBlock class has methods: init() and connect(). See related discussions in micropython#3943, micropython#4213. Signed-off-by: Damien George <[email protected]>
Based on the discussion in #3943 here is my proposal for a revised
machine.ADC
class which is intended to be implemented by all ports to make the ADC class more standardised. The changes here include a newmachine.ADCBlock
class as well, which is used to allow further configuration of ADC if a port supports it.In summary the new interface is:
The API is split up this way into two classes (ADC and ADCBlock) so that basic and common functionality is easily available in the ADC class, and extended functionality is in ADCBlock. A given port only needs to implement ADC if that is all it can do, and already that gives 80% of the functionality. The ADC class is the one that would be used most of the time.
If a port wants to expose more control, and the user needs to use it, then the ADCBlock class is there for that. It allows to specify the resolution, and which channels are connected to which pins.
All existing ports should be able to fit into this model without a problem. In particular the gain settings can be used by nrf and esp32. stm32 can use the sample time.
It should be possible to update the ports in a backwards-compatible way to this new API because most of the methods are new and don't clash with existing ones. ADCBlock is completely new so won't clash with anything.
There is room for extensions to this API: ADC can have additional methods like
read_u24()
andread_uv()
, and ADCBlock might get methods to read internal channels, like voltage references and temperature.Note: it might be easier to read the diff of this PR in split view.