Craft Time Reminder
By Team Chestnut: Patrick, Allison, Emily
Final Documentation
Introduction
For our physical computing final project, we were tasked with designing an assistive device for a client from CLASS, a Pittsburgh-based organization that promotes community inclusion for individuals with disabilities. By conducting interviews and creating prototypes, our goal is to use physical computing skills to develop a device that meets the specific needs of our client, Kathy.
Learn more about our first interview with Kathy here.
What We Built
Front view of the crafting time reminder, power on
The Craft Time Reminder helps Kathy take breaks during her crafting sessions and includes a necklace that securely holds her crafting tools. Kathy likes to work on detailed crafting projects like diamond art and loom knitting, where she often loses track of time and experiences eye strain. The timer starts automatically when the necklace is removed and is preset to one hour, with the total time shown on the display. She can adjust the time in 15-minute increments using buttons and pause the timer during breaks. Audio feedback reports actions such as time adjustments, the timer and necklace's status, and the remaining time. The LED ring shows progress in pink and blinks red when the timer ends. Returning the necklace resets the timer, making it easy to manage breaks while crafting.
Power on: necklace detected, timer set to 60 minutes, LED ring showing 0
front and back view of the device
Below are close-ups showcasing the three different states of the LED ring
Timer Active: pink, increase as time goes
Timer Paused: light green light
Time Up: Blinks red
Photo of our client Kathy interacting with the device in the physical computing lab :)
Close-up of the necklace's pen holder, different sizes available to accommodate different crafting tool sizes that Kathy uses.
bottom view of the device, double-A battery box & rubber feet
Demo Mode: Set to 1 minute, show function of the beam break sensor, MP3 player, LED ring, LED button, and time display.
Other Features: ±15 minutes adjustment buttons, MP3 player, beam break sensor, LED ring, and time display.
Narrative Sketch
Kathy sits down at her crafting table to begin a new diamond art project. She picks up her craft tool necklace, attaches her diamond art pen to it, and the Crafting Reminder starts its one-hour timer with an audio message saying, “Necklace removed, total time 60 minutes. Happy crafting!” The LED ring lights up in pink as the display shows the time ticking down.
With 10 minutes left on the timer, Kathy presses a button to add 15 more minutes to finish her current section. The device beeps and says, “25 minutes and 20 seconds remaining.” When the LED ring begins blinking red to signal the end of the timer, Kathy places the necklace back into the funnel. The timer resets automatically, and a voice says, “Necklace detected.” Kathy steps away from her work to take a short break.
How We Got Here (Prototypes)
This prototype was designed to help answer two main design questions: Where should we place the components to make them most convenient for our client? Is our current method of presenting information clear and effective for our client?
Additional questions we asked
Notes from Prototype Testing Session
For our first cardboard prototype, we designed it so that each component could be easily rearranged, allowing Kathy to experiment with different layouts to find what worked best for her. We wired some basic components that we wanted to include, such as the LED strip, LCD screen, and reed switch, so Kathy could get a basic understanding of how the different components work.
During our in-class session, Kathy tested the prototype and answered our questions. We learned several important things about the layout. Since Kathy is left-handed, she prefers frequently used features to be placed on the left side of the device, while components like the LCD screen and LED light strip, which don’t require interaction, are better positioned on the right. She also finds it more convenient when all the buttons are located near the bottom edge of the device. We also discovered that a slightly slanted device surface makes it easier for Kathy to read the displayed information. Additionally, the prototype helped us narrow down what worked and what didn’t. For example, the LED was too bright, the text on the LCD screen was small, and the reed switch was a little fragile and difficult for Kathy to attach a magnet to and secure.
Kathy suggested adding audio feedback, as the device would be placed in the top-left corner of her craft table, making it harder to see at all times while crafting. She also proposed adding a feature to help open the lids of her diamond art boxes. However, after discussing this idea as a team, we decided not to move forward with that feature.
How We Got Here (Process)
Drawing out the device layout on the whiteboard using the components we plan to use
Building the design using CAD software to export as DXF for laser cutting
1st laser cut prototype, the funnel and some buttons did not fit
Final prototype taped together & ready for assembly
Testing the ±15 minutes adjustment buttons
Soldered all the wires and testing the break beam sensor, mp3 player and the necklace funnel
3D printed a funnel-shaped holder for the necklace and the break beam sensor. The funnel makes the necklace clusters at the bottom for more precise detection. The sensor did not fit in the first attempt.
After two more prints, we finally got the sensor to fit securely
Time-lapse video of the 3D printing
We noticed after soldering that the Arduino and wiring barely fit into the container. We went back and rearranged some of the the pins, shortened all the wires, and resoldered them. Once everything fit, the top piece was finally ready to be glued. We used several clamps of different sizes to securely hold the lid in position while the glue dried.
Discussion
Response to comments
'Triggering mechanism is clever but also specific to certain crafts. '
The original intention of this project is to assist our client, Kathy, by designing a necklace that can hold tools for her crafting work. To incorporate a reminder system along with the necklace mechanism, we designed a funnel-shaped holder for the necklace and used a break beam sensor to detect if the necklace is removed. However, we are aware of the limitations of this mechanism, since the sensitivity of the break beam sensor is sometimes beyond our control, which can cause the entire system to malfunction. Additionally, attaching other crafting tool holders to the necklace could further help Kathy with her various crafting activities.
'Reconsider direction on progress to match typical timers. Voice commands maybe. '
When creating our prototype, we initially considered using an LED strip as a progress bar with an LCD display to show the time remaining. However, we ultimately decided to use an LED ring instead, as its mechanism resembles the functioning of a real-life clock. Also, if we have a chance to continue to work on this project in the future, we would love to add a function so that our client will be able to use voice commands to control the system since buttons can sometimes be hard to access.
Self critique pertaining to the project
We are satisfied with the final product we created, even though some parts still have flaws. Our final product meets almost all the goals we initially set. However, we have two concerns: a minor bug in the code and the sensitivity issue with the break beam sensor.
For the code bug, we originally planned for the system to enter demo mode when the user deducts the total time to 0 using the button of minus 15 minutes. In demo mode, the total time on the display would automatically set to 1 minute. However, if the user tries to reset the total time to 60 minutes, they are unable to do so. This is because the "add 15" button adds 15 minutes to the 1 minute remaining from demo mode, rather than starting from 0.
The sensitivity of the break beam sensor is another concern for us. We designed a funnel as the holder for the necklace, with a pair of break beam sensors attached to its sides. However, as the project progressed, we discovered that the sensors are extremely sensitive, and even minor mistakes in soldering or wiring can cause them to malfunction. Additionally, there are small gaps when the necklace is placed in the funnel, which leads to inconsistent sensor readings, especially when the device is moving or vibrating.
What we learned about our own abilities and/or limitations
One of the most important lessons we learned during this project was that we need to carefully consider the space required for all the components before designing the box. Toward the end of the project, we found it very challenging to fit everything into the box we had designed. As a result, we had to cut most of the wires to make the electrical components take less space. Additionally, we initially did not consider the space for the battery box in our design, which also resulting in the shortage of space inside the box for our final product.
In addition, we realized that it was extremely important to frequently test each component throughout the process. For instance, before soldering all the electronic components together, we tested the MP3 player with the SD card and the speaker. Initially, it was frustrating because they didn’t work, but we eventually discovered it was a wiring issue. If the problem had been with the hardware itself or caused by a slight bug that is hard to find in the code, identifying and fixing it would have been much more time-consuming and could have significantly impacted the overall progress of our project.
Next steps
If we have a chance to start another iteration of this project, we would really like to implement the voice command system mentioned by Professor Zeglin in the feedback section for our client so that Kathy will be able to control the total time without accessing the button and she will be able to fully focus on the crafting work.
Technical Information
Block Diagram
Schematic Diagram
finalproj.ino
/*
Main Code File For Craft Time Reminder
Team Chestnuts: Patrick Zhu, Allison Feldman, Emily Lau
The Craft Time Reminder helps a user remember take breaks during a crafting session. The device
includes a necklace that can be used to hold a crafting tool in place. When this necklace is removed
from its container, the timer starts. The total time can be adjusted in 15-minute intervals before
or after the timer starts. Returning the necklace to its container stops and resets the timer. The
device also includes a multi-purpose pause, start, and mute button.
Code written for an Arduino Uno
Pin Mapping:
Arduino pin | Role | Description
-------------------------------------------------------------------
A4 | output | Used as SDA for the 7-segment clock display
A5 | output | Used as SCL for the 7-segment clock display
2 | input | Reads the TX signal from the DFPlayer Mini
3 | output | Transmits to the RX pin on the DFPlayer Mini
5 | output | Controls the 12-segment LED Ring
6 | input | Reads the signal from the "-15" button
7 | input | Reads the signal from the "+15" button
8 | input | Reads the "busy" pin from the DFPlayer Mini
10 | input | Reads the signal from the LED Arcade Button
11 | output | Controls the LED on the LED Arcade Button
12 | input | Reads the signal from the IR Break Beam Sensor
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h>
#include <Adafruit_NeoPixel.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Arduino.h>
#include "filemapping.h"
// Pin definitions
#define PIN_MP3_TX 2
#define PIN_MP3_RX 3
#define LEDRINGPIN 5
#define MINUSBUTTONPIN 6
#define PLUSBUTTONPIN 7
#define BUSYPIN 8
#define BIGBUTTONPIN 10
#define BIGBUTTONLEDPIN 11
#define SENSORPIN 12
// Define colors in RGB
const int pink_rgb[3] = {76, 19, 30};
const int yellow_rgb[3] = {82, 71, 3};
const int red_rgb[3] = {85, 0, 0};
unsigned long currentMillis;
bool isPlayerIdle;
unsigned long playerIdleStart; // when an "idle" period (nothing is playing) starts
// Timer
unsigned long totalTime_ms = 60 * 60000; // 60 minutes
bool timerReset; // Whether or not the device is in the "reset" state
bool timerStarted = false;
bool timerPaused = false;
bool ledRingBlinkOn = false;
bool timerFinished = false;
bool alarmStopped = false; // alarm == the sound
unsigned long elapsedTime;
long remaining_ms = totalTime_ms;
int remaining_minutes = remaining_ms / 60000;
unsigned long timerStartMillis = 0;
unsigned long pauseStart; // stores the time that a "pause" period was started
unsigned long pauseDuration = 0;
// Button LED
const int buttonBlinkMs = 1000;
const int buttonFlashMs = 500;
unsigned long lastButtonBlinkStart = 0;
bool buttonLEDOn = false;
// LED RING
const int LEDCount = 12;
int lightsOn = 0;
unsigned long intervalLength_ms = totalTime_ms / LEDCount;
const int flashInterval = 1000; // LED flashing interval
unsigned long lastFlashMillis = 0;
// NECKLACE SENSOR
const unsigned long unbrokenThreshold = 2000; // 2 seconds
const unsigned long brokenThreshold = 2000; // 2 seconds
unsigned long unbrokenStartMillis = 0;
unsigned long brokenStartMillis = 0;
int sensorState = 0;
int sensorLastState = 0;
// Button/Sensor States
bool plusButtonLastState = LOW;
bool minusButtonLastState = LOW;
bool bigButtonLastState = LOW;
// Audio variables
bool soundPlaying = false;
int currentSoundFileNum;
int word_i = 0; // the current index of an audio phrase's words[] array
// Audio sequences control variables
bool playStartSound = false;
bool playTotalTimeSound = false;
bool playTimeRemainingSound = false;
bool playTimerPausedSound = false;
bool playTimerStartedSound = false;
bool playTimerFinishedSound = false;
bool playNecklaceDetectedSound = false;
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
DFRobotDFPlayerMini player;
Adafruit_7segment display = Adafruit_7segment();
Adafruit_NeoPixel ring(LEDCount, LEDRINGPIN, NEO_GRB + NEO_KHZ800);
void setup() {
// Set up pins
// pinMode(SENSORPIN, INPUT);
pinMode(SENSORPIN, INPUT_PULLUP);
pinMode(PLUSBUTTONPIN, INPUT);
pinMode(MINUSBUTTONPIN, INPUT);
pinMode(BIGBUTTONPIN, INPUT);
// pinMode(pinButton, INPUT_PULLUP); // Set button pin as input with pull-up resistor
pinMode(BIGBUTTONLEDPIN, OUTPUT); // Set LED pin as output
digitalWrite(BIGBUTTONLEDPIN, LOW);
digitalWrite(SENSORPIN, HIGH); // Enable pull-up resistor
// Set up NeoPixel ring
ring.begin();
ring.setBrightness(100);
ring.show();
Serial.begin(9600);
softwareSerial.begin(9600);
initializeNumberMappings();
initializeOtherSoundMappings();
if (player.begin(softwareSerial)) {
// Set volume to maximum (0 to 30).
player.volume(30);
} else {
Serial.println("Connecting to DFPlayer Mini failed!");
}
resetTimer();
display.begin(0x70); // Default I2C address for the 7-segment display
displayTime(); // Display initial total time
}
void loop() {
currentMillis = millis(); // Get the current time
// Read sensor state
sensor();
// Handle all buttons
plusminusButton();
bigButton();
// Update timer
updateTimer();
// Update the LED ring and display
ledRing();
displayTime();
// Play any/all relevant audio
audio_all();
delay(50);
}
void sensor() {
sensorState = digitalRead(SENSORPIN);
if (timerReset && sensorState) {
// If unbroken, start tracking the time
if (!sensorLastState) {
unbrokenStartMillis = currentMillis;
} else if (currentMillis - unbrokenStartMillis >= unbrokenThreshold && !timerStarted) {
startTimer();
}
} else if (!timerStarted) {
// Reset the unbroken timer if the state becomes "broken"
unbrokenStartMillis = 0;
}
if (!timerReset && !sensorState) { // if the timer hasn't been reset yet and the sensor is "blocked"
// If broken, start tracking the time
if (sensorLastState) {
brokenStartMillis = currentMillis;
} else if (currentMillis - brokenStartMillis >= brokenThreshold) {
resetTimer();
playNecklaceDetectedSound = true;
}
} else {
// Reset the unbroken timer if the state becomes "broken"
brokenStartMillis = 0;
}
// Print state changes
if (sensorState && !sensorLastState) {
Serial.println("Unbroken");
}
if (!sensorState && sensorLastState) {
Serial.println("Broken");
}
sensorLastState = sensorState;
}
void plusminusButton() {
bool plusButtonState = digitalRead(PLUSBUTTONPIN);
bool minusButtonState = digitalRead(MINUSBUTTONPIN);
if (!timerFinished && plusButtonLastState == LOW && plusButtonState == HIGH) {
if (totalTime_ms == (60000)) {
totalTime_ms = 15 * 60000;
} else {
totalTime_ms += (15 * 60000);
}
stopAllSounds();
playTotalTimeSound = true;
if (totalTime_ms > (90 * 60000)) {
totalTime_ms = (90 * 60000);
}
intervalLength_ms = totalTime_ms / LEDCount;
}
if (!timerFinished && minusButtonLastState == LOW && minusButtonState == HIGH && totalTime_ms > 60000) {
if (totalTime_ms == (15 * 60000)) {
totalTime_ms = 60000;
}
else {
totalTime_ms -= (15 * 60000);
}
stopAllSounds();
playTotalTimeSound = true;
if (totalTime_ms < 0) {
totalTime_ms = 0;
}
intervalLength_ms = totalTime_ms / LEDCount;
}
plusButtonLastState = plusButtonState;
minusButtonLastState = minusButtonState;
}
void bigButton() {
bool bigButtonState = digitalRead(BIGBUTTONPIN);
if (bigButtonLastState == LOW && bigButtonState == HIGH) {
if(timerStarted) {
if (timerPaused) {
timerPaused = false;
pauseDuration = pauseDuration + (currentMillis - pauseStart);
stopAllSounds();
playTimerStartedSound = true;
}
else {
pauseStart = currentMillis;
timerPaused = true;
stopAllSounds();
playTimerPausedSound = true;
}
} else if (timerFinished && !alarmStopped) {
alarmStopped = true;
}
}
// Light the LED
if (timerStarted && !timerPaused) {
digitalWrite(BIGBUTTONLEDPIN, HIGH);
}
else if (timerStarted && timerPaused) {
if ((currentMillis - lastButtonBlinkStart) >= buttonBlinkMs) {
lastButtonBlinkStart = currentMillis;
if(!buttonLEDOn) {
digitalWrite(BIGBUTTONLEDPIN, HIGH);
buttonLEDOn = true;
} else {
digitalWrite(BIGBUTTONLEDPIN, LOW);
buttonLEDOn = false;
}
}
}
else if (timerFinished && !timerReset && !alarmStopped) {
if ((currentMillis - lastButtonBlinkStart) >= buttonFlashMs) {
lastButtonBlinkStart = currentMillis;
if(!buttonLEDOn) {
digitalWrite(BIGBUTTONLEDPIN, HIGH);
buttonLEDOn = true;
} else {
digitalWrite(BIGBUTTONLEDPIN, LOW);
buttonLEDOn = false;
}
}
}
else {
digitalWrite(BIGBUTTONLEDPIN, LOW);
}
bigButtonLastState = bigButtonState;
}
void updateTimer() {
if (timerStarted && !timerFinished) {
elapsedTime = currentMillis - timerStartMillis - pauseDuration;
if (!timerPaused) {
// Countdown calculation
remaining_ms = totalTime_ms - elapsedTime;
}
if (remaining_ms <= 0) { // Check to see if timer is finished
remaining_ms = 0;
timerStarted = false;
timerFinished = true;
ledRingBlinkOn = true;
stopAllSounds();
playTimerFinishedSound = true;
}
}
else if (timerFinished && !timerReset) {
remaining_ms = 0;
}
else {
// Before the timer starts, display total time and ensure LEDs are off
remaining_ms = totalTime_ms;
}
remaining_minutes = remaining_ms / 60000;
// remaining_seconds = (remaining_ms % 60000) / 1000;
}
void ledRing() {
if (timerStarted) {
int ledsToLight = elapsedTime / intervalLength_ms;
for (int i = 0; i < LEDCount; i++) {
if (i < ledsToLight) {
if (!timerPaused) {
ring.setPixelColor(i, ring.Color(pink_rgb[0], pink_rgb[1], pink_rgb[2]));
} else {
ring.setPixelColor(i, ring.Color(yellow_rgb[0], yellow_rgb[1], yellow_rgb[2]));
}
} else if (!timerPaused && i == ledsToLight && !timerFinished) {
flashPendingLED(i, currentMillis);
} else {
// Don't flash last LED on the ring if the timer is paused
ring.setPixelColor(i, 0, 0, 0);
}
}
ring.show();
}
else if (timerFinished && !alarmStopped) {
if ((currentMillis - lastFlashMillis) >= 500) {
lastFlashMillis = currentMillis;
if (ledRingBlinkOn) {
ring.fill(0, 0, 0);
ring.show();
ledRingBlinkOn = false;
} else {
ring.fill(ring.Color(red_rgb[0], red_rgb[1], red_rgb[2]));
ring.show();
ledRingBlinkOn = true;
}
}
}
else {
ring.clear(); // Turn off all LEDs
ring.show();
}
}
void displayTime() {
// Format as MM:SS for the 7-segment display
// int displayValue = (remaining_minutes * 100) + remaining_seconds;
int displayValue = ((remaining_ms / 60000) * 100) + ((remaining_ms % 60000) / 1000);
display.print(displayValue); // Print the time in MMSS format
display.drawColon(true);
display.writeDisplay();
}
void audio_all() {
if (playStartSound) {
audio_timerStart();
}
else if (playTotalTimeSound) {
audio_totalTime();
}
else if (playTimeRemainingSound) {
audio_timeRemaining();
}
else if (playTimerPausedSound) {
audio_timerPaused();
}
else if (playTimerStartedSound) {
audio_timerStarted();
}
else if (playTimerFinishedSound) {
audio_timerFinished();
}
else if (playNecklaceDetectedSound) {
audio_necklaceDetected();
}
}
void resetTimer() {
// player.pause();
stopAllSounds();
totalTime_ms = 60 * 60000;
remaining_ms = totalTime_ms;
timerStarted = false;
timerPaused = false;
alarmStopped = false;
pauseDuration = 0;
timerFinished = false;
timerReset = true;
}
void startTimer() {
timerStarted = true;
timerPaused = false;
pauseDuration = 0;
timerFinished = false;
timerStartMillis = currentMillis;
lastFlashMillis = timerStartMillis;
playStartSound = true;
timerReset = false;
}
void flashPendingLED(int ledNum, unsigned long currentMillis) {
if (currentMillis >= lastFlashMillis + flashInterval) {
if (!ledRingBlinkOn) {
ring.setPixelColor(ledNum, ring.Color(pink_rgb[0], pink_rgb[1], pink_rgb[2]));
} else {
ring.setPixelColor(ledNum, 0, 0, 0);
}
ledRingBlinkOn = !ledRingBlinkOn;
lastFlashMillis = currentMillis;
}
}
void stopAllSounds() {
word_i = 0;
soundPlaying = false;
playStartSound = false;
playTotalTimeSound = false;
playTimeRemainingSound = false;
playTimerPausedSound = false;
playTimerStartedSound = false;
playTimerFinishedSound = false;
playNecklaceDetectedSound = false;
}
void playSound(int soundNumber) {
if (!soundPlaying) {
player.play(soundNumber);
soundPlaying = true;
isPlayerIdle = false;
}
if (soundPlaying) {
if ((digitalRead(BUSYPIN) == 1) && isPlayerIdle == false) {
isPlayerIdle = true;
playerIdleStart = currentMillis;
}
else if(isPlayerIdle == true && digitalRead(BUSYPIN) == 0) {
isPlayerIdle = false;
}
else if (isPlayerIdle == true && (currentMillis - playerIdleStart > 100)) {
soundPlaying = false;
}
}
}
void audio_timeRemaining() {
int words[7] = {
otherSoundMappings.youHave, //"You have..."
getNumberSound(remaining_ms / 60000 ), //"___"
((remaining_ms / 60000) != 1 ? otherSoundMappings.minutes : otherSoundMappings.minute), //"minute(s)
otherSoundMappings.andSound, //"and"
getNumberSound( (remaining_ms % 60000) / 1000 ), //"___"
(((remaining_ms % 60000) / 1000 ) != 1 ? otherSoundMappings.seconds : otherSoundMappings.second), //"second(s)"
otherSoundMappings.remaining //"remaining"
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (!soundPlaying) {
word_i += 1;
}
if (word_i >= 7) {
stopAllSounds();
}
}
void audio_timerPaused() {
int words[1] = {
otherSoundMappings.timerPaused //"Timer paused"
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (!soundPlaying) {
word_i += 1;
}
if (word_i >= 1) {
stopAllSounds();
}
}
void audio_necklaceDetected() {
int words[1] = {
otherSoundMappings.necklaceDetected //"Necklace Detected"
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (!soundPlaying) {
word_i += 1;
}
if (word_i >= 1) {
stopAllSounds();
}
}
void audio_timerStarted() {
int words[1] = {
otherSoundMappings.timerStarted //"Timer started"
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (!soundPlaying) {
word_i += 1;
}
if (word_i >= 1) {
stopAllSounds();
}
}
void audio_totalTime() {
int words[4] = {
otherSoundMappings.beep, //*beep sound*
otherSoundMappings.totalTime, //"Total time:"
getNumberSound(totalTime_ms / 60000), //"___"
((totalTime_ms / 60000) != 1 ? otherSoundMappings.minutes : otherSoundMappings.minute), //"minute(s)"
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (!soundPlaying) {
word_i += 1;
}
if (word_i >= 4) {
stopAllSounds();
if (timerStarted) {
playTimeRemainingSound = true;
}
}
}
void audio_timerFinished() {
int words[1] = {
otherSoundMappings.timerUp // *ringtone audio
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (alarmStopped || !soundPlaying) {
player.pause();
stopAllSounds();
}
}
void audio_timerStart() {
int words[5] = {
otherSoundMappings.necklaceRemoved, //"Necklace removed."
otherSoundMappings.totalTime, //"Total time:"
getNumberSound(totalTime_ms / 60000), //"___"
((totalTime_ms / 60000) != 1 ? otherSoundMappings.minutes : otherSoundMappings.minute), //"minute(s)"
otherSoundMappings.happyCrafting, //"Happy crafting!"
};
currentSoundFileNum = words[word_i];
playSound(currentSoundFileNum);
if (!soundPlaying) {
word_i += 1;
}
if (word_i >= 5) {
stopAllSounds();
}
}
filemapping.h:
#ifndef FILEMAPPING_H
#define FILEMAPPING_H
int numberMappings[91] = {};
void initializeNumberMappings() {
numberMappings[0] = 29;
numberMappings[1] = 25;
numberMappings[10] = 76;
numberMappings[11] = 73;
numberMappings[12] = 78;
numberMappings[13] = 79;
numberMappings[14] = 68;
numberMappings[15] = 70;
numberMappings[16] = 65;
numberMappings[17] = 64;
numberMappings[18] = 54;
numberMappings[19] = 55;
numberMappings[2] = 34;
numberMappings[20] = 49;
numberMappings[21] = 48;
numberMappings[22] = 42;
numberMappings[23] = 45;
numberMappings[24] = 53;
numberMappings[25] = 56;
numberMappings[26] = 63;
numberMappings[27] = 60;
numberMappings[28] = 67;
numberMappings[29] = 71;
numberMappings[3] = 38;
numberMappings[30] = 52;
numberMappings[31] = 57;
numberMappings[32] = 62;
numberMappings[33] = 61;
numberMappings[34] = 50;
numberMappings[35] = 47;
numberMappings[36] = 43;
numberMappings[37] = 44;
numberMappings[38] = 75;
numberMappings[39] = 74;
numberMappings[4] = 15;
numberMappings[40] = 10;
numberMappings[41] = 5;
numberMappings[42] = 17;
numberMappings[43] = 18;
numberMappings[44] = 33;
numberMappings[45] = 40;
numberMappings[46] = 27;
numberMappings[47] = 26;
numberMappings[48] = 80;
numberMappings[49] = 86;
numberMappings[5] = 19;
numberMappings[50] = 35;
numberMappings[51] = 39;
numberMappings[52] = 28;
numberMappings[53] = 24;
numberMappings[54] = 8;
numberMappings[55] = 6;
numberMappings[56] = 16;
numberMappings[57] = 20;
numberMappings[58] = 106;
numberMappings[59] = 105;
numberMappings[6] = 9;
numberMappings[60] = 82;
numberMappings[61] = 85;
numberMappings[62] = 91;
numberMappings[63] = 90;
numberMappings[64] = 108;
numberMappings[65] = 103;
numberMappings[66] = 97;
numberMappings[67] = 100;
numberMappings[68] = 11;
numberMappings[69] = 4;
numberMappings[7] = 7;
numberMappings[70] = 107;
numberMappings[71] = 104;
numberMappings[72] = 96;
numberMappings[73] = 101;
numberMappings[74] = 83;
numberMappings[75] = 84;
numberMappings[76] = 93;
numberMappings[77] = 89;
numberMappings[78] = 36;
numberMappings[79] = 37;
numberMappings[8] = 98;
numberMappings[80] = 21;
numberMappings[81] = 14;
numberMappings[82] = 3;
numberMappings[83] = 12;
numberMappings[84] = 23;
numberMappings[85] = 30;
numberMappings[86] = 41;
numberMappings[87] = 32;
numberMappings[88] = 88;
numberMappings[89] = 94;
numberMappings[9] = 99;
numberMappings[90] = 22;
};
struct SoundMappings {
uint8_t andSound;
uint8_t happyCrafting;
uint8_t minute;
uint8_t minutes;
uint8_t necklaceDetected;
uint8_t necklaceRemoved;
uint8_t remaining;
uint8_t second;
uint8_t seconds;
uint8_t timerIsNowPaused;
uint8_t timerPaused;
uint8_t timerStarted;
uint8_t timerStopped;
uint8_t timeToTakeABreak;
uint8_t totalTime;
uint8_t youHave;
uint8_t beep;
uint8_t timerUp;
};
// const SoundMappings otherSoundMappings;
SoundMappings otherSoundMappings;
void initializeOtherSoundMappings() {
otherSoundMappings.andSound = 66;
otherSoundMappings.happyCrafting = 72;
otherSoundMappings.minute = 69;
otherSoundMappings.minutes = 13;
otherSoundMappings.necklaceDetected = 58;
otherSoundMappings.necklaceRemoved = 95;
otherSoundMappings.remaining = 46;
otherSoundMappings.second = 51;
otherSoundMappings.seconds = 92;
otherSoundMappings.timerIsNowPaused = 1;
otherSoundMappings.timerPaused = 59;
otherSoundMappings.timerStarted = 77;
otherSoundMappings.timerStopped = 31;
otherSoundMappings.timeToTakeABreak = 102;
otherSoundMappings.totalTime = 2;
otherSoundMappings.youHave = 109;
otherSoundMappings.beep = 110;
otherSoundMappings.timerUp = 111;
}
int getNumberSound(int file) {
return numberMappings[file];
}
#endif