Introductory Examples - Adafruit Crickit with CPB

The Adafruit Crickit for Circuit Playground Bluefruit is a baseboard providing motor drivers and other useful I/O for a Adafruit Circuit Playground Bluefruit. It communicates with the Bluefruit using the I2C bus. The follow samples demonstrate uses of the Crickit hardware using adafruit_crickit library. For more detailed notes on the library, please see Quick Reference Guide - Adafruit Crickit with CPB.

Pulsing Motor Example

This sketch pulses a small DC motor on and off using the Crickit motor channel 1.

Direct download: pulse_motor.py.

 1# crickit/pulse_motor.py
 2
 3# Demonstrate timed activation of a DC motor connected to the Crickit motor driver.
 4
 5# Related documentation:
 6# http://docs.circuitpython.org/projects/crickit/en/latest/
 7# http://docs.circuitpython.org/projects/seesaw/en/latest/
 8# https://learn.adafruit.com/adafruit-crickit-creative-robotic-interactive-construction-kit
 9
10# ----------------------------------------------------------------
11# Import standard Python modules.
12import time, math
13
14# Import the Crickit interface library.
15from adafruit_crickit import crickit
16
17# ----------------------------------------------------------------
18# Enter the main event loop.
19
20while True:
21
22    crickit.dc_motor_1.throttle = 1 # full speed forward
23    time.sleep(2)
24
25    crickit.dc_motor_1.throttle = 0 # stop
26    time.sleep(2)

Toggling Motor Example

This sketch uses touch control to turn a small DC motor on and off using the Crickit motor channel 1.

Direct download: toggle_motor.py.

 1# crickit/toggle_motor.py
 2
 3# Demonstrate touch-activated control of a DC motor connected to the Crickit motor driver.
 4
 5# Related documentation:
 6# http://docs.circuitpython.org/projects/crickit/en/latest/
 7# http://docs.circuitpython.org/projects/seesaw/en/latest/
 8# https://learn.adafruit.com/adafruit-crickit-creative-robotic-interactive-construction-kit
 9
10# ----------------------------------------------------------------
11# Import standard Python modules.
12import time, math
13
14# Import the Crickit interface library.
15from adafruit_crickit import crickit
16
17# ----------------------------------------------------------------
18# Global state
19moving = False
20touched_last = False
21
22# ----------------------------------------------------------------
23# Enter the main event loop.
24
25while True:
26
27    # Check whether the touch state changed.
28    touched_now = crickit.touch_1.value
29
30    if touched_now and not touched_last:
31        # starting new touch, toggle motor state
32        moving = not moving
33        crickit.dc_motor_1.throttle = 1 if moving else 0
34
35    # Save the current touch state.
36    touched_last = touched_now

Hobby Servo Example

This sketch sweeps a hobby servo back and forth using the Crickit servo channel 1.

Direct download: servo_sweep.py.

 1# crickit/servo_sweep.py
 2
 3# Demonstrate oscillating movement of a hobby servo.  The Crickit supports up to
 4# four hobby servos; please note that the control line should be oriented toward
 5# the outside edge of the board, adjaced to the number marking.  On our micro
 6# servos, this wire is orange.
 7
 8# Related documentation:
 9# http://docs.circuitpython.org/projects/crickit/en/latest/
10# http://docs.circuitpython.org/projects/seesaw/en/latest/
11# https://learn.adafruit.com/adafruit-crickit-creative-robotic-interactive-construction-kit
12
13# ----------------------------------------------------------------
14# Import the standard Python time functions.
15import time
16
17# Import the Crickit interface library.
18from adafruit_crickit import crickit
19
20# ----------------------------------------------------------------
21# Begin the main processing loop.
22while True:
23    print("Starting cycle.")
24    for angle in range(0, 180, 5):
25        crickit.servo_1.angle = angle
26        time.sleep(0.02)
27
28    print("Reversing cycle.")
29    for angle in range(180, 0, -5):
30        crickit.servo_1.angle = angle
31        time.sleep(0.02)
32
33    print("Pausing.")
34    time.sleep(0.5)
35    

Tap Tempo Example

