#Wemos form factor requirement

1 messages · Page 1 of 1 (latest)

tropic forge
#

@violet nebula my other question was why your project has a Wemos form factor requirement. Is that historical?

violet nebula
#

The framework itself doesn't directly care whether the board is Wemos D1 standard. However, I'm supporting a bunch of cool D1 "shield" style expansion boards from TerrainTronics for cool effects related stuff (NeoPixels, IR receivers, StemmaQT/Qwiic connectors, high power LEDs, ...)

#

So it's mainly about providing an extremely simplified "first time beginner" experience. For example:

  • buy THIS controller (some link on Amazon/wherever to a Lolin S2 Mini or clone)
  • buy THIS daughter board kit https://www.tindie.com/products/terraintronics/caernarfon-castle-kit/ (we've talked about him offering a totally pre-soldered version)
  • buy THESE Neopixels/WS2812s/... hence my wish for more of these with connectors, servos, Stemma QT boards, ....
  • press this link for the one-time setup of the S2 Mini
  • download this zip and "Extract All" into your CIRCUITPY drive
  • solder headers, etc as necessary to get things connected
  • ideally someone will eventually offer a "starter kit" with all this ready to go, including everything up to this point
  • pick an example, copy it into code.py, and season to taste
Tindie

1x Caernarfon Castle Kit, for 1 Door and 2 LED's

#

Currently I need to add a simple per-board configuration to support a new controller, but that's pretty trivial. However, part of the "special sauce" is that I can "normalize" a pin layout - so far I've only done this for the D1 Mini but there can be others - such that support for a compatible expansion/shield board is written using the normalized pin assignments. There are several CircuitPython compatible boards - like the Lolin S2 Mini, Lolin S3 Mini, Liligo T7-S3, ... - which support D1 Mini style shields. Of course, which actual pin ends up mapped to what used to be "D7" on the original ESP8266 D1 Mini can (and usually does) change with each board. So part of the per board configuration (for D1 Mini compatible boards) is which actual pin address/ID is used for each "normalized layout standard" pin.

#

With this in place, I can write "shield" driver code for a given "standardized layout" based on the normalized pin names, and that neither knows nor cares about the actual pin assignments. Same code works on any controller which is compatible with that type of shield/daughterboard.

tropic forge
#

so there is some kind of universal_board to substitute for board, I guess.

violet nebula
#

So here's the TL;DR;
Say you have a Caernarfon Castle for a project and want to use the IR remote receiver, two servos, a 37 led Neopixel chain, and a StemmaQT connection (all of these have a dedicated header / connector on the Caernarfon board) to a QT Rotary Encoder and an MPR121 breakout. Your code.py for the hardware configuration (no behaviors yet) could be something like

from .DemoCommon import *

class CaernarfonSimpleDemo( DemoBase ):
    def setup(self):
        main = self.main
        
        caernarfon = self.main.addCaernarfon( neoPixelCount=40 )
       
        bigRing     =  caernarfon.pixels.nextNLights(32)
        littleStick =  caernarfon.pixels.nextNLights(8)
        
        irReceiver  = caernarfon.addIrRemote()
        servo1      = caernarfon.initServo( 1,"servo1" )
        servo2      = caernarfon.initServo( 2,"servo1" )
        
        capTouch    = caernarfon.adafruitFactory.addMPR121()
        rotary      = caernarfon.adafruitFactory.addQTRotaryEncoder(caernarfon.i2c)

  # ...

demo = CaernarfonSimpleDemo( )
demo.run()
violet nebula
#

So not only do I not need to know the actual pins in the source for Caernarfon Castle driver, the need user doesn't need to know them either. They just say main.addCaernarfon(...) and the framework uses the mapping to then fill in the actual pins by looking them up in board and/or microcontroller

#

Ideally, for most projects an end user staying within the curated list of "beginner friendly" hardware and standardized "portable" connections (shields, StemmaQT/Qwiic sockets, ...) will never need to know or specify a pin assignment, i2c address, etc.

#

And their project code will work on any supported combination of controllers and "portable connection" addons without modification.

#

For example, I think I could add a "Feather Wing" mapping the same way I'm supporting the D1 Mini layout. Then I can add support for any Feather Wing accesory board. And create a configuration for any Feather controller mapping "Feather Wing" pins to the actual pins. Then you could write similar code to use any Feather Wing with any Feather controller (which is hardware compatible with that wing and supported by CircuitPython)

#

It's not a perfect solution - for example, if someone wants to directly use GPIO pins on the controller - say use pin 21 as a PWM output - they'll need to know the board specific pin assignment and which pin to connect physically. OTOH, if you wanted to set up a servo on channel 7 of an Servo FeatherWing, you might simply say something like

  servos = self.main.adafruitFeatherFactory.addServoWing()
  doorMotor = servos.initServo(7,"door")

in your setup code and connect your standard 3 pin servo to the labeled channel 7 pins on the Feather Wing

#

so as long as you're using supported shields/wings/etc. with clearly labeled connections, the whole "pin assignment" issue disappears

#

another little twist is that you should only need one import * from ... in your code.py

#

I have factories set up under the main Manager instance (might rename that, main is potentially confusing) so that all the supported hardware options are just a few auto-completes away - ni need to install, import, etc

#

