Custom components
A custom component is a part you make yourself out of shop parts. It's one Python file in your library that holds a Module for circuit.py, plus driver code for main.py if you like. Once it's in your library, any workspace can bring it along: the daily contest, practice and the sandbox.
Why bother? In a contest your score is the time you used, plus a penalty for what your build costs, plus one for each wrong submission. A component you've already built and tested helps with all three:
- Cost. A component costs exactly what its parts cost. Design it lean once, and every build that uses it is cheaper.
- Time. On contest day you import it in one line instead of wiring from scratch.
- Mistakes. Wiring and driver code you've tested in practice don't cost you wrong submissions.
Making one
Open the Components tab in any workspace and fill in New component, or use Start a component on the component library page. You pick:
- a module name: lowercase letters, digits and underscores, like
traffic_light. It becomes the filetraffic_light.pyand the name you import. Names Python or the installed libraries already use (time,math,gpiozero,wiring…) are taken. - a title, like Traffic light, shown in lists.
The new component starts as a working example (an LED with its resistor) to change. It opens in a tab next to circuit.py and main.py. Edits stay in that workspace until you press Save to library (the tab shows ● while there are unsaved changes). On the component's own page you can edit the title, the description and the code, and publish it.
What goes in the file
"""A traffic light: three LEDs with their resistors and a shared ground."""
from wiring import *
class TrafficLight(Module):
def build(self):
red, yellow, green = LED("red"), LED("yellow"), LED("green")
r1, r2, r3 = Resistor(330), Resistor(330), Resistor(330)
r1 >> red
r2 >> yellow
r3 >> green
red.cathode >> yellow.cathode
yellow.cathode >> green.cathode
self.expose(red=r1.pin1, yellow=r2.pin1, green=r3.pin1, gnd=red.cathode)
# Driver code for main.py can live in the same file.
from gpiozero import LED as _Led
class TrafficLightDriver:
def __init__(self, red, yellow, green):
self.lights = {"red": _Led(red), "yellow": _Led(yellow), "green": _Led(green)}
def show(self, colour):
for name, light in self.lights.items():
light.value = name == colour
circuit.py uses the Module:
from wiring import *
from traffic_light import TrafficLight
pi = Pi()
lights = TrafficLight()
connect(pi.GPIO17, lights.red)
connect(pi.GPIO27, lights.yellow)
connect(pi.GPIO22, lights.green)
connect(lights.gnd, pi.GND)
and main.py uses the driver:
from traffic_light import TrafficLightDriver
from time import sleep
lights = TrafficLightDriver(red=17, yellow=27, green=22)
for colour in ["red", "yellow", "green"]:
lights.show(colour)
sleep(1)
Everything about Modules (build(), expose(), chain(), parameters) is on the Modules page. Two things to watch:
- An exposed pin can't share its name with an attribute: with
self.red = LED("red")andexpose(red=...),lights.redwould be ambiguous, so the build stops with an error. Keep inner parts in local variables (as above) or give them other names (self.red_led). - Importing
wiringfrommain.pyis fine: defining the classes buys nothing, only creating a Module incircuit.pydoes.
In a build
The Components tab lists the components in this build, each with its import line. Your library is underneath: Add puts one in the build, Remove takes it out (it stays in your library). A build can bring up to 8 components. Run, Run tests and Submit all use them, and the board groups each Module's parts together.
The bill counts every part a component buys at its shop price, exactly as if you'd written the parts in circuit.py. A component is never a shop item with a price of its own (unlike kits).
In the daily contest
The daily contest accepts components you wrote yourself. When you submit:
- unsaved edits to your components are saved to your library first;
- the server copies each component's code into the submission, so later edits don't change a build that's already submitted or accepted;
- a build that brings a component you didn't write (someone else's, or your copy of someone else's) is refused before it reaches the judge, without a penalty. The Components tab marks those not allowed in contests.
Once the day is over, the winning builds open with their components included. See past solutions.
Sharing
Publish on a component's page makes it public: anyone can read it on the component library and copy it into their own library. Copies work in the sandbox and practice, not in the contest. Builds you share in the community carry their components' code, so whoever opens your post gets a build that runs. If the component is published, they can also copy it from the post.
Limits
- up to 50 components in a library, 8 in one build;
- up to 50,000 characters per component;
- module names: 2–40 characters,
a–z,0–9and_, starting with a letter.