Tinkering workshop

From Interaction Station Wiki
Jump to navigation Jump to search

Yoana:

introduction on Adafruit Circuit Playground Express

install CircuitPython

install mu editor

Interacting to the Serial Console

The REPL

short cuts:

Indentation and commenting options

Python programs are Space holder Character Sensitive.

To indent the three lines, I selected them all and then pressed the Tab key.

To unindent, select some lines and press Shift-Tab. For commenting: select lines and press command(control)-k

http://interactionstation.wdka.hro.nl/wiki/Cpx-basic


Nan== install library..

examples:

library CircuitPython Made Easy

1. Smiley face with NeoPixels


2. Capacitive Touch & NeoPixels

3. Play audio file

4. Drum machine

5. final infrared tagging games(maybe)



timing / schedule

start 13:00 end 17:00


13:00 - 14:00 Yoana introduction part

14:00 - 14:15 - break

14:15 - 16:00 Nan's part

16:00 - 16:15 break

16:15 - 17:00 Play


CircuitPython Made Easy

Libraries:

Libraries are codes other people have written for you. The libraries we will be using are included as part of the CircuitPython code, but you still must import them into your program. Other libraries, for many uses, must be downloaded and placed in a folder named lib on the CIRCUITPY drive.


CircuitPython Libraries already included in CPX, But if you are using CPB, (CPX = Circuit Playground Express, CPB = Circuit Playground Bluefruit)

you need to install CircuitPython Libraries by download the file and put them in the folder named lib on the CIRCUITPY drive.

we will useCircuitPython Made Easy libraries, a simple way to include the Circuit Playground functionality in our code.

more reference and examples:

https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express

code examples

Neopixel smiley face

A Smiley Face😊

 1from adafruit_circuitplayground import cp
 2
 3# The NeoPixels are super-bright. Change the global brightness.
 4cp.pixels.brightness = 0.3
 5
 6while True:
 7    # The smiley's eyes
 8    cp.pixels[1] = (255, 0, 0)
 9    cp.pixels[3] = (255, 0, 0)
10
11    # The smiley's mouth
12    cp.pixels[5] = (255, 0, 255)
13    cp.pixels[6] = (255, 0, 255)
14    cp.pixels[7] = (255, 0, 255)
15    cp.pixels[8] = (255, 0, 255)
16    cp.pixels[9] = (255, 0, 255)

Let's blink a smiley face by using time.sleep

 1from adafruit_circuitplayground import cp
 2 
 3# The NeoPixels are super-bright. Change the global brightness.
 4cp.pixels.brightness = 0.3
 5
 6import time  
 7
 8while True:
 9    time.sleep(1)
10    # The smiley's eyes
11    cp.pixels[1] = (255, 0, 0)
12    cp.pixels[3] = (255, 0, 0)
13 
14    # The smiley's mouth
15    cp.pixels[5] = (255, 0, 255)
16    cp.pixels[6] = (255, 0, 255)
17    cp.pixels[7] = (255, 0, 255)
18    cp.pixels[8] = (255, 0, 255)
19    cp.pixels[9] = (255, 0, 255)
20    time.sleep(1)
21
22    # The smiley's eyes
23    cp.pixels[1] = (0, 0, 0)
24    cp.pixels[3] = (0, 0, 0)
25 
26    # The smiley's mouth
27    cp.pixels[5] = (0, 0, 0)
28    cp.pixels[6] = (0, 0, 0)
29    cp.pixels[7] = (0, 0, 0)
30    cp.pixels[8] = (0, 0, 0)
31    cp.pixels[9] = (0, 0, 0)


hmm... now the code seems to be too long

let's Shorten the code by implementing variables, "for" loops

 1import time
 2from adafruit_circuitplayground import cp
 3#neoPixel pins for the smiley face
 4pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
 5# The NeoPixels are super-bright. Change the global brightness.
 6cp.pixels.brightness = 0.1
 7light_colour=(105,0,105)
 8OFF=(0,0,0)
 9
10while True:
11    for i in range (7):
12        cp.pixels[pixels_pin[i]]=light_colour       
13    time.sleep(1)
14    for i in range (7):
15        cp.pixels[pixels_pin[i]]=OFF     
16    time.sleep(1)


much better!!! now if you add a time.sleep(0.5) in the for loop you will see a fading animation of the smiley face.

Touch sense

there are in total 7 touch pins on CPX. let's try to use the touch sensor to trigger the smiley face.


 1import time
 2from adafruit_circuitplayground import cp
 3#neoPixel pins for the smiley face
 4pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
 5# The NeoPixels are super-bright. Change the global brightness.
 6cp.pixels.brightness = 0.1
 7light_colour=(105,0,105)
 8OFF=(0,0,0)
 9