Which is a bit of a pain to maintain, and problematic if you want more flexibility (like customizing something via inheritance), but works quite nicely for this project

tropic forge
#

Thanks for the explanations.

violet nebula
#

No problem. Some the ideas I'm working with go a long way back -(my C++ firmware meant to provide similar "beginner friendly" support is around a quarter million lines of code - and still in stealth mode. Another part of the "D1 Mini" bias is that I've been working with and supporting Dafydd at Terrain Tronics for quite some time - he's greate with electronics engineering, but a bit less experienced on software. Since he's been releasing some new products lately, and I didn't really feel like building stand alone code for them (that could be use without my C++ firmware), I decided it was finally time to see how quickly I could throw together some CircuitPython support. That was around three months ago. I got a bit carried away....

#

FWIW there are things in LCPF that would probably not be a good fit for general use with CircuitPython (it could end up getting quite messy if you want to draw outside the lines). And there are capabilities I'm putting in based on some powerful and potentially uncommon patterns and designs which I feel a bit, well, mercenary isn't the right word, but certainly disinclined to make available free for someone else to profit from.

#

That said, this whole second layer of "normalized shield/expansion board" definitions and the related bits which let you write driver code, board configurations, and user code without direct board pin assignments is NOT one of those things. It would probably take a bit of effort to refactor into a stand-alone system, but after that I'd have no problem releasing that under an MIT license and/or just turning it over to the CircuitPython community.

#

I think it could potentially become a common mechanism easing a lot of the "pin configuration" pain for just about any shield-like expansion board standard. And in and of itself, I can't think of anything that would prevent it from being cleanly used in a much wider range of project styles (not just the "simplicity-over-everything-else" extreme of LCPF).

violet nebula
# tropic forge Thanks for the explanations.

One other thing I wanted to mention... As I only started working on LCPF and learning CircuitPython around three months ago, it still has a ways to grow and isn't nearly as well documented as I'd like. That's part of my motivation for firehose responses like this - it helps organize thoughts and often ends up inspiring (if not outright being directly cut & pasted ) my documentation efforts.

tropic forge
#

Have you looked at Adafruit’s Wippersnapper system? More directed toward IoT, but meant to be no-code/low-code. just got a Blockly interfaces

#

not for robots!

violet nebula
#

Looking at your experience, it might be worth having a conversation about some architectural ideas and patterns specific to no/low-code systems someday. Graduate work on "Programming by Example".... very interesting. I have a loose collection of LCPF design goals at https://www.lumensalis.com/Projects/LCPF/Design/. It's not exactly "Programming by Example", but it will likely have a very strong "Programming by Examples" aspect - take something close to what you want and tweak it (part of why completely avoiding board/pin specific bits is so important). It's all about providing simple ways to specify what you want the system to do, without needing to tell it how. Strong "Domain Driven Design" flavors, more declarative than imperative. But that's for another day - for now I need more docs for getting new users going than internal design history....

violet nebula
# tropic forge Have you looked at Adafruit’s Wippersnapper system? More directed toward IoT, bu...

Haven't yet. but I'll check it out. But I've definitely dabbled with Blockly - started on some integration work (still far from complete) for using Blockly as a front end for the DSL built in to my C++ firmware. I've got a somewhat scattered but wide ranging browser UI for that system built on Next.js, React, Websockets, Three.js, etc with Blockly tied in as a (eventual) GUI for behavior specification

violet nebula
# tropic forge not for robots!

It could actually be quite appropriate and useful for toy robots. One specific goal is providing high level declarative domain grammar for temporal behaviors - potentially coordinated ones. Probably never enough to get a bipedal android walking, but patting it's head and rubbing it's tummy - sure. If you read the Example Use Case from the link above, a good example of the intent is "when I press the STOP button on my remote, close the door".

#

However it will be TOTALLY inappropriate for anything powerful or heavy enough to injure someone. I can - and have - built software for that, VERY different set of requirements and appropriate architectural strategies. But I'm guessing you already know that....

tropic forge
#

there are three people coding Wippersnapper + a designer

violet nebula
#

Looks like WipperSnapper can support at least the "when X happens, do Y" when Y is a more limited imperative behavior (which is actually a pretty cool thing)

#

I'm aiming a bit higher, but of course this has a cost in end-user extensibility. WipperSnapper may not be all that much better as it appears to require writing C++ code (and therefore the whole build/upload workflow) to facilitate more complex behaviors. OTOH, if you rebuilt WipperSnapper in CircuitPython, so talking to the "man behind the curtain" for fancy stuff was simply updating some .py files on your CIRCUITPY drive - that would probably be MUCH easier to extend than what I'm doing.

tropic forge
#

originally it was supporting plain ESP32. It's really for a different audience. It's worth trying to set up a board with it and see how it goes for youj.

violet nebula
#

But if I can anticipate+iterate well enough to sufficiently provide "all the verbs" needed specifically for a targeted domain, there shouldn't be much (any for the majority) need to paint outside the lines

tropic forge
#

I'm not saying that's the solution. I'm just saying it's an itneresting direction to look at

#

the code is open source in the adafruit github org

violet nebula
#

Man, the things I can already do with an ESP32... That's part of the "itch" behind this whole project - how could I provide a way for your average maker / DIY enthusiast to come anywhere close to what I can pull out of the hat without programming since the '80s