PyRaspBeta

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 file traffic_light.py and 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") and expose(red=...), lights.red would 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 wiring from main.py is fine: defining the classes buys nothing, only creating a Module in circuit.py does.

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–9 and _, starting with a letter.