Let's start with A0 which is in the bottom right corner, and work our way counter-clockwise
A0 (a.k.a D12) - This is a special pin that can do true analog output so it's great for playing audio clips. In can be digital I/O, or analog I/O, but if you do that it will interfere with the built-in speaker. This is the one pin that cannot be used for capacitive touch.
A1 / D6 - This pin can be digital I/O, or analog Input. This pin has PWM output and can be capacitive touch sensor
A2 / D9 - This pin can be digital I/O, or analog Input. This pin has PWM output and can be capacitive touch sensor
A3 / D10 - This pin can be digital I/O, or analog Input. This pin has PWM output and can be capacitive touch sensor
A4 / D3 - This pin can be digital I/O, or analog Input. This pin is also the I2C SCL pin, and can be capacitive touch sensor
A5 / D2 - This pin can be digital I/O, or analog Input. This pin is also the I2C SDA pin, and can be capacitive touch sensor
A6 / D0 - This pin can be digital I/O, or analog Input. This pin has PWM output, Serial Receive, and can be capacitive touch sensor
A7 / D1 - This pin can be digital I/O, or analog Input. This pin has PWM output, Serial Transmit, and can be capacitive touch sensor
// blink the onboard LED
/**
* Special function that loops forever.
*/
forever(function () {
// turn the onboard LED on
pins.LED.digitalWrite(true)
// wait 500 milliseconds (half a second)
pause(500)
// turn the onboard LED off
pins.LED.digitalWrite(false)
// wait 500 milliseconds (half a second)
pause(500)
})
// blink an external LED
// attach GND to negative leg, A1 to positive leg
let LED_PIN = pins.A1 // store the chosen pin in a variable
/**
* Special function that loops forever.
*/
forever(function () {
// turn the pin on
LED_PIN.digitalWrite(true)
// wait 500 milliseconds (half a second)
pause(500)
// turn the pin off
LED_PIN.digitalWrite(false)
// wait 500 milliseconds (half a second)
pause(500)
})
// blink an onboard neopixel
let neopixel = 0 // track which neopixel to blink
// the forever function runs over and over again
forever(function () {
// turn the Neopixel red by specifying:
// full red (highest value of 255), no green and no blue
light.setPixelColor(neopixel, light.rgb(255, 0, 0))
pause(1000) // wait for a second
// turn the Neopixel off by specifying:
// no red, no green and no blue
light.setPixelColor(neopixel, light.rgb(0, 0, 0))
pause(1000) // wait for a second
})
// use the light sensor to control neopixels
// when there is a lot of light, all are pink
// when it is dark, they sparkle
let LIGHT_THRESHOLD = 20; // you may need to play with this
forever(function () {
// if the darkness is above a threshold value
if (input.lightLevel() > LIGHT_THRESHOLD) {
// turn all neopixels off
light.clear()
// then show a sparkle animation for .5 seconds
light.showAnimation(light.sparkleAnimation, 500)
}
// otherwise
else {
// light all neopixels pink
light.setAll(light.rgb(255, 20, 147))
}
})
// use the sound sensor to control neopixels
// when there is a lot of sound, sparkle
// otherwise, all are pink
let SOUND_THRESHOLD = 100; // set a threshold value
forever(function () {
// if the darkness is above a threshold value
if (input.soundLevel() > SOUND_THRESHOLD) {
// turn all neopixels off
light.clear()
// then show a sparkle animation for .5 seconds
light.showAnimation(light.sparkleAnimation, 500)
}
// otherwise
else {
// light all neopixels pink
light.setAll(light.rgb(255, 20, 147))
}
})
// print the light sensor value to the console
forever(function () {
console.logValue("light sensor", input.lightLevel())
pause(100)
})
let temp = 0
forever(function () {
temp = input.temperature(TemperatureUnit.Fahrenheit)
if (temp > 90) {
light.setAll(0xff0000)
} else if (temp < 89) {
light.setAll(0x00ffff)
} else {
light.setAll(0xffff00)
}
pause(100)
})
input.buttonA.onEvent(ButtonEvent.Click, function () {
light.clear()
})
input.buttonB.onEvent(ButtonEvent.Click, function () {
light.setAll(input.ambientColor())
})
forever(function () {
})
// set up the velostat and wiring:
// https://docs.google.com/document/d/1Ve4l8B4V112InWYsD8NXnqRUdxUZQAYjeTp3Ix2Yo0U/edit
// use the serial monitor to find these values
// if MakeCode is refusing to cooperate...
// use Arduino...
let THRESH1 = 800
let THRESH2 = 900
forever(function () {
// most pressure
if (pins.A3.analogRead() >= THRESH2) {
light.setAll(0xff0000)
}
// medium pressure
else if (pins.A3.analogRead() >= THRESH1) {
light.setAll(0xffff00)
}
// not enough pressure
else {
light.clear()
}
})
// For the CPX, use the green ultrasonic RCWL-1601 (3.3V)
// Trig to A2, Echo to A1
let distance = 0
forever(function () {
pins.A2.digitalWrite(false)
control.waitMicros(2)
pins.A2.digitalWrite(true)
control.waitMicros(10)
pins.A2.digitalWrite(false)
distance = pins.A1.pulseIn(PulseValue.High) / 58
// have the neopixel ring show "bar graph" up to 50
light.graph(distance, 50)
// if in a certain range
if (distance >= 5 && distance <= 10)
// play a sound!
music.baDing.play()
})
// if you have errors, use EXTENSIONS -> servo
servos.A1.setAngle(0) // start at 0
// wait .5 second to get back to 0 in case it wasn't close
pause(500)
// on button A click, sweep forward
input.buttonA.onEvent(ButtonEvent.Click, function () {
servos.A1.setAngle(0)
// wait .5 second to get back to 0 in case it wasn't close
pause(500)
// iterate from 0 degrees to 180 degrees
// in steps of 1 degree
for (let pos = 0; pos <= 180; pos++) {
// tell servo to go to position in variable 'pos'
servos.A1.setAngle(pos)
// waits 5 ms for the servo to reach the position
pause(5)
}
})
// on button B click, sweep back
input.buttonB.onEvent(ButtonEvent.Click, function () {
servos.A1.setAngle(180)
// wait .5 second to get to 180 in case it wasn't close
pause(500)
// iterate from 0 degrees to 180 degrees
// in steps of 1 degree
for (let pos = 180; pos >= 0; pos--) {
// tell servo to go to position in variable 'pos'
servos.A1.setAngle(pos)
// waits 15 ms for the servo to reach the position
pause(5)
}
})
// This program uses the onboard neopixels to respond to tilting
// X axis is left/right (labeled on baord) lights pink/purple
// Y axis is forward back (also labeled on board) lights orange/yellow
// Z axis is which side is up lights blue/teal
let xAbs = 0
let yAbs = 0
let zAbs = 0
// X is left/right tilting
function respondToX() {
if (input.acceleration(Dimension.X) < 0) {
light.showRing(
`purple purple purple purple purple black black black black black`
)
} else {
light.showRing(
`black black black black black pink pink pink pink pink`
)
}
}
// Y is forward/back tilting
function respondToY() {
if (input.acceleration(Dimension.Y) > 0) {
light.showRing(
`orange orange orange black black black black orange orange orange`
)
} else {
light.showRing(
`black black yellow yellow yellow yellow yellow yellow black black`
)
}
}
// Z is face up/down
function respondToZ() {
if (input.acceleration(Dimension.Z) > 0) {
light.setAll(0x00ffff)
} else {
light.setAll(0x0000ff)
}
}
forever(function () {
// we will use a threshold to see if which is most significant
xAbs = Math.abs(input.acceleration(Dimension.X))
yAbs = Math.abs(input.acceleration(Dimension.Y))
zAbs = Math.abs(input.acceleration(Dimension.Z))
// console.log(input.rotation(Rotation.Roll))
console.log(input.acceleration(Dimension.Z))
// determine which is biggest
if (xAbs > yAbs && xAbs > zAbs) {
respondToX()
} else if (yAbs > xAbs && yAbs > zAbs) {
respondToY()
} else if (zAbs > xAbs && zAbs > yAbs) {
respondToZ()
}
// should never happen...
else
light.clear()
})
/**
* This program supports chasing lights effect.
* First, it uses the onboard "strip" (the ring of built-in neopixels),
* then uses an external strip attached to pin A1.
*/
forever(function () {
// change this part
// right now, it uses the onboard strip which has 10 neopixels
// and chases a blue (0xRRGGBB) color every 200 milliseconds
// for 2 rounds
chaseNeopixels(light.onboardStrip(), 10, 0x0000ff, 200, 2)
// and this part, still uses the onboard strip which has 10 neopixels
// but chases a purple (0xRRGGBB) color every 100 milliseconds
// for 3 rounds
chaseNeopixels(light.onboardStrip(), 10, 0xff00ff, 100, 3)
// I think this part should set up an external strip with 15 neopixels,
// but I can't test since I don't have one!
let externalNeopixelStrip = light.createNeoPixelStrip(pins.A1, 15)
// so this should use the external strip with 15 neopixels
// to chase a green (0xRRGGBB) color every 50 milliseconds
// for 4 rounds
chaseNeopixels(externalNeopixelStrip, 15, 0x00ff00, 50, 4)
})
/**
* Have the neopixels "chase" along the strip.
* speed is the number of milliseconds each pixel stays on
* color is the RGB value to use for the light in format 0xRRGGBB
* numPixels is the number of neopixels in the strip
* numRounds is the number of rounds to execute
*/
function chaseNeopixels(strip: light.NeoPixelStrip, numPixels: number,
color: number, speed: number, numRounds: number) {
for (let chaseIndex = 0; chaseIndex < numRounds; chaseIndex++)
for (let pixIndex = 0; pixIndex < numPixels; pixIndex++) {
// turn on the pixel
strip.setPixelColor(pixIndex, color)
loops.pause(speed) // keep it on
// turn off the pixel
strip.setPixelColor(pixIndex, 0x000000)
}
}
// MessageBlox program controls a lantern
// on a loud sound (like a knock):
// shows a rainbow pattern and stays on light blue
// on pin A2 touch, plays a fun sound and cycles the lights
// on pin A6 touch, turns off the light
let colorIndex = 0 // starting color
// rainbow colors to cycle cyan to purple to red to green
let rainbowColors = [0x00ffff, 0x007fff, 0x0000ff, 0x7f00ff,
0xff00ff, 0xff007f, 0xff0000, 0xff7f00,
0xffff00, 0x7fff00, 0x00ff00, 0x00ff7f]
// starting code
light.setBrightness(255) // set up to be bright
pause( 500 )
light.clear()
/** On a loud sound, rainbow animation and stop at cyan */
input.onLoudSound(function () {
light.showAnimation(light.rainbowAnimation, 2000)
light.setAll(0x00ffff)
})
/** On touching A2, play a fun sound and show the next color */
input.touchA2.onEvent(ButtonEvent.Click, function () {
music.baDing.play()
light.setAll(rainbowColors[(++colorIndex)%rainbowColors.length])
})
/** On touching A6, turn off the lantern */
input.touchA6.onEvent(ButtonEvent.Click, function () {
light.clear()
})
// melody is a list of [noteVal,beatDuration] pairs
// for example: [330,2] represents playing value 330 for 2 beats
// if noteVal is -1, then a rest will occur for the beatDuration
let melody: number[][] =
[
[330, 1], [330, 1], [330, 2],
[-1, .5], // -1 indicates rest
[330, 1], [330, 1], [330, 2],
[-1, .5],
[330, 1], [392, 1], [262, 1], [294, 1], [330, 2],
[-1, .5],
[349, 1], [349, 1], [349, 1], [349, 1], [349, 1], [330, 1], [330, 1],
[330, .5], [330, .5],
[392, 1], [392, 1], [349, 1], [294, 1],
[262, 2]
]
input.pinA1.onEvent(ButtonEvent.Click, function () {
light.showAnimation(light.sparkleAnimation, 500)
light.showRing(
`red green red green red red green red green red`
)
for (let note of melody)
playNote(note[0], note[1])
})
/** Helper functions for playing notes **/
function playNote(noteVal: number, beat: number) {
let beatMS = beatToMS(beat);
// if it's a rest
if (noteVal == -1)
music.rest(beatMS)
else
music.playTone(noteVal, beatMS)
}
/** Takes a beat and converts it to milliseconds. */
function beatToMS(beat: number) {
switch (beat) {
case .25: return music.beat(BeatFraction.Quarter); // quarter note
case .5: return music.beat(BeatFraction.Half); // half note
case 1: return music.beat(BeatFraction.Whole); // whole note
case 2: return music.beat(BeatFraction.Double); // double note
default: return music.beat(BeatFraction.Whole);
}
}
Pitches.h
/*************************************************
* Public Constants
*************************************************/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
Reference: https://makecode.adafruit.com/javascript
Notes: https://github.com/microsoft/pxt-adafruit/blob/master/docs/learnsystem/hot-potato.md
How I found the pins and such: https://github.com/microsoft/pxt-adafruit/blob/master/libs/circuit-playground/device.d.ts, code below
declare namespace pins {
// pin-pads
//% fixedInstance shim=pxt::getPin(PIN_A0)
const A0: AnalogOutPin;
//% fixedInstance shim=pxt::getPin(PIN_A1)
const A1: PwmPin;
//% fixedInstance shim=pxt::getPin(PIN_A2)
const A2: PwmPin;
//% fixedInstance shim=pxt::getPin(PIN_A3)
const A3: AnalogInPin;
//% fixedInstance shim=pxt::getPin(PIN_A4)
const A4: AnalogInPin;
//% fixedInstance shim=pxt::getPin(PIN_A5)
const A5: AnalogInPin;
//% fixedInstance shim=pxt::getPin(PIN_A6)
const A6: AnalogInPin; // could be PwmPin when mbed fixed
//% fixedInstance shim=pxt::getPin(PIN_A7)
const A7: AnalogInPin; // could be PwmPin when mbed fixed
// Define aliases, as Digital Pins
//% fixedInstance shim=pxt::getPin(PIN_A4)
const SCL: DigitalInOutPin;
//% fixedInstance shim=pxt::getPin(PIN_A5)
const SDA: DigitalInOutPin;
//% fixedInstance shim=pxt::getPin(PIN_A6)
const RX: DigitalInOutPin;
//% fixedInstance shim=pxt::getPin(PIN_A7)
const TX: DigitalInOutPin;
//% fixedInstance shim=pxt::getPin(PIN_D13)
const LED: DigitalInOutPin;
//% fixedInstance shim=pxt::getPin(PIN_IR_OUT)
const IROut: DigitalInOutPin;
//% fixedInstance shim=pxt::getPin(PIN_IR_IN)
const IRIn: DigitalInOutPin;
}
declare namespace input {
/**
* Left button.
*/
//% indexedInstanceNS=input indexedInstanceShim=pxt::getButton
//% block="button A" weight=95 fixedInstance
//% shim=pxt::getButton(0)
const buttonA: Button;
/**
* Right button.
*/
//% block="button B" weight=94 fixedInstance
//% shim=pxt::getButton(1)
const buttonB: Button;
/**
* Left and Right button.
*/
//% block="buttons A+B" weight=93 fixedInstance
//% shim=pxt::getButton(2)
const buttonsAB: Button;
}
declare namespace input {
/**
* Capacitive pin A1
*/
//% block="touch A1" fixedInstance shim=pxt::getTouchButton(PIN_A1)
const touchA1: TouchButton;
/**
* Capacitive pin A2
*/
//% block="touch A2" fixedInstance shim=pxt::getTouchButton(PIN_A2)
const touchA2: TouchButton;
/**
* Capacitive pin A3
*/
//% block="touch A3" fixedInstance shim=pxt::getTouchButton(PIN_A3)
const touchA3: TouchButton;
/**
* Capacitive pin A4
*/
//% block="touch A4" fixedInstance shim=pxt::getTouchButton(PIN_A4)
const touchA4: TouchButton;
/**
* Capacitive pin A5
*/
//% block="touch A5" fixedInstance shim=pxt::getTouchButton(PIN_A5)
const touchA5: TouchButton;
/**
* Capacitive pin A6
*/
//% block="touch A6" fixedInstance shim=pxt::getTouchButton(PIN_A6)
const touchA6: TouchButton;
/**
* Capacitive pin A7
*/
//% block="touch A7" fixedInstance shim=pxt::getTouchButton(PIN_A7)
const touchA7: TouchButton;
/**
* Capacitive pin A1
*/
//% block="pin A1" fixedInstance shim=pxt::getTouchButton(PIN_A1)
const pinA1: TouchButton;
/**
* Capacitive pin A2
*/
//% block="pin A2" fixedInstance shim=pxt::getTouchButton(PIN_A2)
const pinA2: TouchButton;
/**
* Capacitive pin A3
*/
//% block="pin A3" fixedInstance shim=pxt::getTouchButton(PIN_A3)
const pinA3: TouchButton;
/**
* Capacitive pin A4
*/
//% block="pin A4" fixedInstance shim=pxt::getTouchButton(PIN_A4)
const pinA4: TouchButton;
/**
* Capacitive pin A5
*/
//% block="pin A5" fixedInstance shim=pxt::getTouchButton(PIN_A5)
const pinA5: TouchButton;
/**
* Capacitive pin A6
*/
//% block="pin A6" fixedInstance shim=pxt::getTouchButton(PIN_A6)
const pinA6: TouchButton;
/**
* Capacitive pin A7
*/
//% block="pin A7" fixedInstance shim=pxt::getTouchButton(PIN_A7)
const pinA7: TouchButton;
}
Here's an example for how to use a paper circuit with the CPE -- you can use alligator clips to connect to the copper tape.
To make a better connection for the LED onto the paper circuit:
Use needle nose pliers to curl the LED leads.
Be sure you know which one is positive and which is negative!
Then, rest the LED on copper tape and use a small piece to "sandwich" the curled leads and make a decent connection.
Here's another example that shows how to connect two LEDs (in parallel).
You may need to play with the threshold value. If it's too low, then it will be very sensitive; sometimes just attaching an alligator clip will count as a "touch." In this case, use the Serial monitor to determine a better threshold value.
Build a little component that "sandwiches" the velostat between two conductive layers of "bread."
Materials
1 small rectangle of velostat
The size is up to you -- the pictures in this tutorial use about 2" x 3"
In Fimbel, velostat is located in the Electronics Cabinet
A 10K resistor
In Fimbel, these are in the organizer above the soldering station. Look for the drawer that says 10k.
Copper tape
Paper/cardboard
Draw/cut out your sandwich "bread" layers using your velostat to guide the size. In the picture below, you'll see that the righthand side is set up to have 2 attachment areas, while the left side only has one.
Use copper tape to cover each "bread" layer/side.
The strips of copper tape should be complementary to each other to ensure that current can flow (through the velostat) from one side to the other.
Make sure that the copper tape from each layer of bread does not touch -- there must be velostat sandwiched between.
Use copper tape to attach the 10k resistor to one side. Use another piece of copper tape to attach the resistor.
Place the velostat between the two sides, and your velostat "sandwich" pressure sensor is complete!
Use 3 alligator clips to attach:
the resistor to a GND pin
the other strip of the same (ground) side to an analog pin
use A3 on the Circuit Playground to work with the sample code
the strip on the other side to a voltage 3.3V pin
Micro Servo 9g SG90 (in Elegoo kits)
Attach your wires from the Servo to the CPE:
GND to GND (brown in the image)
Voltage to 3.3V or Vout (red in the image)
PWM control to A1 (orange in the image)
Double-check your connections and make sure no metal is touching other metal that you don't want!