8000 Add docs / photos describing PyCon UK related discussion on API. by ntoll · Pull Request #24 · bbcmicrobit/micropython · GitHub
[go: up one dir, main page]

Skip to content

Add docs / photos describing PyCon UK related discussion on API. #24

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

Closed
wants to merge 1 commit into from

Conversation

ntoll
Copy link
Contributor
@ntoll ntoll commented Sep 22, 2015

This PR still needs work and contributions before we forget it all.

I suggest we leave this open only 24h so we give people a chance to revise yet we make progress quickly. I'm anxious we don't stymie @whaleygeek's efforts with an ever changing API.

@dpgeorge
Copy link
Member

I think we should not add images to the repo. They make it big (and are always there in the version control). Instead let's just transcribe their content to text.

@matthewelse
Copy link
Collaborator

@dpgeorge @ntoll, perhaps the wiki functionality on GitHub would be good for this?

@dpgeorge
Copy link
Member

A wiki could be used. Right now time is of the essence so we should just use whatever means we can to flesh out the API. Feel free to make a wiki page if you like (It could be used later on for general API reference).

I think we also decided that animate would take the "wait" and "loop" keywords. Other functions like print and scroll can also take the "wait" keyword (and even the "loop" keyword makes sense for them).

@matthewelse
Copy link
Collaborator

@dpgeorge
Copy link
Member

I updated the wiki to reflect new decisions on API.

One thing to consider: read_analog / write_analog take/return a number between 0 and 1023. That range is pretty obscure for kids. We can make it an integer between 0 and 100, or even a float between 0 and 1. Any comments?

@markshannon
Copy link
Collaborator

I like the idea of using a float between 0.0 and 1.0 for analog values. It matches up with the digital values nicely.

@markshannon
Copy link
Collaborator

How familiar are 11 year olds with decimal fractions? I was 11 too long ago to remember :)

@dpgeorge
Copy link
Member

How familiar are 11 year olds with decimal fractions?

Yes, probably an integer (between 0 and 100) is much easier.

@ntoll
Copy link
Contributor Author
ntoll commented Sep 27, 2015

I vote whole numbers between 0-100 since pretty much all children, no matter their ability level, will understand this.

(N.B. When I was a teacher, I'd get 1 or 2 kids out of a 100-ish-person cohort in each year 7 who couldn't count to 100 for various SEN [special educational needs] reasons. Teachers will be aware of who these pupils are and should have strategies in place to deal with this, all coordinated by the school's SENCO [special educational needs co-ordinator] whose task it is to make sure such kids have joined-up and consistent support).

@markshannon
Copy link
Collaborator

OK, 0 to 100 it is. I'm going to accept floats as well (in the same range) so that microbit.pin0.write_analog(100/3) will work.

@dpgeorge
Copy link
Member

I'm going to accept floats as well (in the same range) so that microbit.pin0.write_analog(100/3) will work.

Yes, I think this is a good idea. Forcing the kids to do int(100/3) is pointless, it just makes it harder for them, and doesn't really teach them anything.

Similarly set_analog_period_microseconds should accept a float and truncate it to an int.

See also #7.

@larryhastings
Copy link
Collaborator

On 09/27/2015 10:48 AM, Damien George wrote:

I'm going to accept floats as well (in the same range) so that
microbit.pin0.write_analog(100/3) will work.

Yes, I think this is a good idea. Forcing the kids to do |int(100/3)|
is pointless, it just makes it harder for them, and doesn't really
teach them anything.

Just asking: is the range [0..100)? As in, you will see the value 0,
you will see the value 99, but you will never see the value 100? Or do
we actually want [0..100], with 101 possible values?

(And, did you mean int(3/100)?)

//arry/

@markshannon
Copy link
Collaborator

The range is [0..100] with 101 values.
I meant 100/3, but you can use 3/100 if you want :)

@dpgeorge
Copy link
Member

Just asking: is the range [0..100)?

It is a good question. I think it should be [0..100].

But now that I think more about this range I realise that we lose a lot of precision with an analog return value between 0 and 100. The internal ADC is 10 bit and so 1023 is it's maximum value. I'm pretty sure the device can achieve this resolution and I don't think we should unnecessarily truncate.

Options:

  1. We stick with 1023 being maximum (should we anyway be deviating from TD for this matter?).
  2. We use [0..1000].
  3. We use [0..100] but return a float so the precision is there if needed.
  4. We use [0..3.3] to represent the voltage on the pin (since that's actually what is measured).

@ntoll
Copy link
Contributor Author
ntoll commented Sep 27, 2015

My 2c as the devil's advocate... although I'm happy to be shot down and concede... ;-)

