28 February 2026

Scaffolding: Mapping "Tap Fast"

The concept of the game is to try to press a button at the same time that the LED goes over the other LED, so it's just a timing game where you have to time up your button press with the LED lights crossing over. In our game however you have to use the light sensor instead of a button to when the LED light goes over the indicated light and once you do that it the game ends and you hear a victory jingle and if you don't do it you can try again by restarting the game by using the switch to turn of the playground and turn it on again. You can also use the potentiometer to change the brightness of the LED to whatever you want.

CODE:

#include <Adafruit_CircuitPlayground.h>

int PIN_SWITCH = A3;
int PIN_POT    = A2;

int GREEN_light = 0;
int RED_light = 1;

int next = 0;

bool isSwitchOn() {
  return digitalRead(PIN_SWITCH) == LOW;
}

void setup() {
  CircuitPlayground.begin();
  pinMode(PIN_SWITCH, INPUT_PULLUP);
}

void loop() {

  // Brightness control by the potentiometer
  int pot = analogRead(PIN_POT);
  int brightness = map(pot, 0, 1023, 0, 255);
  CircuitPlayground.setBrightness(brightness);

  // If switch OFF → clear and stop
  if (!isSwitchOn()) {
    CircuitPlayground.clearPixels();
    return;
  }

  int now = millis();

  // Move red every 1000 millisec, and return to 0 after circle
  if (now - next >= 1000) {
    next = now;
    RED_light = RED_light + 1;
    if (RED_light >= 10) RED_light = 0;
  }

  // clear both light and redraw green
  CircuitPlayground.clearPixels();

  CircuitPlayground.setPixelColor(GREEN_light, 0, 255, 0);


 // If red hits green show yellow and check light sensor to win
if (RED_light == GREEN_light) {
  CircuitPlayground.setPixelColor(GREEN_light, 255, 255, 0);

  int lightValue = CircuitPlayground.lightSensor();

  if (lightValue < 50) {
    for (int i = 0; i < 10; i++) {
      CircuitPlayground.setPixelColor(i, 0, 255, 0);
    }
    CircuitPlayground.playTone(990, 60);
    delay(70);
    CircuitPlayground.playTone(1320, 120);
    delay(2000);              
    NVIC_SystemReset();
  }

} else {
  // else keep red light moving
  CircuitPlayground.setPixelColor(RED_light, 255, 0, 0);
}
}

Video: https://www.youtube.com/watch?v=1mJ_hX0fnII








Le twistinator


 The game we have is currently you would try to get the white dot in between the red dots to clear the level. You would move the board in the direction you wanted the dot to go and you would need to try to control it to perfectly go into the green dot. If you don’t get the dot into the green dot in time the whole board will flash red at you and if you do get it there in time and click the button you will get the whole board to light up green. The goal of the game is to get the white dot into the green dot and when you clear that stage you can decrease the time it takes for you to fail the game in a certain amount of time.The win condition is to try to click the button while your dot is in the green circle and clear the last difficult


Code:

#include <Adafruit_CircuitPlayground.h>

#include <Adafruit_Circuit_Playground.h>


int goalIndex;

int blockLeft;

int blockRight;


unsigned long timer;

unsigned long startTime;


//analog inputs

//potentiometer (A3)

int value;

//button (A2)

int value2;

int speed;


bool lastButton = false;


void setup() {

  Serial.begin(9600);

  delay(1000);

  CircuitPlayground.begin();

  randomSeed(analogRead(0));

  newGoal();

}


void loop() 

