This project is available for sale! Email me at: aspen@kimly.net to buy one.
I used a potentiometer, a force sensor, a red LED and a blue LED for this circuit. The two LEDs were connected to PWM pins so that their brightness could be controlled by the variable resistors. The variable resistors were connected to analog pins. After using the serial monitor to find the range of values the sensors were outputting, I used the map() function to convert between these values and the LED brightness values of 0-255. The sensor values for the potentiometer only reached a maximum of about 715. This, I later learned, was caused by my use of the 3.3 V pin instead of the 5V pin of the microcontroller.
Enjoying the use of variable resistors, I changed my code to use their outputs differently. I made the two LEDs blink on and off apart from each other, and used the force sensor to turn the lights on and off (within a certain threshold of values, the LEDs turned on, which equates to simply pressing on the force sensor). The potentiometer controlled the speed of the blinking (the delay between the lights switching). The map function made this very easy, as I could use it to turn the potentiometer output to numbers in a chosen range of milliseconds.
Design an interactive concept with two or more analog inputs and 2 different outputs
I wanted to make a game that uses the way neopixel strips are programmed with red, green, and blue values. The potentiometers control the values of these three colors for one LED, and a random number generator mapped to the color values controls the values of these colors for the other LED. The player must use the potentiometers to match the first LED to the random-colored LED. When the colors match within a threshold of numbers (10 above or below the target), the lights flash and a buzzer plays three notes. A button can be pressed to restart the game with a new random color.
I used 3 potentiometers, a buzzer, a button, and two separate neopixel LEDs.
I switched out the potentiometers for nicer ones and split the LED strip into two separate pieces, taking all the components off the breadboard. I also added a speaker to add auditory feedback.
First, I tested my idea with 3 potentiometers, a button, and a set of 2 neopixels.
I used my set up to write and test my code. Most of the issues I had were simple, like missing a semicolon or an equals sign. Overall, the code is simple. The two LEDs are separate, with one being controlled by a random generation of numbers, and the other being controlled by the three potentiometers.
/*
Syntax
map(value, fromLow, fromHigh, toLow, toHigh)
Parameters
value: the number to map.
fromLow: the lower bound of the value’s current range.
fromHigh: the upper bound of the value’s current range.
toLow: the lower bound of the value’s target range.
toHigh: the upper bound of the value’s target range.
*/
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
//define the digital pin that the LED strip is connected to
#define PIN1 12
#define PIN2 11
//the first parameter is the number of LEDs you have - change for your strip
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(1, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(1, PIN2, NEO_GRB + NEO_KHZ800);
//knob values
const int RPin = A0;
int RVal = 0;
const int GPin = A1;
int GVal = 0;
const int BPin = A2;
int BVal = 0;
//random color values
int R = 0;
int G = 0;
int B = 0;
bool go = true;
bool done = false;
bool play = true;
const int buttonPin = 10;
int buttonVal = 0;
const int buzzerPin = 6;
int threshold = 12; //changes how easy the game is -- higher threshold is easier
void setup() {
Serial.begin(9600);
strip1.begin();
strip1.show(); // Initialize all pixels to 'off'
strip2.begin();
strip2.show(); // Initialize all pixels to 'off'
pinMode(buttonPin, INPUT);
pinMode(buzzerPin, OUTPUT);
}
void loop() {
//read knob values and map them to color values
RVal = analogRead(RPin);
RVal = map(RVal, 0, 1023, 0, 255);
GVal = analogRead(GPin);
GVal = map(GVal, 0, 1023, 0, 255);
BVal = analogRead(BPin);
BVal = map(BVal, 0, 1023, 0, 255);
buttonVal = digitalRead(buttonPin);
//Serial.print(buttonVal);
//Serial.print(", ");
if (buttonVal == HIGH)
{
go = true; //responsible for the random color changing only when the button is pressed
done = false; //responsible for showing that the game has been completed
play = true; //responsible for the visual and auditory feedback
}
if (go == true)
{
R = random(0, 255);
G = random(0, 255);
B = random(0, 255);
strip2.setPixelColor(0, R, G, B);
strip2.show();
go = false;
}
//used to monitor the values of the knobs compared to the random color
Serial.print(", ");
Serial.print(R);
Serial.print(" ");
Serial.print(RVal);
Serial.print(", ");
Serial.print(G);
Serial.print(" ");
Serial.print(GVal);
Serial.print(", ");
Serial.print(B);
Serial.print(" ");
Serial.println(BVal);
if (done == false)
{
strip1.setPixelColor(0, RVal, GVal, BVal);
strip1.show();
}
if ((RVal >= (R - threshold) && RVal <= (R + threshold) ) && (GVal >= (G - threshold) && GVal <= (G + threshold)) && (BVal >= (B - threshold) && BVal <= (B + threshold) ))
{
done = true;
if (play == true)
{
tone(buzzerPin, 349.2);
delay(300);
noTone(buzzerPin);
delay(50);
tone(buzzerPin, 440);
delay(300);
noTone(buzzerPin);
delay(50);
tone(buzzerPin, 523.3);
delay(300);
noTone(buzzerPin);
strip1.setPixelColor(0, 0, 0, 0);
strip2.setPixelColor(0, 0, 0, 0);
strip1.show();
strip2.show();
strip1.setPixelColor(0, R, G, B);
strip2.setPixelColor(0, R, G, B);
strip1.show();
strip2.show();
delay(500);
strip1.setPixelColor(0, 0, 0, 0);
strip2.setPixelColor(0, 0, 0, 0);
strip1.show();
strip2.show();
delay(500);
strip1.setPixelColor(0, R, G, B);
strip2.setPixelColor(0, R, G, B);
strip1.show();
strip2.show();
delay(500);
strip1.setPixelColor(0, 0, 0, 0);
strip2.setPixelColor(0, 0, 0, 0);
strip1.show();
strip2.show();
delay(500);
play = false;
}
//A (440), A (440), A (440), F (349.2), A (440), C (523.3)
}
}
With the help of a friend, I brainstormed a design for the shape of the game. I wanted it to be easy to hold and able to be laser cut. Making it a familiar game controller shape helped show that it is a game.
The first design had the controller shape, but felt too blocky in order to make it laser cutter friendly.
The second design had a simple shape and would have worked, but seemed boring.
The final design had the controller shape and a less square box, a combination of the first two designs.
Handles help the player hold the box while using the knobs.
The box is laser cut and sanded to round corners after the pieces were glued together.
I had to recut all the pieces multiple times because I misjudged how much space I would need for the wiring and components. I added color and direction labels to the knobs, holes for the speaker, and a small hole for the button.
The LEDs are diffused using a translucent paper inside of spray bottle caps.
3D printing was easy since I already had the handles modelled. I sanded them to a soft texture with 320 grit sandpaper.
The first step was to replace the pushbutton with a button with a longer stem. This allowed it to poke through the wood out of the box.
Next, I glued all the components on to the back of the wooden top. I added tin foil to the back of the lights to make more light reflect out.
I then plugged in all the wires, being careful to make sure they were pushed all the way into the breadboard, and glued the box on over the circuitry.
The final sensor "box" is a playable game that works consistently and is sturdy. It has rounded edges and comfortable handles, and a simple task. The only wire coming out from the box is for power. The box can stand up on its own or be played while being held.