10while True:
11    if cp.touch_A4:
12        for i in range (7):
13            cp.pixels[pixels_pin[i]]=light_colour   
14            time.sleep(.1)
15            print("A4-touched!")
16    else:
17        for i in range (7):
18            cp.pixels[pixels_pin[i]]=OFF     
19            time.sleep(.1)

play audio file

 1import time
 2from adafruit_circuitplayground import cp
 3#neoPixel pins for the smiley face
 4pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
 5
 6# The NeoPixels are super-bright. Change the global brightness.
 7cp.pixels.brightness = 0.1
 8colour01=(105,0,105)
 9colour02=(0,100,105)
10OFF=(0,0,0)
11
12while True:
13    if cp.touch_A4:
14        for i in range (7):
15            cp.pixels[pixels_pin[i]]=colour01   
16            time.sleep(0.03)
17            print("A4-touched!")
18        cp.play_file("rise.wav")
19    else:
20        for i in range (7):
21            cp.pixels[pixels_pin[i]]=OFF     
22            time.sleep(0.03)
23    if cp.touch_A3:
24        for i in range (7):
25            cp.pixels[pixels_pin[i]]=colour02   
26            time.sleep(0.03)
27            print("A3-touched!")
28 
29        cp.play_file("dip.wav")
30    else:
31        for i in range (7):
32            cp.pixels[pixels_pin[i]]=OFF
33            time.sleep(0.03)

Drum Machine

https://learn.adafruit.com/adafruit-circuit-playground-express/playground-drum-machine

copy the drum samples there:

[samples]

 1# Circuit Playground 808 Drum machine
 2import time
 3import board
 4import touchio
 5import digitalio
 6 
 7try:
 8    from audiocore import WaveFile
 9except ImportError:
10    from audioio import WaveFile
11 
12try:
13    from audioio import AudioOut
14except ImportError:
15    try:
16        from audiopwmio import PWMAudioOut as AudioOut
17    except ImportError:
18        pass  # not always supported by every board!
19 
20bpm = 120  # Beats per minute, change this to suit your tempo
21 
22# Enable the speaker
23speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
24speaker_enable.direction = digitalio.Direction.OUTPUT
25speaker_enable.value = True
26 
27# Make the input capacitive touchpads
28capPins = (board.A1, board.A2, board.A3, board.A4, board.A5,
29           board.A6, board.TX)
30 
31touchPad = []
32for i in range(7):
33    touchPad.append(touchio.TouchIn(capPins[i]))
34 
35# The seven files assigned to the touchpads
36audiofiles = ["bd_tek.wav", "elec_hi_snare.wav", "elec_cymbal.wav",
37              "elec_blip2.wav", "bd_zome.wav", "bass_hit_c.wav",
38              "drum_cowbell.wav"]
39 
40audio = AudioOut(board.SPEAKER)
41 
42 
43def play_file(filename):
44    print("playing file " + filename)
45    file = open(filename, "rb")
46    wave = WaveFile(file)
47    audio.play(wave)
48    time.sleep(bpm / 960)  # Sixteenth note delay
49 
50 
51while True:
52    for i in range(7):
53        if touchPad[i].value:
54            play_file(audiofiles[i])


Light meter

 1#light meter
 2
 3import time
 4from adafruit_circuitplayground import cp
 5cp.pixels.auto_write = False
 6cp.pixels.brightness = 0.3
 7 
 8 
 9def scale_range(value):
10#"""Scale a value from 0-320 (light range) to 0-9 (NeoPixel range).
11#    Allows remapping light value to pixel position."""
12    return round(value / 280 * 9)
13    
14while True:
15    peak = scale_range(cp.light)
16    print(cp.light)
17    print(int(peak))
18 
19    for i in range(10):
20        if i <= peak:
21            cp.pixels[i] = (0, 255, 255)
22        else:
23            cp.pixels[i] = (0, 0, 0)
24    cp.pixels.show()
25    time.sleep(0.2)