{

  //inputs

  //potentiometer

  value = analogRead(A3);

  //button  

  value2 = analogRead(A2);


  //speed using potentiometer

  if (value <= 200) speed = 1;

  if (value > 200 && value <= 300) speed = 2;

  if (value > 300 && value <= 400) speed = 3;

  if (value > 400 && value <= 500) speed = 4;

  if (value > 500 && value <= 600) speed = 5;

  if (value > 600 && value <= 700) speed = 6;

  if (value > 700 && value <= 800) speed = 7;

  if (value > 800 && value <= 900) speed = 8;

  if (value > 900) speed = 9;


  //timer

  timer = speed * 800;  


  //tilting

  float x = CircuitPlayground.motionX();

  float y = CircuitPlayground.motionY();

  float rad = atan2(y, x);


  //led things

  int playerLED = mapfloat(rad, -PI, PI, 0, 10);

  playerLED = playerLED - 2;

  if (playerLED < 0) playerLED += 10;

  if (playerLED > 9) playerLED = 9;


  //Leds

  CircuitPlayground.clearPixels();

  CircuitPlayground.setPixelColor(blockLeft, 255, 0, 0);

  CircuitPlayground.setPixelColor(blockRight, 255, 0, 0);

  CircuitPlayground.setPixelColor(goalIndex, 0, 255, 0);

  CircuitPlayground.setPixelColor(playerLED, 80, 80, 80);


  //buttons

  float buttonScaled = mapfloat(value2, 0, 1023, 0.0, 1.0);

  bool buttonNow = (buttonScaled > 0.1); 


  if (buttonNow && !lastButton) 

  {

    if (playerLED == goalIndex) 

    {

      winFlash();

      newGoal();

    } 

    else if (playerLED == blockLeft || playerLED == blockRight) 

    {

      loseFlash();

      newGoal();

    }

  }


  lastButton = buttonNow;


  //timer

  if (millis() - startTime >= timer) 

  {

    loseFlash();

    newGoal();

  }


  delay(20);

}


//sets goals

void newGoal() 

{

  goalIndex = random(1, 9);

  blockLeft = (goalIndex + 9) % 10;

  blockRight = (goalIndex + 1) % 10;

  startTime = millis();

}


//flash led winning

void winFlash() {

  for (int i = 0; i < 3; i++) 

  {

    CircuitPlayground.clearPixels();

    for (int j = 0; j < 10; j++) 

    {

      CircuitPlayground.setPixelColor(j, 0, 255, 0);

    }

    delay(200);

    CircuitPlayground.clearPixels();

    delay(200);

  }

}


//flash led losing

void loseFlash() {

  for (int i = 0; i < 3; i++) 

  {

    CircuitPlayground.clearPixels();

    for (int j = 0; j < 10; j++) 

    {

      CircuitPlayground.setPixelColor(j, 255, 0, 0);

    }

    delay(200);

    CircuitPlayground.clearPixels();

    delay(200);

  }

}


//math from teachers vid

float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) 

{

  float result = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

  return result;

}




Video:


https://youtube.com/shorts/3bcjK8LFgwA?feature=share








25 February 2026

Ignacio Vergara - Noise Makers

 

 

Noise Makers

Description

This week I built a simple MIDI instrument using three buttons and one potentiometer. The buttons trigger the notes, and the knob controls the pitch across two octaves.

Each button corresponds to a different note: C, D, and E. The potentiometer changes the MIDI note value over a 24-semitone range, which equals two octaves, since one octave consists of 12 consecutive semitones.

For each button, I mapped the knob to a specific MIDI range:

  • Button 1 (C): The knob controls values from 48 to 72, which corresponds to C3 up to C5
  • Button 2 (D): The knob controls values from 50 to 74, which corresponds to D3 up to D5.
  • Button 3 (E): The knob controls values from 52 to 76, which corresponds to E3 up to E5. 

To play the notes I used a software called Reaper which is a DAW program that allows me to attach a synthesizer to my MIDI instrument and play piano notes.


 Video Demonstration

 



 Photos









 Sketch

 

 

Schematic








Code

 

/*
 * MIDIUSB_test.ino
 *
 * Created: 4/6/2015 10:47:08 AM
 * Author: gurbrinder grewal
 * Modified by Arduino LLC (2015)
 */

#include "MIDIUSB.h"

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

int btn1 = 9;
int btn2 = 10;
int btn3 = 11;
const int knobPin = A0;