This sketch uses touch control to synchronize blinking NeoPixels. Please note that the CPB itself can also detect touch inputs, so the essence of the example could be adapted to work without the Crickit.

Direct download: tap_tempo.py.

  1# crickit/tap_tempo.py
  2
  3# Demonstrate synchronization of rhythmic output to touch activations on the
  4# Crickit.  Note: the CPB itself can also detect touch inputs, so the essence of
  5# the example could be adapted to work without the Crickit.
  6
  7# Related documentation:
  8# http://docs.circuitpython.org/projects/crickit/en/latest/
  9# http://docs.circuitpython.org/projects/seesaw/en/latest/
 10# https://learn.adafruit.com/adafruit-crickit-creative-robotic-interactive-construction-kit
 11
 12# ----------------------------------------------------------------
 13# Import standard Python modules.
 14import time, math
 15
 16# Import the Crickit interface library.
 17from adafruit_crickit import crickit
 18
 19# Import the board-specific input/output library for the CPB itself
 20from adafruit_circuitplayground import cp
 21
 22# Configure the NeoPixel LED array for bulk update.
 23cp.pixels.auto_write = False
 24
 25# Turn down the NeoPixel brightness, otherwise it is somewhat blinding.
 26cp.pixels.brightness = 0.5
 27
 28# ----------------------------------------------------------------
 29# Each instance of the following class creates an rhythmic color display on a
 30# single NeoPixel.  The instance should be polled periodically from the event
 31# loop to update the display.
 32
 33class NeoOscillator:
 34    def __init__(self, led_index):
 35        self.led = led_index
 36        self.phase = 0                    # oscillator phase angle between 0 and 2 pi
 37        self.phase_rate = 0.5 * math.pi   # oscillation rate in phase/second
 38        self.intensity = 0
 39        
 40    def set_tempo(self, bpm):
 41        """Set the oscillator tempo in beats per minute."""
 42        # (beats/minute) * (minutes/second) * (radians/beat) -> radians/second
 43        self.phase_rate = bpm * (1.0/60.0) * (2*math.pi)
 44
 45    def tap_event(self):
 46        """Process a synchronizing tap event by adjusting the phase rate."""
 47
 48        # The output has been set up so the perceived start of the beat is in the middle of the phase
 49        # cycle.  Calculate the error in phase and apply feedback to the phase rate.
 50        # If the oscillator is running ahead of the tap, slow down the rate, else speed it up.
 51        phase_error = math.pi - self.phase
 52        self.phase_rate += 0.25 * phase_error
 53        
 54    def poll(self, elapsed):
 55        """Polling function to be called as frequently as possible from the event loop
 56        with the nanoseconds elapsed since the last cycle."""
 57
 58        # advance the phase based on the elapsed time
 59        self.phase = math.fmod(self.phase + self.phase_rate * (1e-9*elapsed), 2*math.pi)
 60
 61        # calculate new RGB values
 62        self.intensity = min(max(int(-255*math.sin(self.phase)), 0), 255)
 63        cp.pixels[self.led] = (self.intensity, self.intensity, self.intensity)
 64
 65# ----------------------------------------------------------------
 66# Each instance of the following class processes touch inputs from a single
 67# capacitive touch input on the Crickit.  The instance should be polled
 68# periodically from the event loop to update the state.
 69
 70class CrickitTouch:
 71    def __init__(self, touch_input):
 72        self.input  = touch_input  # the object to consult for touch state
 73        self.state  = False        # most recently observed input state
 74
 75        # flags which are set for just one polling cycle to indicate events.
 76        self.tapped = False
 77
 78    def poll(self, elapsed):
 79        """Polling function to be called as frequently as possible from the event loop
 80        with the nanoseconds elapsed since the last cycle."""
 81
 82        # Reset any transient flags.
 83        self.tapped = False
 84
 85        # Read the touch input and detect events.
 86        new_input = self.input.value
 87        if new_input != self.state:
 88
 89            if new_input is True:
 90                self.tapped = True
 91                print("Tapped.")
 92
 93            self.state = new_input
 94
 95# ----------------------------------------------------------------
 96# Global state
 97moving = False
 98touched_last = False
 99last_timestamp = time.monotonic_ns()