I believe that if there is an input that has a range of possible values we should expose the full range in the simplest form possible. If there are 1024 possible values then I believe that's what we should report. That we can do it with integers is a plus because all children are likely to understand this concept (whereas floats will confuse some of them).

To counter the "but 1024 is weird" point: that's only the same as starting to count from 0, but we don't worry about that! Also, as kids become more familiar with programming they will start to encounter such base 2 related numbering and recognise them for what they are. I believe this is simply another way in which we're gently introducing fundamental aspects of computers. (But I concede this is a rather arbitrary position to take - I guess it has more to do with taste and intuition about such things than any hard or fast rule.)

It also means we're uniform with TouchDevelop. This is a good thing except for when TouchDevelop is obviously wrong :-)

For example, some of TD's names for things are bonkers IMHO - this is a matter of taste about naming things and we have our own heuristics for doing this - KISS, short, easy to spell, commonly used vocabulary, no acronyms etc... In contrast, it's not a matter of taste that analog input has a range of 0-1023 - that's just how it works because of its physical properties.

To go all highfalutin - the former is a socially constructed description (i.e. some human has decided some name because they think that's the way it should be), whereas the latter is scientifically derived (we can go check that there is in fact a range of only 1024 possible values one can extract from the pin).

If TD "socially constructs" weird names then we should ignore them and do the right thing. If TD exposes a range of 1024 possible values because that's the way the device works, then we should do the same.

Does this make sense?

@larryhastings
Copy link
Collaborator

On 09/27/2015 12:53 PM, Damien George wrote:

Just asking: is the range [0..100)?

It is a good question. I think it should be [0..100].

But now that I think more about this range I realise that we lose a
lot of precision with an analog return value between 0 and 100. The
internal ADC is 10 bit and so 1023 is it's maximum value. I'm pretty
sure the device can achieve this resolution and I don't think we
should unnecessarily truncate.

Options:

  1. We stick with 1023 being maximum (should we anyway be deviating
    from TD for this matter?).
  2. We use [0..1000].
  3. We use [0..100] but return a float so the precision is there if
    needed.
  4. We use [0..3.3] to represent the voltage on the pin (since that's
    actually what is measured).

Let me paraphrase* Albert Einstein and say: an API should be as simple
as possible, but no simpler. TBH I think 0..1000 and 0..100 are bad
APIs; in an attempt to "simplify" the API we have made it clunky and
lost precision. I assume [0...3.3] would be a float value, which means
it combines the conceptual overhead of the float value with the
inconvenience of magic value 3.3.

So let me ask you: what API would /you/ want? That's easy: [0..1) as a
floating-point value. There's been some concern in the thread that
11-year-olds would have problems with the concept of a range from 0 to

  1. I'm not an educator of 11-year-olds so I can't really speak to
    that. All I can suggest is, we all know how convenient it is, and maybe
    preteens could simply learn the invocation "now divide by your total
    range and pass that in". Also again maybe this would inspire the
    inquisitive children to ask "why?" and learn something.

If we really can't do [0..1), in my opinion the only other sensible
choice is [0..1023](or [0..1024) if you prefer).

Actually I think we can improve that slightly:
pin0.set_analog_range(n)
could set the range to [0..n]**. Then the child could

We could even continue to accept floats, so if they have a range from 0
to 100 and pass in 55.3 we could set the analog value to 566 (and not
floor it to 563).

Oh! And then the clever kids (and us) could call
pin0.set_analog_range(1)
and use the API we really wanted anyway.

//arry

/* Apocryphally, at least.

** I'd prefer it be [0..n), as that's enormously more Pythonic. But I
fear again that will be seen as too conceptually messy for the kids.
Maybe we can have a nice argument about it!

@ntoll
Copy link
Contributor Author
ntoll commented Sep 27, 2015

@larryhastings
Copy link
Collaborator

On 09/27/2015 01:42 PM, Larry Hastings wrote:

So let me ask you: what API would /you/ want? That's easy: [0..1) as
a floating-point value. There's been some concern in the thread that
11-year-olds would have problems with the concept of a range from 0 to

  1. I'm not an educator of 11-year-olds so I can't really speak to
    that. All I can suggest is, we all know how convenient it is, and
    maybe preteens could simply learn the invocation "now divide by your
    total range and pass that in". Also again maybe this would inspire the
    inquisitive children to ask "why?" and learn something.

One more thought. How many kids are going to get as far as noodling
around with analog outputs? Maybe it's far enough into the belly of the
beast that we can afford to leave it as an "advanced" API and use [0..1)?

//arry/

@ntoll
Copy link
Contributor Author
ntoll commented Sep 27, 2015

Of course the underlying voltage is the actual physical property being measured and a range of 1024 possible values is somewhat arbitrary, but my devil's advocacy about introducing a familiarity with base 2-ish number still stands.

@larryhastings wrt 11yo noodling with analog out - that'll depend a lot on the teacher and how such concepts are introduced.

Personally, I think I like 0..1 but I'm not sure how kids would find it.

Since I have an 11yo to hand (not immediately, he's asleep upstairs) I could do some subtle testing to see what he and his buddies find easiest.

@dpgeorge
Copy link
Member

We did have a long discussion about this point (ADC return value) for MicroPython proper (see micropython/micropython#1130). In order to be consistent across boards that have different ADC resolutions, and not take the performance hit associated with floating point (and also loss of precision in some cases), the decision was to left shift the result to 16 or 24 bit width, so the maximum would be 0xffff or 0xffffff.

Given all of the above, to keep it simple but close to the hardware, go for [0..1024) = [0..1023]. If kids use analog in/out then they'll soon learn what the range means.

BTW, analog out should have the same range as in.

@sparkslabs
Copy link
Collaborator

Personally, I'd stick with 0-1023.

Thinking process:

It's the same then as the other platforms then. Yes, it might seem a little
odd initially, but on an scale of 0 to 1023, how odd? (by not changing it
you're not introducing an extra thing to learn)

The other thing is that while yes, 1023 is odd, it gives people an excuse
to find out why it's odd, which leads eventually to base 2, and the fact
it's 1024 values, and all that useful stuff.

As a general principle, I'd just ask when things turn up like this "do we
need to change it". If the answer is "no", personally I'd leave it. Also,
the corollary question would be "Are we introducing confusion by changing
it?" and if the answer is "yes", I'd definitely avoid changing it unless
necessary :-)

By way of example of something from around 9-10 months back: Co-ordinates
for pixels. There was an expectation from one part of the team that
co-ordinates would start in the bottom left - like in maths. The was an
expectation from another part (writing the code/building stuff) that
co-ordinates should start in the top left - like they do with the vast
majority of computer graphic co-ordinate systems. After much discussion, we
decided that while it might cause a little confusion initially - (due to
mismatch with maths) that the fact that it would be useful to use the same
origin as the bulk of computer graphics systems. It provided a good reason
to point out how computers vary from expectations.

So based on comments, the ADC is a 10bit ADC, and that gives arise to 1024
values. That's a useful concept to NOT hide IMO. ie by using 0..1023 we
avoid hiding the fact that continuous values when sampled by computers go
into a range of discrete values. That in itself then maps to all sorts of
bits of the curriculum - in computing but also to design technology, and
probably beyond.

So the questions I'd have is:

  • Do we need to change the range ?
  • Are we hiding a useful concept if we make it a float?

My conclusion based on reading the thread is that leaving it unchanged
makes most sense, but mainly commenting because hopefully the why is more
useful. :-)

Michael.

On 27 September 2015 at 21:30, Nicholas Tollervey notifications@github.com
wrote:

My 2c as the devil's advocate... although I'm happy to be shot down and
concede... ;-)

I believe that if there is an input that has a range of possible values we
should expose the full range in the simplest form possible. If there are
1024 possible values then I believe that's what we should report. That we
can do it with integers is a plus because all children are likely to
understand this concept (whereas floats will confuse some of them).

To counter the "but 1024 is weird" point: that's only the same as starting
to count from 0, but we don't worry about that! Also, as kids become more
familiar with programming they will start to encounter such base 2 related
numbering and recognise them for what they are. I believe this is simply
another way in which we're gently introducing fundamental aspects of
computers. (But I concede this is a rather arbitrary position to take - I
guess it has more to do with taste and intuition about such things than any
hard or fast rule.)

It also means we're uniform with TouchDevelop. This is a good thing except
for when TouchDevelop is obviously wrong :-)

For example, some of TD's names for things are bonkers IMHO - this is a
matter of taste about naming things and we have our own heuristics for
doing this - KISS, short, easy to spell, commonly used vocabulary, no
acronyms etc... In contrast, it's not a matter of taste that analog input
has a range of 0-1023 - that's just how it works because of its physical
properties.

To go all highfalutin - the former is a socially constructed description
(i.e. some human has decided some thing because they think that's the way
it should be), whereas the latter is scientifically derived (we can go
check that there is in fact a range of only 1024 possible values one can
extract from the pin).

If TD "socially constructs" weird names then we should ignore them an do
the right thing. If TD exposes a range of 1024 possible values because
that's the way the device works, then we should do the same.

Does this make sense?


Reply to this email directly or view it on GitHub
#24 (comment)
.

@dpgeorge
Copy link
Member

Thanks @sparkslabs that is very useful feedback. We will keep it at 0..1023 (for both analog read and write).

It is great to know that there are things like this (and the LED coordinates) that have had a lot of thought and discussion put into them already. We (uPy on the microbit developers) should not try to second guess or re-discuss such things; it's not a good use of time.

The problem is we don't know which parts have had discussion and feedback from users. Looking at some parts of the 8000 TD design it seems that not everything is fully thought through, and it's hard to tell which bits are and which are not.

If we had a list of API design decisions which have been thoroughly discussed then that would make development go much smoother.

@dpgeorge
Copy link
Member

TD use pause(ms) instead of sleep(ms)... I think we should change to pause to match them.

@ntoll
Copy link
Contributor Author
ntoll commented Sep 29, 2015

Hmm... I'm not sure... Python has time.sleep which "feels" the same as microbit.sleep. We have to ask ourselves are we consistent across platforms or across Python modules (if you see what I mean)..?

BTW, I'm not sure what the right answer is right now.

Intuitively I'd keep sleep given that's what the DAL uses too (so C++ programmers will use sleep). Happy to be persuaded otherwise. Perhaps TD should change pause to sleep..? ;-)

@dpgeorge
Copy link
Member

I think TD originally called it sleep and changed it to pause following discussion/feedback, but that's a vague memory. Would be nice to know the details of their decision.

@msprotz
Copy link
Collaborator
msprotz commented Sep 29, 2015

Yeah I don't remember. Maybe it's the name that they used in the pilot project a year ago. In any case, sleep is kind of a technical term -- pause actually makes more sense I believe.

I think it's ok to have the discrepancy.

@larryhastings
Copy link
Collaborator

Do we want to be consistent with TD, or with Python--and the entire rest of the world? I vote for the latter and leave it as sleep().

@sparkslabs
Copy link
Collaborator

We used "pause" in the prototype we used in schools in January

(cf http://bug.iotoy.org/bug/create_program/) .

I don't recall there being a big discussion about it TBH. Pause in my
opinion makes more sense than sleep because it left us open to having a
function called "sleep" that would allow the device to actually properly
sleep.

The prototype slept a lot to conserve power - to the extent that the main
display interrupt could be characterised like this: (pseudo code :) )

for i in 0..4:
for j in 0..4:
if display[i,j]:
switch on pixel
set watch dog timer for minimal time
sleep # ( actually switch everything off)
# woken from interrupt microseconds later
switch pixel off

There was an item in the backlog (never gotten to :-) - to expose the
"sleep for X seconds" behaviour in the API. That would've allowed the
device to run for a couple of weeks (probably) with intermittent, but
active independent behaviour on a coin cell.

Anyway, I digress. Pause seemed more appropriate than sleep in the context
probably because the docs we provided at the time also said "After 3
minutes the device will go to sleep" (which we did in the end for the trial

  • again to conserve power). That behaviour could be overridden though.

We documented the sleeping behaviour here:
http://bug.iotoy.org/downloads/FAQ/Microbug_FAQ.pdf

You'll see what I mean.

When you have that concept of sleep - which on an embedded device can
really mean everything on the device goes to sleep, that's why we picked
pause. I guess the reason we didn't have a big discussion about it at the
time was probably due to the fact that sleeping was one of the design
choices.

I don't have strong feelings either way about it, but if I was going to
decide again, I'd pick pause for similar reasons.

Michael.

On 29 September 2015 at 16:50, Jonathan Protzenko notifications@github.com
wrote:

Yeah I don't remember. Maybe it's the name that they used in the pilot
project a year ago. In any case, sleep is kind of a technical term -- pause
actually makes more sense I believe.

I think it's ok to have the discrepancy.


Reply to this email directly or view it on GitHub
#24 (comment)
.

@sparkslabs
Copy link
Collaborator

To larry's point, if this is valid in micropython on micro:bit:

import time
time.sleep()

Then I would suggest that that sleep operates the same as
microbit.pause() :-)

Michael

On 29 September 2015 at 17:14, Michael sparks.m@gmail.com wrote:

We used "pause" in the prototype we used in schools in January

(cf http://bug.iotoy.org/bug/create_program/) .

I don't recall there being a big discussion about it TBH. Pause in my
opinion makes more sense than sleep because it left us open to having a
function called "sleep" that would allow the device to actually properly
sleep.

The prototype slept a lot to conserve power - to the extent that the
main display interrupt could be characterised like this: (pseudo code :) )

for i in 0..4:
for j in 0..4:
if display[i,j]:
switch on pixel
set watch dog timer for minimal time
sleep # ( actually switch everything off)
# woken from interrupt microseconds later
switch pixel off

There was an item in the backlog (never gotten to :-) - to expose the
"sleep for X seconds" behaviour in the API. That would've allowed the
device to run for a couple of weeks (probably) with intermittent, but
active independent behaviour on a coin cell.

Anyway, I digress. Pause seemed more appropriate than sleep in the context
probably because the docs we provided at the time also said "After 3
minutes the device will go to sleep" (which we did in the end for the trial

  • again to conserve power). That behaviour could be overridden though.

We documented the sleeping behaviour here:
http://bug.iotoy.org/downloads/FAQ/Microbug_FAQ.pdf

You'll see what I mean.

When you have that concept of sleep - which on an embedded device can
really mean everything on the device goes to sleep, that's why we picked
pause. I guess the reason we didn't have a big discussion about it at the
time was probably due to the fact that sleeping was one of the design
choices.

I don't have strong feelings either way about it, but if I was going to
decide again, I'd pick pause for similar reasons.

Michael.

On 29 September 2015 at 16:50, Jonathan Protzenko <
notifications@github.com> wrote:

Yeah I don't remember. Maybe it's the name that they used in the pilot
project a year ago. In any case, sleep is kind of a technical term -- pause
actually makes more sense I believe.

I think it's ok to have the discrepancy.


Reply to this email directly or view it on GitHub
#24 (comment)
.

@ntoll
Copy link
Contributor Author
ntoll commented Sep 29, 2015

I'm with Larry - MicroPython is a version of Python and we should remain consistent within the wider Python ecosystem.

I realise this is a question of taste. :-)

@markshannon
Copy link
Collaborator

FWIW The DAL has a sleep function, but no pause.
It is an energy efficient sleep and has a minimum (accurate) duration of 6ms. Seems perfect to me.
Why would we want "pause"?

@dpgeorge
Copy link
Member

In this case I consider whether or not the devices does a low-power sleep during a sleep/pause call an implementation issue that doesn't need to concern the user (well not usually). To support proper MCU sleeping requires a method to wake, usually by an real-time-clock alarm interrupt, or external pin interrupt, and I don't expect these details to be exposed in our child-friendly API.

So we should think more about the indented meaning of sleep/pause/delay rather than how it's implemented.

"Pause" has connotations of pressing pause on a video player or remote control, where everything stops until you press play/continue. I don't think that's what we want, because background animations/music can continue. Instead the device is "waiting", most likely to give the user time to interact (eg read the display). So microbit.wait() might be the right word, but that's breaking with tradition, so microbit.sleep() is also ok.

@sparkslabs
Copy link
Collaborator

@mark - FWIW, I have no strong feelings either way. I was just explaining
why we used pause then :-) -- since @jonathan raised the issue of the
prototype. The card I had in the backlog for the prototype - that never got
reimplemented was for their to be sleep(time) as well as pause(time).

pause(time) had the same effect as python's time.sleep - but took the
variant clock speed into account. (We'd ratch back the clock speed again to
boost battery life, so this was another reason to use that rather that
"delay"). sleep(time) would have the same meaning as jeelibs'
"loseSomeTime" function - which effectively does a hardware powerdown/sleep
and uses watchdog timers to wake up after the given time period. (The
jeelibs stuff I'm referring to is here - http://jeelabs.org/tag/lowpower/
and really interesting if you're trying to squeeze lots of run time from
teeny batteries :-) )

That's however a historical artefact and only mildly interesting.
Wouldn't've raised it if @jonathan hadn't mentioned the prototype and I
thought filling in the context may be useful :-)

As mentio B9E6 ned, I don't have strong feelings about this since, esp given
there's good pythony reasons for sleep :-)

Michael.

On 29 September 2015 at 20:48, Mark Shannon notifications@github.com
wrote:

FWIW The DAL has a sleep function, but no pause.
It is an energy efficient sleep and has a minimum (accurate) duration of
6ms. Seems perfect to me.
Why would we want "pause"?


Reply to this email directly or view it on GitHub
#24 (comment)
.

@ntoll
Copy link
Contributor Author
ntoll commented Oct 2, 2015

Given the original content associated with this ticket is now in the Wiki and now that we appear to have a consensus about sleep and return value for analog reads... I'll close this issue.

Happy to re-open if need be but I don't expect to.

@ntoll ntoll closed this Oct 2, 2015
@dpgeorge dpgeorge deleted the pyconuk-api-braindump branch October 16, 2015 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
0