Standard API for drivers?
Re: Standard API for drivers?
Perhaps adding an iconic example of a simple driver and it's interface would be a good idea!
Re: Standard API for drivers?
Great idea, please go for it! (yes, I'm being manipulative here )platforma wrote:Perhaps adding an iconic example of a simple driver and it's interface would be a good idea!
Re: Standard API for drivers?
I'm now writing a driver for a distance sensor (VL6180), and it, as many sensors, requires a small delay between starting the measurement and reading the result. The usual way in the brave and wild world of Arduino to deal with this situation is to simply insert a random delay in there and move on. But of course this can be disastrous to any code that needs to do multiple things in a loop, especially when you use yield to implement co-routines, etc. So I was thinking about a better approach.
One simple way, and in fact one that directly translates into the sensor's i2c calls, is to have two separate methods, one for starting the measurement, and one for reading it, and clearly document that there has to be a delay between them. You can even have a third method that includes the delay, for people who just don't care.
But I was thinking, why don't we use the power of Python, and, in particular, a pattern that has been used in its standard library already (for instance, in https://docs.python.org/2/library/conte ... extmanager). That is, still have a single method, but instead of a function make it an iterator generator, and put yield in place of the delay. Then there is just a single function, but the user still has freedom as to how to implement the delay. It would look something like this:
What do you think?
One simple way, and in fact one that directly translates into the sensor's i2c calls, is to have two separate methods, one for starting the measurement, and one for reading it, and clearly document that there has to be a delay between them. You can even have a third method that includes the delay, for people who just don't care.
But I was thinking, why don't we use the power of Python, and, in particular, a pattern that has been used in its standard library already (for instance, in https://docs.python.org/2/library/conte ... extmanager). That is, still have a single method, but instead of a function make it an iterator generator, and put yield in place of the delay. Then there is just a single function, but the user still has freedom as to how to implement the delay. It would look something like this:
Code: Select all
def measure():
start_measurement()
yield
return read_measurement()
measurement = measure()
time.sleep_us(10)
result = next(measurement)
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: Standard API for drivers?
It's a neat idea but the implementation needs improvement. measure() is a generator function and the line
creates a generator without running it. The line
will result in a StopIteration error without yielding a value. Try something on these lines:
which produces the following at the REPL:
Note the lack of output from a = rats()
Code: Select all
measurement = measure()
Code: Select all
result = next(measurement)
Code: Select all
def rats():
print('Got here') # do the measurement
yield
yield 'Result' # fetch the result
Code: Select all
>>> a = rats()
>>> next(a)
Got here
>>> next(a)
'Result'
>>>
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: Standard API for drivers?
Hmm... seems my generator-fu is a little bit rusty. I have to check how that @contectmanager decorator is doing it with a single yield...
Re: Standard API for drivers?
OK, after some experimenting (sorry I didn't do that before posting, I though I remember the behavior correctly), I conclude that the way this works is too magical and un-intuitive. I guess the right solution would be to use futures/promises/deferreds here, but that's not in stdlib.
Re: Standard API for drivers?
By the way, anybody knows how expensive closures are? I would expect them to be rather costly, as they have to keep all the context and all. But something like this could look nice:
I could even record the time when the measurement was started, and throw an exception if you try to check too soon!
Hmm... actually...
would work too, and without the closure.
Code: Select all
def measure():
start_measurement()
def result():
return read_measurement()
return result
measurement = measure()
time.delay_us(10)
result = measurement()
Hmm... actually...
Code: Select all
class Sensor:
def measure(self):
self.start_measurement()
return self.read_measurement
Re: Standard API for drivers?
Hi,
I would like to share some concept I'm using when writing driver.
Here how I do conduct the work... not perfect but available for the mass.
https://github.com/mchobby/esp8266-upy
I do also like the example is to previous response. KISS concept... like it
I would like to share some concept I'm using when writing driver.
- API should also been Plateform Agnostic, so the __init__() should receive the required bus (and address when appropriate).
- API should use machine.I2C, machine.SPI, ... in priority.
- Driver should always include code sample , detailled readme (as manual) an comprehensive wiring example (Markdown is great).
Code: Select all
from machine import I2C
from trackball import Trackball
import time
i2c = I2C(2) # Y9=scl, Y10=sda or Pyboard-Uno-R3 (I2C over pin 13)
# initialise le trackball
trackball = Trackball( i2c )
https://github.com/mchobby/esp8266-upy
I do also like the example is to previous response. KISS concept... like it