infrared tagging game:

  1from adafruit_circuitplayground.express import cpx
  2import board
  3from adafruit_circuitplayground import cp
  4import time
  5import pulseio
  6import array
  7import touchio
  8import digitalio
  9
 10# change into your own color by changing the rgb value
 11myID_colour=(0,255,255)
 12# NeoPixel brightness
 13
 14# Create IR input, maximum of 59 bits.
 15pulseIn = pulseio.PulseIn(board.IR_RX, maxlen=59, idle_state=True)
 16# Clears any artifacts
 17pulseIn.clear()
 18pulseIn.resume()
 19
 20# Creates IR output pulse
 21pwm = pulseio.PWMOut(board.IR_TX, frequency=38000, duty_cycle=2 ** 15)
 22pulse = pulseio.PulseOut(pwm)
 23
 24# Array for button A pulse, this is the pulse output when the button is pressed
 25# Inputs are compared against this same array
 26# array.array('H', [x]) must be used for IR pulse arrays when using pulseio
 27# indented to multiple lines so its easier to see
 28pulse_A = array.array('H', [1000, 3800, 65000, 950, 300, 200, 300, 1000, 350, 175,
 29    275, 215, 275, 250, 275, 215, 275, 225, 275, 215, 275, 1000, 300, 225, 275,
 30    950, 300, 950, 300, 1000, 300, 950, 300, 250, 275, 700, 300, 950, 300, 450,
 31    300, 475, 300, 215, 275, 725, 300, 950, 300, 200, 300, 715, 325, 900, 315,
 32    425, 315, 1000, 65000])
 33pulse_B = array.array('H', [1000, 3800, 65000, 960, 300, 200, 300, 950, 350, 190,
 34    215, 245, 300, 225, 275, 225, 275, 215, 275, 200, 300, 700, 300, 200, 300,
 35    700, 300, 1000, 315, 675, 300, 1000, 300, 200, 300, 700, 300, 950, 300,
 36    950, 300, 700, 300, 700, 300, 450, 300, 475, 275, 715, 300, 225, 275, 450,
 37    300, 450, 300, 1000, 65000])
 38
 39# Fuzzy pulse comparison function. Fuzzyness is % error
 40def fuzzy_pulse_compare(pulse1, pulse2, fuzzyness=0.5):
 41    if len(pulse1) != len(pulse2):
 42        return False
 43    for i in range(len(pulse1)):
 44        threshold = int(pulse1[i] * fuzzyness)
 45        if abs(pulse1[i] - pulse2[i]) > threshold:
 46            return False
 47    return True
 48
 49# Initializes NeoPixel ring
 50cp.pixels.brightness= 0.2
 51# my id color
 52cp.pixels.fill(myID_colour)
 53#cp.pixels.show()
 54
 55# serial print once when activated
 56print('IR Activated!')
 57
 58while True:
 59# when button is pressed, send IR pulse
 60# detection is paused then cleared and resumed after a short pause
 61# this prevents reflected detection of own IR
 62    while cp.touch_A3:
 63        pulseIn.pause()  # pauses IR detection
 64        pulse.send(pulse_A)  # sends IR pulse
 65        time.sleep(.2)  # wait so pulses dont run together
 66        pulseIn.clear()  # clear any detected pulses to remove partial artifacts
 67        pulseIn.resume()  # resumes IR detection
 68    while cp.touch_A4:
 69        pulseIn.pause()
 70        pulse.send(pulse_B)
 71        time.sleep(.2)
 72        pulseIn.clear()
 73        pulseIn.resume()
 74# Wait for a pulse to be detected of desired length
 75    while len(pulseIn) >= 59:  # our array is 59 bytes so anything shorter ignore
 76        pulseIn.pause()
 77# converts pulseIn raw data into useable array
 78        detected = array.array('H', [pulseIn[x] for x in range(len(pulseIn))])
 79#        print(len(pulseIn))
 80#        print(detected)
 81
 82    # Got a pulse, now compare against stored pulse_A and pulse_B
 83        if fuzzy_pulse_compare(pulse_A, detected):
 84            print('Received correct Button A control press!')
 85            t_end = time.monotonic() + 0.8  # saves time 2 seconds in the future
 86            while time.monotonic() < t_end: # plays sparkels until time is up
 87                for x in range(10):
 88                    if x!= 0 and x!=2 and x!=4:
 89                        cp.pixels[x]=(250, 55, 100)
 90
 91                    else:
 92                        cp.pixels[x]=(0, 0, 0)
 93                cp.play_file("kiss.wav")
 94                time.sleep(1.5)
 95                cp.pixels.fill(myID_colour)
 96
 97        if fuzzy_pulse_compare(pulse_B, detected):
 98            print('Received correct Button B control press!')
 99            t_end = time.monotonic() + 0.8
100            while time.monotonic() < t_end:
101                #rainbow_cycle(.001)
102                cp.pixels.fill((255, 0, 0))
103                cp.play_file("explosion.wav")
104                time.sleep(0.5)
105                cp.pixels.fill(myID_colour)
106
107
108
109        time.sleep(.1)
110        pulseIn.clear()
111        pulseIn.resume()