void setup() {
  Serial.begin(115200);
  pinMode(btn1, INPUT_PULLUP);
  pinMode(btn2, INPUT_PULLUP);
  pinMode(btn3, INPUT_PULLUP);
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void loop() {

  int knob = analogRead(knobPin);
 
  int note1 = map(knob, 0, 1023, 48, 72); // 1 octave is 12 consecutive semitones so this will go from C3 which is 48 to 72 which is C5
  int note2 = map(knob, 0, 1023, 50, 74);
  int note3 = map(knob, 0, 1023, 52, 76);

  // note 1

  if(digitalRead(btn1) == LOW){
    noteOn(0, note1, 64);   // Channel 0, middle C, normal velocity
    Serial.println("Sending note on");
  }
    if(digitalRead(btn1) == HIGH){
    noteOff(0, note1, 64);   // Channel 0, middle C, normal velocity
    Serial.println("Sending note on");
  }
  MidiUSB.flush();

  // note 2

    if(digitalRead(btn2) == LOW){
    noteOn(0, note2, 64);   // Channel 0, middle C, normal velocity
    Serial.println("Sending note on");
  }
    if(digitalRead(btn2) == HIGH){
    noteOff(0, note2, 64);   // Channel 0, middle C, normal velocity
    Serial.println("Sending note on");
  }
  MidiUSB.flush();

  // note 3

    if(digitalRead(btn3) == LOW){
    noteOn(0, note3, 64);   // Channel 0, middle C, normal velocity
    Serial.println("Sending note on");
  }
    if(digitalRead(btn3) == HIGH){
    noteOff(0, note3, 64);   // Channel 0, middle C, normal velocity
    Serial.println("Sending note on");
  }
  MidiUSB.flush();

}

 






17 February 2026

Cubano Tarot


This project takes a DC motor with a fan attachment and turns it into a fun little Fortune Teller game. The Cubano Tarot is based on a form of card-based fortune telling more commonly seen in members of the Afro-Latino Cuban community. Including my own family.

A button placed on the breadboard and when pressed by either the Fortune Teller or the person having their fortune read, the preprogrammed Arduino code allows the fan on the DC Motor to spin for about 10 to 15 seconds. Attached to the fan are three coins. The Crying Eye, which represents failure. The Rose which represents money. And lastly, the wine cup which represents happiness. There is also a circular based at the bottom with three leaf-designed. Each leaf has a Roman numeral from 1 to 3. The person having their fortune read has to assign a wish or a prediction to each leaf. Depending on what coin lands where determines their future. Or, if the coins don’t align with the three leaves, then the fortune is inconclusive or if the person likes, they can wait for the coins to spin again and land on a proper leaf.

The art has been drawn by me in Adobe Illustrator. Then, laser cut into their specific shapes and glued together. A fan has had each coin, (that has been glued to a stick) taped to its individual wing. Then, the DC Motor is placed through a hole in the bottom base—the base being propped up by a Cuban coffee cup—and the fan attached. Allowing it to spin above the base.

Sketch


Schematic

Pictures

 

Video Demonstration 



Code

//www.elegoo.com
//2016.12.12

/************************
Exercise the motor using
the L293D chip
************************/

#define ENABLE 5
#define DIRA 3
#define DIRB 4

int i;
 
void setup() {
  //---set pin direction
  pinMode(ENABLE,OUTPUT);
  pinMode(DIRA,OUTPUT);
  pinMode(DIRB,OUTPUT);
  Serial.begin(9600);
}

void loop() {

  // RUN MOTOR for 10 SECONDS TOTAL
  digitalWrite(ENABLE, HIGH);

  digitalWrite(DIRA, HIGH);
  digitalWrite(DIRB, LOW);
  delay(5000);   // run 5 seconds

  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, HIGH);
  delay(5000);   // run 5 seconds

  // TOP MOTOR FOR 15 SECONDS
  digitalWrite(ENABLE, LOW);   // stop motor
  Serial.println("Motor stopped");
  delay(15000);                // stay stopped 15 seconds
}