Tinkering workshop

From Interaction Station Wiki
Jump to: navigation, search


Introduction on Adafruit Circuit Playground Express

Install CircuitPython

Install mu editor

Circuitpython circuit playground adafruit blinka computer.png 17850097.png

Python is the fastest-growing programming language. And CircuitPython is based on Python language but designed to run on microcontroller boards.

CircuitPython is designed with education in mind.

It's easy to start learning how to program and you get immediate feedback from the board.


Before we start we all have to do this to set up:

1. Install or update CircuitPython!

https://learn.adafruit.com/adafruit-circuit-playground-express/circuitpython-quickstart

*1. Click the link below and download the latest UF2 file:
https://circuitpython.org/board/circuitplayground_express/
*2. Plug your Circuit Playground Express into your computer via a (data)USB cable.
*3. Double-click the small Reset button in the middle of the CPX(short for circuit playground express).
 you will see all of the LEDs turn green. If they turn all red, check the USB cable, try another USB port, etc.
 (If double-clicking doesn't do it, try a single-click!)
*4. You will see a new disk drive appear called CPLAYBOOT
  Drag the adafruit-circuitpython-etc...uf2 file onto it.
*5. The CPLAYBOOT drive will disappear and a new disk drive will appear called CIRCUITPY

That's it! You're done :)

2. Installing Mu Editor

Download Mu from(if you are using computers from school, the Mu Editor is already installed)

https://codewith.mu

Circuitpython mu-front-page.png


The first time you start Mu, you will be prompted to select your 'mode' -

you can always change your mind later. For now please select CircuitPython!


Circuitpython Screen Shot 2017-12-24 at 2.55.02 PM.png


Mu attempts to auto-detect your board, so please plug in your CircuitPython device and make sure it shows up as a CIRCUITPY drive before starting Mu

Circuitpython Screen Shot 2017-12-24 at 3.16.23 PM.png


SAVE AS:

if you want to save the code.py file in different names as well as in different locations:

double click on the file name in Mu editor.

Save-as-Capture.PNG

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

Mu CircuitPython Mode Cheat Sheet 1.jpg

3. Hello World (Blink in Circuitpython)

  1. # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
  2. # SPDX-License-Identifier: MIT
  3.  
  4. """This is the "Hello, world!" of CircuitPython: Blinky! This example blinks the little red LED on
  5. and off!"""
  6.  
  7. import time
  8. from adafruit_circuitplayground import cp
  9.  
  10. while True:
  11.     cp.red_led = True
  12.     time.sleep(0.5)
  13.     cp.red_led = False
  14.     time.sleep(0.5)

4. Interacting to the Serial Console

The REPL

The other feature of the serial connection is the Read-Evaluate-Print-Loop, or REPL.

The REPL allows you to enter individual lines of code and have them run immediately.

It's really handy if you're running into trouble with a particular program and can't figure out why.

It's interactive so it's great for testing new ideas.

To use the REPL, you first need to be connected to the serial console.

Once that connection has been established, you'll want to press Ctrl + C.

If there is code running, it will stop and you'll see Press any key to enter the REPL. Use CTRL-D to reload.

Follow those instructions, and press any key on your keyboard.

https://learn.adafruit.com/adafruit-circuit-playground-express/the-repl

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


Interaction with touch sensor and neopixel

During this workshop, we will learn how to design and create an interactive game that enhances communication,

expression, and collaboration in the current 1.5 social distance reality.

we will focus on sending “touch signal” to each other without physical contact,

but in the forms of lights, color and sound.


1.Neopixel smiley face

A Smiley Face😊

  1. from adafruit_circuitplayground import cp
  2.  
  3. # The NeoPixels are super-bright. Change the global brightness.
  4. cp.pixels.brightness = 0.3
  5.  
  6. while 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

  1. from adafruit_circuitplayground import cp
  2.  
  3. # The NeoPixels are super-bright. Change the global brightness.
  4. cp.pixels.brightness = 0.3
  5.  
  6. import time  
  7.  
  8. while 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

  1. import time
  2. from adafruit_circuitplayground import cp
  3. #neoPixel pins for the smiley face
  4. pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
  5. # The NeoPixels are super-bright. Change the global brightness.
  6. cp.pixels.brightness = 0.1
  7. light_colour=(105,0,105)
  8. OFF=(0,0,0)
  9.  
  10. while 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.

2.Touch sense as trigger

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


if we touch pin A4, The smiley face will appear if not the smiley face will disappear.


  1. import time
  2. from adafruit_circuitplayground import cp
  3. #neoPixel pins for the smiley face
  4. pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
  5. # The NeoPixels are super-bright. Change the global brightness.
  6. cp.pixels.brightness = 0.1
  7. light_colour=(105,0,105)
  8. OFF=(0,0,0)
  9.  
  10. while 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)