100
101# Initialize the oscillators and slightly perturb the initial tempos.
102oscillators = [NeoOscillator(led) for led in range(10)]
103for n, osc in enumerate(oscillators):
104    osc.set_tempo(60 + 0.2 * n)
105
106# Initialize the touch inputs.
107touches = [CrickitTouch(crickit.touch_1), CrickitTouch(crickit.touch_4)]
108
109# ----------------------------------------------------------------
110# Enter the main event loop.
111
112while True:
113
114    # Calculate the time elapsed since last cycle (in nanoseconds).
115    now = time.monotonic_ns()
116    elapsed = now - last_timestamp
117    last_timestamp = now
118
119    # Update the oscillation outputs.
120    for osc in oscillators:
121        osc.poll(elapsed)
122
123    # Send new data to the physical LED chain.
124    cp.pixels.show()
125
126    # Update the touch detectors.
127    for touch in touches:
128        touch.poll(elapsed)
129
130    # If tapped, apply a phase correction to a set of oscillators.
131    if touches[0].tapped:
132        for osc in oscillators[0:5]:
133            osc.tap_event()
134            # print(f"phase: {osc.phase} rate: {osc.phase_rate} intensity: {osc.intensity}")
135            
136    if touches[1].tapped:
137        for osc in oscillators[5:]:
138            osc.tap_event()
139

Soft Sensor Example

This sketch reads an analog voltage from Signal 1 as a demonstration of connecting a soft sensor. A similar example without the Crickit can be seen on Soft Sensing Examples - Adafruit Circuit Playground Bluefruit.

Direct download: soft_analog.py.

 1# soft_analog.py
 2
 3# Demonstrate measurement of an analog soft sensor input using the Crickit.
 4# This is intended to attach to an external soft touch sensor hand-fabricated
 5# using conductive fabric and Velostat.  The electrical resistance of the sensor
 6# varies with pressure.
 7
 8# The wiring for this is as follows:
 9#  1. One half of sensor connected to GND (either half).
10#  2. Other half of sensor connected to Signal 1.
11#  3. External resistor connects between Signal 1 and 3.3V.
12
13# This example uses three pins from the Signal I/O section of the Cricket:
14# Signal 1, +3.3V, and GND.  An external resistor (typically 10K) should be
15# connected between the 3.3V pin and Signal 1, and the conductive sensor between
16# Signal 1 and GND.  The resistor will provide a small current to create a
17# voltage across the sensor which will vary with pressure.  E.g., it will form
18# one leg of a voltage divider with the sensor.
19
20# As mechanical pressure is applied, the sensor resistance drops along with the
21# voltage across the sensor.  Please note that the sensor voltage follows an
22# inverse logic: when not pressed, the input value will be midrange, and when
23# pressed, it will drop (possibly to zero).
24
25# ----------------------------------------------------------------
26# Import the standard Python time functions.
27import time
28
29# Import the Crickit interface library.
30from adafruit_crickit import crickit
31
32# Calculate the scaling coefficient to translate the raw analog value into volts.
33scaling = 3.3 / (2**10)
34
35# ----------------------------------------------------------------
36# Begin the main processing loop.
37while True:
38
39    # Read the integer sensor value and scale it to a value in Volts.
40    volts = crickit.seesaw.analog_read(crickit.SIGNAL1) * scaling
41    
42    # Every handmade sensor will have different properties, so the
43    # interpretation of the voltage value will usually need to be individually
44    # calibrated.  One way to accomplish this is by measuring the voltage
45    # response under different conditions, then applying additional scaling and
46    # offset to produce a normalized signal (possibly inverted).  For example,
47    # if the observed voltage ranges between 1.4 and 0.1 Volts, the input signal
48    # could be normalized to a [0,1] range as follows:
49    pressure = (1.4 - volts) / (1.4 - 0.1)
50
51    # Print the voltage reading and normalized value on the console.
52    print(f"({volts}, {pressure})")
53    
54    # Limit the rate of the main loop.
55    time.sleep(0.1)