3.Touch piano keyboard

  1. import time
  2. from adafruit_circuitplayground import cp
  3. #neoPixel pins for the smiley face
  4. pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
  5.  
  6. playtime=0.2
  7. # NOTE C4-B4
  8. c4=262 
  9. d4=294
  10. e4=330
  11. f4=349
  12. g4=392
  13. a4=440
  14. b4=494
  15.  
  16. while True:
  17.     if cp.touch_A1:
  18.         cp.play_tone(c4, playtime) 
  19.         print("A1-touched!")
  20.     if cp.touch_A2:
  21.         cp.play_tone(d4, playtime)
  22.         print("A2-touched!")
  23.     if cp.touch_A3:
  24.         cp.play_tone(e4, playtime)
  25.         print("A3-touched!")
  26.     if cp.touch_A4:
  27.         cp.play_tone(f4, playtime)
  28.         print("A4-touched!")
  29.     if cp.touch_A5:
  30.         cp.play_tone(g4, playtime)
  31.         print("A5-touched!")
  32.     if cp.touch_A6:
  33.         cp.play_tone(a4, playtime)
  34.         print("A6-touched!")
  35.     if cp.touch_A7:
  36.         cp.play_tone(b4, playtime)
  37.         print("A7-touched!")

3.Play audio file

here some audio files you can download and copy to the circuit playground express.

Dip: http://interactionstation.wdka.hro.nl/mediawiki/images/6/61/Dip.wav

Rise: http://interactionstation.wdka.hro.nl/mediawiki/images/2/2b/Rise.wav

Explosion: http://interactionstation.wdka.hro.nl/mediawiki/images/f/f8/Explosion.wav

Kiss.wav: http://interactionstation.wdka.hro.nl/mediawiki/images/d/df/Kiss.wav

Happy-ringtone: http://interactionstation.wdka.hro.nl/mediawiki/images/9/9b/Happy-ringtone.wav

Wrong-buzzer: http://interactionstation.wdka.hro.nl/mediawiki/images/6/61/Wrong-buzzer.wav

Yelling-yeah: http://interactionstation.wdka.hro.nl/mediawiki/images/9/95/Yelling-yeah.wav

Jazz-piano: http://interactionstation.wdka.hro.nl/mediawiki/images/a/a9/Jazz-piano.wav


  1. import time
  2. from adafruit_circuitplayground import cp
  3. #neoPixel pins for the smiley face
  4. pixels_pin=[1,  3,  5, 6, 7, 8, 9,10]
  5.  
  6. # The NeoPixels are super-bright. Change the global brightness.
  7. cp.pixels.brightness = 0.1
  8. colour01=(105,0,105)
  9. colour02=(0,100,105)
  10. OFF=(0,0,0)
  11.  
  12. while 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("yelling-yeah.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("jazz-piano.wav")
  30.     else:
  31.         for i in range (7):
  32.             cp.pixels[pixels_pin[i]]=OFF
  33.             time.sleep(0.03)

4.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
  2. import time
  3. import board
  4. import touchio
  5. import digitalio
  6.  
  7. try:
  8.     from audiocore import WaveFile
  9. except ImportError:
  10.     from audioio import WaveFile
  11.  
  12. try:
  13.     from audioio import AudioOut
  14. except ImportError:
  15.     try:
  16.         from audiopwmio import PWMAudioOut as AudioOut
  17.     except ImportError:
  18.         pass  # not always supported by every board!
  19.  
  20. bpm = 120  # Beats per minute, change this to suit your tempo
  21.  
  22. # Enable the speaker
  23. speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
  24. speaker_enable.direction = digitalio.Direction.OUTPUT
  25. speaker_enable.value = True
  26.  
  27. # Make the input capacitive touchpads
  28. capPins = (board.A1, board.A2, board.A3, board.A4, board.A5,
  29.            board.A6, board.TX)
  30.  
  31. touchPad = []
  32. for i in range(7):
  33.     touchPad.append(touchio.TouchIn(capPins[i]))
  34.  
  35. # The seven files assigned to the touchpads
  36. audiofiles = ["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.  
  40. audio = AudioOut(board.SPEAKER)
  41.  
  42.  
  43. def 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.  
  51. while True:
  52.     for i in range(7):
  53.         if touchPad[i].value:
  54.             play_file(audiofiles[i])

connect to a proper speaker:

we can use A0 and GND as audio output and connect it to a proper speaker.

you can use M3 bolts and nuts to fix the electrical wire on the circuit playground express.

Circuit playground hp.png IMG 3518.jpeg

infrared tagging game:

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