Featured

Iteration 3: Close phase

My deliverables for this project are the teeth you can see below and the 3D tools that are also in the images below. There is still work that needs to be done on these two things but my final deliverable was to have an iteration of teeth that were approved and we did a very good job on that.

Lessons that I learned from this project are that you never really stop learning about a software you work on. I am still learning more and more about Blender in order to get the tools exported for use, and that is still a process that takes some time. Along with that I also learned a how to use MeshMixer and what it was. But professionally I learned how to have proper communication when working with a team in different places, InWorks is their own lab in one part of the medical campus while Dr.G is in another and then I was in Boulder. We had to have proper communication in order to make this project successful.

Technical review for this project, the surgical tools still need some work on them in order to export them with the material and shaders. Currently I am unable to export them with materials from blender but I am working on it and getting close to a solution. The teeth are basically done its just making more models to print and adding a little bit of something that will make it more cleared in xrays the separation between the outer part of the tooth and the inside part. Other than that it has gone well and I got most of my MVP done.

For future plans this project will still continue on being worked on, the tools still need a solution to exporting them with full material and shaders on them and the teeth are great but we wanted to also get them into a state where they look almost identical to the ones that are $20. I will still be fallowing this project until I can and continue working on things as much as I can. Hopefully by June the surgical models will be exportable and we can implement them into student use.

Featured

Interactive Object

Phase 1: Getting RFID working

We started by getting the all the parts needed and prioritized getting the RFID to work. We started with a simple RFID id-3LA and a break out board, but while we soldered it onto the breakout board we ran into a problem of not working. It had previously worked before soldering but in the end it stopped working for us, everyone was baffled because they didn’t know why it stopped working it looked fined. In the end we ended up getting another RFID this time we got the ID-12LA with its compatible board and that ended up working for us a lot better. We took a sample program from our online Arduino sources to get the RFID working to scan in our card IDs. We were able to get the cards read in and use their ASCII ID to implement it into the rest of the project.

/******* RFID Test Code *********/
/*****************************
RFID-powered lockbox
Written by: acavis, 3/31/2015
Modified: Ho YUN "Bobby" Chan @ SparkFun Electronics Inc., 11/10/2017
Inspired by & partially adapted from
http://bildr.org/2011/02/rfid-arduino/
Description: This sketch will move a servo when
a trusted tag is read with the
ID-12/ID-20 RFID module
———-HARDWARE HOOKUP———-
PINOUT FOR SERVO MOTOR
Servo Motor —– Arduino
GND GND
Vcc 5V
SIG D9
PINOUT FOR SPARKFUN RFID USB READER
Arduino —– RFID module
5V VCC
GND GND
D2 TX
PINOUT FOR SPARKFUN RFID BREAKOUT BOARD
Arduino —– RFID module
5V VCC
GND GND
GND FORM
D2 D0
Optional: If using the breakout, you can also
put an LED & 330 ohm resistor between
the RFID module's READ pin and GND for
a "card successfully read" indication.
Note: Make sure to GND the FORM pin to enable the ASCII output format.
————————————————–
******************************/
#include <SoftwareSerial.h>
//#include <Servo.h>
// Choose two pins for SoftwareSerial
SoftwareSerial rSerial(5, 3); // RX, TX
// Make a servo object
//Servo lockServo;
// Pick a PWM pin to put the servo on
//const int servoPin = 9;
// For SparkFun's tags, we will receive 16 bytes on every
// tag read, but throw four away. The 13th space will always
// be 0, since proper strings in Arduino end with 0
// These constants hold the total tag length (tagLen) and
// the length of the part we want to keep (idLen),
// plus the total number of tags we want to check against (kTags)
const int tagLen = 16;
const int idLen = 13;
const int kTags = 4;
// Put your known tags here!
char knownTags[kTags][idLen] = {
"111111111111",
"5500080E8FDC",
"550008004A17"
};
// Empty array to hold a freshly scanned tag
char newTag[idLen];
void setup() {
// Starts the hardware and software serial ports
Serial.begin(9600);
rSerial.begin(9600);
}
void loop() {
// Counter for the newTag array
int i = 0;
// Variable to hold each byte read from the serial buffer
int readByte;
// Flag so we know when a tag is over
boolean tag = false;
// This makes sure the whole tag is in the serial buffer before
// reading, the Arduino can read faster than the ID module can deliver!
if (rSerial.available() == tagLen) {
tag = true;
}
if (tag == true) {
while (rSerial.available()) {
// Take each byte out of the serial buffer, one at a time
readByte = rSerial.read();
/* This will skip the first byte (2, STX, start of text) and the last three,
ASCII 13, CR/carriage return, ASCII 10, LF/linefeed, and ASCII 3, ETX/end of
text, leaving only the unique part of the tag string. It puts the byte into
the first space in the array, then steps ahead one spot */
if (readByte != 2 && readByte!= 13 && readByte != 10 && readByte != 3) {
newTag[i] = readByte;
i++;
}
// If we see ASCII 3, ETX, the tag is over
if (readByte == 3) {
tag = false;
}
}
}
// don't do anything if the newTag array is full of zeroes
if (strlen(newTag)== 0) {
return;
}
else {
int total = 0;
for (int ct=0; ct < kTags; ct++){
total += checkTag(newTag, knownTags[ct]);
}
// If newTag matched any of the tags
// we checked against, total will be 1
if (total > 0) {
// Put the action of your choice here!
// I'm going to rotate the servo to symbolize unlocking the lockbox
Serial.println("Success!");
}
else {
// This prints out unknown cards so you can add them to your knownTags as needed
Serial.print("Unknown tag! ");
Serial.print(newTag);
Serial.println();
}
}
// Once newTag has been checked, fill it with zeroes
// to get ready for the next tag read
for (int c=0; c < idLen; c++) {
newTag[c] = 0;
}
}
// This function steps through both newTag and one of the known
// tags. If there is a mismatch anywhere in the tag, it will return 0,
// but if every character in the tag is the same, it returns 1
int checkTag(char nTag[], char oTag[]) {
for (int i = 0; i < idLen; i++) {
if (nTag[i] != oTag[i]) {
return 0;
}
}
return 1;
}
view raw RFIDCode.ino hosted with ❤ by GitHub

Phase 2: Getting RFID to work with MP3 Shield

After we had worked on getting the RFID to work we needed to get the mp3 player shield to connect with the RFID so it played a song when the card was scanned in. We started first by testing out the mp3 player using its library we found sample code that would allow us to control the player through the serial monitor. After plugging in the mp3 player we tested the songs on the micro card and played with it for a little while to figure out how it worked.

/******* MP3 Shield Player Code *********/
/**
* \file FilePlayer.ino
*
* \brief Example sketch of using the MP3Shield Arduino driver, with flexible list of files and formats
* \remarks comments are implemented with Doxygen Markdown format
*
* \author Bill Porter
* \author Michael P. Flaga
*
* This sketch listens for commands from a serial terminal (such as the Serial
* Monitor in the Arduino IDE). Listening for either a single character menu
* commands or an numeric strings of an index. Pointing to a music file, found
* in the root of the SdCard, to be played. A list of index's and corresponding
* files in the root can be listed out using the 'l' (little L) command.
*
* This sketch allows the various file formats to be played: mp3, aac, wma, wav,
* fla & mid.
*
* This sketch behaves nearly identical to MP3Shield_Library_Demo.ino, but has
* extra complicated loop() as to recieve string of characters to create the
* file index. As the Serial Monitor is typically default with no CR or LF, this
* sketch uses intercharacter time out as to determine when a full string has
* has been entered to be processed.
*/
#include <SPI.h>
//Add the SdFat Libraries
#include <SdFat.h>
#include <FreeStack.h>
//and the MP3 Shield Library
#include <SFEMP3Shield.h>
// Below is not needed if interrupt driven. Safe to remove if not using.
#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Timer1
#include <TimerOne.h>
#elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
#include <SimpleTimer.h>
#endif
/**
* \brief Object instancing the SdFat library.
*
* principal object for handling all SdCard functions.
*/
SdFat sd;
/**
* \brief Object instancing the SFEMP3Shield library.
*
* principal object for handling all the attributes, members and functions for the library.
*/
SFEMP3Shield MP3player;
int16_t last_ms_char; // milliseconds of last recieved character from Serial port.
int8_t buffer_pos; // next position to recieve character from Serial port.
//——————————————————————————
/**
* \brief Setup the Arduino Chip's feature for our use.
*
* After Arduino's kernel has booted initialize basic features for this
* application, such as Serial port and MP3player objects with .begin.
* Along with displaying the Help Menu.
*
* \note returned Error codes are typically passed up from MP3player.
* Whicn in turns creates and initializes the SdCard objects.
*
* \see
* \ref Error_Codes
*/
char buffer[6]; // 0-35K+null
void setup() {
uint8_t result; //result code from some function as to be tested at later time.
Serial.begin(115200);
Serial.print(F("F_CPU = "));
Serial.println(F_CPU);
Serial.print(F("Free RAM = ")); // available in Version 1.0 F() bases the string to into Flash, to use less SRAM.
Serial.print(FreeStack(), DEC); // FreeRam() is provided by SdFatUtil.h
Serial.println(F(" Should be a base line of 1017, on ATmega328 when using INTx"));
//Initialize the SdCard.
if(!sd.begin(SD_SEL, SPI_FULL_SPEED)) sd.initErrorHalt();
// depending upon your SdCard environment, SPI_HAVE_SPEED may work better.
if(!sd.chdir("/")) sd.errorHalt("sd.chdir");
//Initialize the MP3 Player Shield
result = MP3player.begin();
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to start MP3 player"));
if( result == 6 ) {
Serial.println(F("Warning: patch file not found, skipping.")); // can be removed for space, if needed.
Serial.println(F("Use the \"d\" command to verify SdCard can be read")); // can be removed for space, if needed.
}
}
#if (0)
// Typically not used by most shields, hence commented out.
Serial.println(F("Applying ADMixer patch."));
if(MP3player.ADMixerLoad("admxster.053") == 0) {
Serial.println(F("Setting ADMixer Volume."));
MP3player.ADMixerVol(-3);
}
#endif
help();
last_ms_char = millis(); // stroke the inter character timeout.
buffer_pos = 0; // start the command string at zero length.
parse_menu('l'); // display the list of files to play
}
//——————————————————————————
/**
* \brief Main Loop the Arduino Chip
*
* This is called at the end of Arduino kernel's main loop before recycling.
* And is where the user's serial input of bytes are read and analyzed by
* parsed_menu.
*
* Additionally, if the means of refilling is not interrupt based then the
* MP3player object is serviced with the availaible function.
*
* \note Actual examples of the libraries public functions are implemented in
* the parse_menu() function.
*/
void loop() {
// Below is only needed if not interrupt driven. Safe to remove if not using.
#if defined(USE_MP3_REFILL_MEANS) \
&& ( (USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer) \
|| (USE_MP3_REFILL_MEANS == USE_MP3_Polled) )
MP3player.available();
#endif
char inByte;
if (Serial.available() > 0) {
inByte = Serial.read();
if ((0x20 <= inByte) && (inByte <= 0x126)) { // strip off non-ASCII, such as CR or LF
if (isDigit(inByte)) { // macro for ((inByte >= '0') && (inByte <= '9'))
// else if it is a number, add it to the string
buffer[buffer_pos++] = inByte;
} else {
// input char is a letter command
buffer_pos = 0;
parse_menu(inByte);
}
buffer[buffer_pos] = 0; // update end of line
last_ms_char = millis(); // stroke the inter character timeout.
}
} else if ((millis() – last_ms_char) > 500 && ( buffer_pos > 0 )) {
// ICT expired and have something
if (buffer_pos == 1) {
// look for single byte (non-number) menu commands
parse_menu(buffer[buffer_pos – 1]);
} else if (buffer_pos > 5) {
// dump if entered command is greater then uint16_t
Serial.println(F("Ignored, Number is Too Big!"));
} else {
// otherwise its a number, scan through files looking for matching index.
int16_t fn_index = atoi(buffer);
SdFile file;
char filename[13];
sd.chdir("/",true);
uint16_t count = 1;
while (file.openNext(sd.vwd(),O_READ))
{
file.getName(filename, sizeof(filename));
if ( isFnMusic(filename) ) {
if (count == fn_index) {
Serial.print(F("Index "));
SerialPrintPaddedNumber(count, 5 );
Serial.print(F(": "));
Serial.println(filename);
Serial.print(F("Playing filename: "));
Serial.println(filename);
int8_t result = MP3player.playMP3(filename);
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to play track"));
}
char title[30]; // buffer to contain the extract the Title from the current filehandles
char artist[30]; // buffer to contain the extract the artist name from the current filehandles
char album[30]; // buffer to contain the extract the album name from the current filehandles
MP3player.trackTitle((char*)&title);
MP3player.trackArtist((char*)&artist);
MP3player.trackAlbum((char*)&album);
//print out the arrays of track information
Serial.write((byte*)&title, 30);
Serial.println();
Serial.print(F("by: "));
Serial.write((byte*)&artist, 30);
Serial.println();
Serial.print(F("Album: "));
Serial.write((byte*)&album, 30);
Serial.println();
break;
}
count++;
}
file.close();
}
}
//reset buffer to start over
buffer_pos = 0;
buffer[buffer_pos] = 0; // delimit
}
delay(100);
}
uint32_t millis_prv;
//——————————————————————————
/**
* \brief Decode the Menu.
*
* Parses through the characters of the users input, executing corresponding
* MP3player library functions and features then displaying a brief menu and
* prompting for next input command.
*/
void parse_menu(byte key_command) {
uint8_t result; // result code from some function as to be tested at later time.
// Note these buffer may be desired to exist globably.
// but do take much space if only needed temporarily, hence they are here.
char title[30]; // buffer to contain the extract the Title from the current filehandles
char artist[30]; // buffer to contain the extract the artist name from the current filehandles
char album[30]; // buffer to contain the extract the album name from the current filehandles
Serial.print(F("Received command: "));
Serial.write(key_command);
Serial.println(F(" "));
//if s, stop the current track
if(key_command == 's') {
Serial.println(F("Stopping"));
MP3player.stopTrack();
//if 1-9, play corresponding track
} else if(key_command >= '1' && key_command <= '9') {
//convert ascii numbers to real numbers
key_command = key_command – 48;
#if USE_MULTIPLE_CARDS
sd.chvol(); // assign desired sdcard's volume.
#endif
//tell the MP3 Shield to play a track
result = MP3player.playTrack(key_command);
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to play track"));
} else {
Serial.println(F("Playing:"));
//we can get track info by using the following functions and arguments
//the functions will extract the requested information, and put it in the array we pass in
MP3player.trackTitle((char*)&title);
MP3player.trackArtist((char*)&artist);
MP3player.trackAlbum((char*)&album);
//print out the arrays of track information
Serial.write((byte*)&title, 30);
Serial.println();
Serial.print(F("by: "));
Serial.write((byte*)&artist, 30);
Serial.println();
Serial.print(F("Album: "));
Serial.write((byte*)&album, 30);
Serial.println();
}
//if +/- to change volume
} else if((key_command == '-') || (key_command == '+')) {
union twobyte mp3_vol; // create key_command existing variable that can be both word and double byte of left and right.
mp3_vol.word = MP3player.getVolume(); // returns a double uint8_t of Left and Right packed into int16_t
if(key_command == '-') { // note dB is negative
// assume equal balance and use byte[1] for math
if(mp3_vol.byte[1] >= 254) { // range check
mp3_vol.byte[1] = 254;
} else {
mp3_vol.byte[1] += 2; // keep it simpler with whole dB's
}
} else {
if(mp3_vol.byte[1] <= 2) { // range check
mp3_vol.byte[1] = 2;
} else {
mp3_vol.byte[1] -= 2;
}
}
// push byte[1] into both left and right assuming equal balance.
MP3player.setVolume(mp3_vol.byte[1], mp3_vol.byte[1]); // commit new volume
Serial.print(F("Volume changed to -"));
Serial.print(mp3_vol.byte[1]>>1, 1);
Serial.println(F("[dB]"));
//if < or > to change Play Speed
} else if((key_command == '>') || (key_command == '<')) {
uint16_t playspeed = MP3player.getPlaySpeed(); // create key_command existing variable
// note playspeed of Zero is equal to ONE, normal speed.
if(key_command == '>') { // note dB is negative
// assume equal balance and use byte[1] for math
if(playspeed >= 254) { // range check
playspeed = 5;
} else {
playspeed += 1; // keep it simpler with whole dB's
}
} else {
if(playspeed == 0) { // range check
playspeed = 0;
} else {
playspeed -= 1;
}
}
MP3player.setPlaySpeed(playspeed); // commit new playspeed
Serial.print(F("playspeed to "));
Serial.println(playspeed, DEC);
/* Alterativly, you could call a track by it's file name by using playMP3(filename);
But you must stick to 8.1 filenames, only 8 characters long, and 3 for the extension */
} else if(key_command == 'f' || key_command == 'F') {
uint32_t offset = 0;
if (key_command == 'F') {
offset = 2000;
}
//create a string with the filename
char trackName[] = "track001.mp3";
#if USE_MULTIPLE_CARDS
sd.chvol(); // assign desired sdcard's volume.
#endif
//tell the MP3 Shield to play that file
result = MP3player.playMP3(trackName, offset);
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to play track"));
}
/* Display the file on the SdCard */
} else if(key_command == 'd') {
if(!MP3player.isPlaying()) {
// prevent root.ls when playing, something locks the dump. but keeps playing.
// yes, I have tried another unique instance with same results.
// something about SdFat and its 500byte cache.
Serial.println(F("Files found (name date time size):"));
sd.ls(LS_R | LS_DATE | LS_SIZE);
} else {
Serial.println(F("Busy Playing Files, try again later."));
}
/* Get and Display the Audio Information */
} else if(key_command == 'i') {
MP3player.getAudioInfo();
} else if(key_command == 'p') {
if( MP3player.getState() == playback) {
MP3player.pauseMusic();
Serial.println(F("Pausing"));
} else if( MP3player.getState() == paused_playback) {
MP3player.resumeMusic();
Serial.println(F("Resuming"));
} else {
Serial.println(F("Not Playing!"));
}
} else if(key_command == 't') {
int8_t teststate = MP3player.enableTestSineWave(126);
if(teststate == -1) {
Serial.println(F("Un-Available while playing music or chip in reset."));
} else if(teststate == 1) {
Serial.println(F("Enabling Test Sine Wave"));
} else if(teststate == 2) {
MP3player.disableTestSineWave();
Serial.println(F("Disabling Test Sine Wave"));
}
} else if(key_command == 'S') {
Serial.println(F("Current State of VS10xx is."));
Serial.print(F("isPlaying() = "));
Serial.println(MP3player.isPlaying());
Serial.print(F("getState() = "));
switch (MP3player.getState()) {
case uninitialized:
Serial.print(F("uninitialized"));
break;
case initialized:
Serial.print(F("initialized"));
break;
case deactivated:
Serial.print(F("deactivated"));
break;
case loading:
Serial.print(F("loading"));
break;
case ready:
Serial.print(F("ready"));
break;
case playback:
Serial.print(F("playback"));
break;
case paused_playback:
Serial.print(F("paused_playback"));
break;
case testing_memory:
Serial.print(F("testing_memory"));
break;
case testing_sinewave:
Serial.print(F("testing_sinewave"));
break;
}
Serial.println();
} else if(key_command == 'b') {
Serial.println(F("Playing Static MIDI file."));
MP3player.SendSingleMIDInote();
Serial.println(F("Ended Static MIDI file."));
#if !defined(__AVR_ATmega32U4__)
} else if(key_command == 'm') {
uint16_t teststate = MP3player.memoryTest();
if(teststate == -1) {
Serial.println(F("Un-Available while playing music or chip in reset."));
} else if(teststate == 2) {
teststate = MP3player.disableTestSineWave();
Serial.println(F("Un-Available while Sine Wave Test"));
} else {
Serial.print(F("Memory Test Results = "));
Serial.println(teststate, HEX);
Serial.println(F("Result should be 0x83FF."));
Serial.println(F("Reset is needed to recover to normal operation"));
}
} else if(key_command == 'e') {
uint8_t earspeaker = MP3player.getEarSpeaker();
if(earspeaker >= 3){
earspeaker = 0;
} else {
earspeaker++;
}
MP3player.setEarSpeaker(earspeaker); // commit new earspeaker
Serial.print(F("earspeaker to "));
Serial.println(earspeaker, DEC);
} else if(key_command == 'r') {
MP3player.resumeMusic(2000);
} else if(key_command == 'R') {
MP3player.stopTrack();
MP3player.vs_init();
Serial.println(F("Reseting VS10xx chip"));
} else if(key_command == 'g') {
int32_t offset_ms = 20000; // Note this is just an example, try your own number.
Serial.print(F("jumping to "));
Serial.print(offset_ms, DEC);
Serial.println(F("[milliseconds]"));
result = MP3player.skipTo(offset_ms);
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to skip track"));
}
} else if(key_command == 'k') {
int32_t offset_ms = -1000; // Note this is just an example, try your own number.
Serial.print(F("moving = "));
Serial.print(offset_ms, DEC);
Serial.println(F("[milliseconds]"));
result = MP3player.skip(offset_ms);
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to skip track"));
}
} else if(key_command == 'O') {
MP3player.end();
Serial.println(F("VS10xx placed into low power reset mode."));
} else if(key_command == 'o') {
MP3player.begin();
Serial.println(F("VS10xx restored from low power reset mode."));
} else if(key_command == 'D') {
uint16_t diff_state = MP3player.getDifferentialOutput();
Serial.print(F("Differential Mode "));
if(diff_state == 0) {
MP3player.setDifferentialOutput(1);
Serial.println(F("Enabled."));
} else {
MP3player.setDifferentialOutput(0);
Serial.println(F("Disabled."));
}
} else if(key_command == 'V') {
MP3player.setVUmeter(1);
Serial.println(F("Use \"No line ending\""));
Serial.print(F("VU meter = "));
Serial.println(MP3player.getVUmeter());
Serial.println(F("Hit Any key to stop."));
while(!Serial.available()) {
union twobyte vu;
vu.word = MP3player.getVUlevel();
Serial.print(F("VU: L = "));
Serial.print(vu.byte[1]);
Serial.print(F(" / R = "));
Serial.print(vu.byte[0]);
Serial.println(" dB");
delay(1000);
}
Serial.read();
MP3player.setVUmeter(0);
Serial.print(F("VU meter = "));
Serial.println(MP3player.getVUmeter());
} else if(key_command == 'T') {
uint16_t TrebleFrequency = MP3player.getTrebleFrequency();
Serial.print(F("Former TrebleFrequency = "));
Serial.println(TrebleFrequency, DEC);
if (TrebleFrequency >= 15000) { // Range is from 0 – 1500Hz
TrebleFrequency = 0;
} else {
TrebleFrequency += 1000;
}
MP3player.setTrebleFrequency(TrebleFrequency);
Serial.print(F("New TrebleFrequency = "));
Serial.println(MP3player.getTrebleFrequency(), DEC);
} else if(key_command == 'E') {
int8_t TrebleAmplitude = MP3player.getTrebleAmplitude();
Serial.print(F("Former TrebleAmplitude = "));
Serial.println(TrebleAmplitude, DEC);
if (TrebleAmplitude >= 7) { // Range is from -8 – 7dB
TrebleAmplitude = -8;
} else {
TrebleAmplitude++;
}
MP3player.setTrebleAmplitude(TrebleAmplitude);
Serial.print(F("New TrebleAmplitude = "));
Serial.println(MP3player.getTrebleAmplitude(), DEC);
} else if(key_command == 'B') {
uint16_t BassFrequency = MP3player.getBassFrequency();
Serial.print(F("Former BassFrequency = "));
Serial.println(BassFrequency, DEC);
if (BassFrequency >= 150) { // Range is from 20hz – 150hz
BassFrequency = 0;
} else {
BassFrequency += 10;
}
MP3player.setBassFrequency(BassFrequency);
Serial.print(F("New BassFrequency = "));
Serial.println(MP3player.getBassFrequency(), DEC);
} else if(key_command == 'C') {
uint16_t BassAmplitude = MP3player.getBassAmplitude();
Serial.print(F("Former BassAmplitude = "));
Serial.println(BassAmplitude, DEC);
if (BassAmplitude >= 15) { // Range is from 0 – 15dB
BassAmplitude = 0;
} else {
BassAmplitude++;
}
MP3player.setBassAmplitude(BassAmplitude);
Serial.print(F("New BassAmplitude = "));
Serial.println(MP3player.getBassAmplitude(), DEC);
} else if(key_command == 'M') {
uint16_t monostate = MP3player.getMonoMode();
Serial.print(F("Mono Mode "));
if(monostate == 0) {
MP3player.setMonoMode(1);
Serial.println(F("Enabled."));
} else {
MP3player.setMonoMode(0);
Serial.println(F("Disabled."));
}
#endif
/* List out music files on the SdCard */
} else if(key_command == 'l') {
if(!MP3player.isPlaying()) {
Serial.println(F("Music Files found :"));
SdFile file;
char filename[13];
sd.chdir("/",true);
uint16_t count = 1;
while (file.openNext(sd.vwd(),O_READ))
{
file.getName(filename, sizeof(filename));
if ( isFnMusic(filename) ) {
SerialPrintPaddedNumber(count, 5 );
Serial.print(F(": "));
Serial.println(filename);
count++;
}
file.close();
}
Serial.println(F("Enter Index of File to play"));
} else {
Serial.println(F("Busy Playing Files, try again later."));
}
} else if(key_command == 'h') {
help();
}
// print prompt after key stroke has been processed.
Serial.print(F("Time since last command: "));
Serial.println((float) (millis() – millis_prv)/1000, 2);
millis_prv = millis();
Serial.print(F("Enter s,1-9,+,-,>,<,f,F,d,i,p,t,S,b"));
#if !defined(__AVR_ATmega32U4__)
Serial.print(F(",m,e,r,R,g,k,O,o,D,V,B,C,T,E,M:"));
#endif
Serial.println(F(",l,h :"));
}
//——————————————————————————
/**
* \brief Print Help Menu.
*
* Prints a full menu of the commands available along with descriptions.
*/
void help() {
Serial.println(F("Arduino SFEMP3Shield Library Example:"));
Serial.println(F(" courtesy of Bill Porter & Michael P. Flaga"));
Serial.println(F("COMMANDS:"));
Serial.println(F(" [1-9] to play a track"));
Serial.println(F(" [f] play track001.mp3 by filename example"));
Serial.println(F(" [F] same as [f] but with initial skip of 2 second"));
Serial.println(F(" [s] to stop playing"));
Serial.println(F(" [d] display directory of SdCard"));
Serial.println(F(" [+ or -] to change volume"));
Serial.println(F(" [> or <] to increment or decrement play speed by 1 factor"));
Serial.println(F(" [i] retrieve current audio information (partial list)"));
Serial.println(F(" [p] to pause."));
Serial.println(F(" [t] to toggle sine wave test"));
Serial.println(F(" [S] Show State of Device."));
Serial.println(F(" [b] Play a MIDI File Beep"));
#if !defined(__AVR_ATmega32U4__)
Serial.println(F(" [e] increment Spatial EarSpeaker, default is 0, wraps after 4"));
Serial.println(F(" [m] perform memory test. reset is needed after to recover."));
Serial.println(F(" [M] Toggle between Mono and Stereo Output."));
Serial.println(F(" [g] Skip to a predetermined offset of ms in current track."));
Serial.println(F(" [k] Skip a predetermined number of ms in current track."));
Serial.println(F(" [r] resumes play from 2s from begin of file"));
Serial.println(F(" [R] Resets and initializes VS10xx chip."));
Serial.println(F(" [O] turns OFF the VS10xx into low power reset."));
Serial.println(F(" [o] turns ON the VS10xx out of low power reset."));
Serial.println(F(" [D] to toggle SM_DIFF between inphase and differential output"));
Serial.println(F(" [V] Enable VU meter Test."));
Serial.println(F(" [B] Increament bass frequency by 10Hz"));
Serial.println(F(" [C] Increament bass amplitude by 1dB"));
Serial.println(F(" [T] Increament treble frequency by 1000Hz"));
Serial.println(F(" [E] Increament treble amplitude by 1dB"));
#endif
Serial.println(F(" [l] Display list of music files"));
Serial.println(F(" [0####] Enter index of file to play, zero pad! e.g. 01-65534"));
Serial.println(F(" [h] this help"));
}
void SerialPrintPaddedNumber(int16_t value, int8_t digits ) {
int currentMax = 10;
for (byte i=1; i<digits; i++){
if (value < currentMax) {
Serial.print("0");
}
currentMax *= 10;
}
Serial.print(value);
}
view raw MP3Shield.ino hosted with ❤ by GitHub

We then moved on to connecting it with the RFID to try getting them to work with each other, at this point we found it difficult to get both codes working with each other, we searched online to find examples in order to help us get the communication we needed. In the end we couldn’t find anything that was similar to our project without it having buttons to help play or stop songs. We looked at the project with buttons and as guidance we used their code to turn the RFID into a button so it would work similarly, we made another void to connect both the RFID and the shield player. We added a bool variable in order to tell if it was playing something we called it runSound, and added it to our mp3 code in the IF statement. That would be triggered in our ReadTag function when the RFID scanner was used, if the card was read and it matched one of the codes it would play the song assigned to it.

/******** RFID&MP3******/
#include <Arduino.h>
#line 1 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
#line 1 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
/**
\file MP3ButtonPlayer2.ino
\brief Example sketch of using the MP3Shield Arduino driver using buttons,
with arduino recommended(simpler) debounce library
\remarks comments are implemented with Doxygen Markdown format
\author Michael P. Flaga
This sketch demonstrates the use of digital input pins used as buttons as
NEXT, PLAY and STOP to control the tracks that are to be played.
Where PLAY or STOP will begin or cancel the stream of track000.mp3 through
track999.mp3, as indexed by NEXT, begining with 0.
\note Use this example uses the bounce2 library to provide debouncing fuctions. Advocated by Arduino's website at http://playground.arduino.cc/code/bounce
*/
// libraries
#include <SPI.h>
#include <SdFat.h>
#include <SFEMP3Shield.h>
#include <SoftwareSerial.h>
SoftwareSerial rSerial(5, 3); // RX, TX
SdFat sd;
SFEMP3Shield MP3player;
int8_t current_track = 0;
const int tagLen = 16;
const int idLen = 13;
const int kTags = 4;
// Put your known tags here!
char knownTags[kTags][idLen] = {
"5500080E8FDC",//Track 0
"550008004A17",//Track 1
"111111111111"
};
char newTag[idLen];
bool runSound = false;
//——————————————————————————
#line 47 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
void setup();
#line 61 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
void loop();
#line 101 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
void readTag();
#line 181 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
int checkTag(char nTag[], char oTag[]);
/#line 47 "C:\\Users\\EOLuser\\AppData\\Local\\Temp\\arduino_modified_sketch_325931\\MP3ButtonPlayer2.ino"
void setup() {
Serial.begin(115200);
rSerial.begin(9600);
if (!sd.begin(9, SPI_HALF_SPEED)) sd.initErrorHalt();
if (!sd.chdir("/")) sd.errorHalt("sd.chdir");
MP3player.begin();
MP3player.setVolume(10, 10);
Serial.println(F("Looking for Buttons to be depressed…"));
}
//——————————————————————————
void loop() {
// Below is only needed if not interrupt driven. Safe to remove if not using.
#if defined(USE_MP3_REFILL_MEANS) \
&& ( (USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer) \
|| (USE_MP3_REFILL_MEANS == USE_MP3_Polled) )
MP3player.available();
#endif
readTag();
if (runSound == true) {
Serial.print(F("B_PLAY pressed, Start Playing Track # "));
Serial.println(current_track);
MP3player.playTrack(current_track);
delay(1000);
runSound = false;
}
}
void readTag() {
// Counter for the newTag array
int i = 0;
// Variable to hold each byte read from the serial buffer
int readByte;
// Flag so we know when a tag is over
boolean tag = false;
// This makes sure the whole tag is in the serial buffer before
// reading, the Arduino can read faster than the ID module can deliver!
if (rSerial.available() == tagLen) {
tag = true;
}
if (tag == true) {
while (rSerial.available()) {
// Take each byte out of the serial buffer, one at a time
readByte = rSerial.read();
/* This will skip the first byte (2, STX, start of text) and the last three,
ASCII 13, CR/carriage return, ASCII 10, LF/linefeed, and ASCII 3, ETX/end of
text, leaving only the unique part of the tag string. It puts the byte into
the first space in the array, then steps ahead one spot */
if (readByte != 2 && readByte != 13 && readByte != 10 && readByte != 3) {
newTag[i] = readByte;
i++;
}
// If we see ASCII 3, ETX, the tag is over
if (readByte == 3) {
tag = false;
}
}
}
// don't do anything if the newTag array is full of zeroes
if (strlen(newTag) == 0) {
return;
}
else {
int total = 0;
for (int ct = 0; ct < kTags; ct++) {
total += checkTag(newTag, knownTags[ct]);
if(total >0){
current_track = ct;
break;
}
}
// If newTag matched any of the tags
// we checked against, total will be 1
if (total > 0) {
runSound = true;
// Put the action of your choice here!
// I'm going to rotate the servo to symbolize unlocking the lockbox
Serial.println("Success!");
}
else {
// This prints out unknown cards so you can add them to your knownTags as needed
Serial.print("Unknown tag! ");
runSound = false;
Serial.print(newTag);
Serial.println();
}
}
// Once newTag has been checked, fill it with zeroes
// to get ready for the next tag read
for (int c = 0; c < idLen; c++) {
newTag[c] = 0;
}
}
int checkTag(char nTag[], char oTag[]) {
for (int i = 0; i < idLen; i++) {
if (nTag[i] != oTag[i]) {
return 0;
}
}
return 1;
}
view raw RFID&MP3.ino hosted with ❤ by GitHub

Phase 3: Adding an interrupt to the code

After getting the RFID and MP3 player working together we wanted to have a way to change songs while other songs were being played. At this point we have a song playing but you would have to wait for it to finish playing and then play the next song, but we wanted users to have the freedom of changing the song in at any point. In order to do this we had to go searching for some kind of code that would let the user change the song, what we found was an interrupt code. I had a hard time trying to figure out how to implement the code I had found into our working code, I tried adding a function that would allow me to interrupt the music playing or at least stop it while the user scanned the next card. After some time working on the interrupt I found that it didn’t want to work along with the rest of the code, so I had to find a way to make it work using the other code I looked out from the samples of the hardware. The mp3 shield player has a line of code as “MP3player.stopTrack();” which allowed me to stop the song when I need it too, I added that line to our RFID code. When a card is scan the song would start playing and if you scan a card again it would stop the song and start whatever song would be assigned to that card, even if it was the same song. In the end we only needed a couple lines of code to get the project working the way we wanted.

/******* Final Project Code *********/
// libraries
#include <SPI.h>
#include <SdFat.h>
#include <SFEMP3Shield.h>
#include <SoftwareSerial.h>
SoftwareSerial rSerial(5, 3); // RX, TX
SdFat sd;
SFEMP3Shield MP3player;
int8_t current_track = 0;
const int tagLen = 16;
const int idLen = 13;
const int kTags = 6;
const byte interruptPin = 10;
volatile byte state = LOW;
// Put your known tags here!
char knownTags[kTags][idLen] = {
"5500080E8FDC",//Track 0
"550008004A17",//Track 1
"6500E7385DE7", //Track 2
"6800901D7E9B", //Track 3
"67009C0DEE18", //Track 4
"111111111111"
};
char newTag[idLen];
bool runSound = false;
//——————————————————————————
int checkTag(char nTag[], char oTag[]);
void setup() {
Serial.begin(115200);
Serial.println(F("Looking for Buttons to be depressed 2 …"));
rSerial.begin(9600);
Serial.println(F("Looking for Buttons to be depressed 3 …"));
if (!sd.begin(9, SPI_HALF_SPEED)) sd.initErrorHalt();
if (!sd.chdir("/")) sd.errorHalt("sd.chdir");
MP3player.begin();
MP3player.setVolume(10, 10);
Serial.println(F("Looking for Buttons to be depressed…"));
pinMode(interruptPin, INPUT_PULLUP);
//attachInterrupt(digitalPinToInterrupt(interruptPin),rfidInterrupt,CHANGE);
}
//——————————————————————————
void loop() {
// Below is only needed if not interrupt driven. Safe to remove if not using.
#if defined(USE_MP3_REFILL_MEANS) \
&& ( (USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer) \
|| (USE_MP3_REFILL_MEANS == USE_MP3_Polled) )
MP3player.available();
#endif
readTag();
if (runSound == true) {
Serial.print(F("B_PLAY pressed, Start Playing Track # "));
Serial.println(current_track);
MP3player.playTrack(current_track);
delay(1000);
Serial.println(F("Looking for Buttons to be depressed 44 …"));
runSound = false;
}
//digitalWrite(rSerial, state);
}
void rfidInterrupt(){
MP3player.stopTrack();
Serial.println(F("Looking for Buttons to be depressed… 22"));
runSound = false;
}
void readTag() {
// Counter for the newTag array
int i = 0;
// Variable to hold each byte read from the serial buffer
int readByte;
// Flag so we know when a tag is over
boolean tag = false;
// This makes sure the whole tag is in the serial buffer before
// reading, the Arduino can read faster than the ID module can deliver!
if (rSerial.available() == tagLen) {
tag = true;
}
if (tag == true) {
while (rSerial.available()) {
// Take each byte out of the serial buffer, one at a time
readByte = rSerial.read();
/* This will skip the first byte (2, STX, start of text) and the last three,
ASCII 13, CR/carriage return, ASCII 10, LF/linefeed, and ASCII 3, ETX/end of
text, leaving only the unique part of the tag string. It puts the byte into
the first space in the array, then steps ahead one spot */
if (readByte != 2 && readByte != 13 && readByte != 10 && readByte != 3) {
newTag[i] = readByte;
i++;
}
// If we see ASCII 3, ETX, the tag is over
if (readByte == 3) {
tag = false;
}
}
}
// don't do anything if the newTag array is full of zeroes
if (strlen(newTag) == 0) {
return;
}
else {
int total = 0;
for (int ct = 0; ct < kTags; ct++) {
total += checkTag(newTag, knownTags[ct]);
if(total >0){
current_track = ct;
break;
}
}
// If newTag matched any of the tags
// we checked against, total will be 1
if (total > 0) {
runSound = true;
MP3player.stopTrack();
// Put the action of your choice here!
// I'm going to rotate the servo to symbolize unlocking the lockbox
Serial.println("Success!");
}
else {
// This prints out unknown cards so you can add them to your knownTags as needed
Serial.print("Unknown tag! ");
runSound = false;
Serial.print(newTag);
Serial.println();
}
}
// Once newTag has been checked, fill it with zeroes
// to get ready for the next tag read
for (int c = 0; c < idLen; c++) {
newTag[c] = 0;
}
}
int checkTag(char nTag[], char oTag[]) {
for (int i = 0; i < idLen; i++) {
if (nTag[i] != oTag[i]) {
return 0;
}
}
return 1;
}

Phase 4: Final project and adding lights

Our final project turned out as best as we can could make it with our limited hardware and knowledge. The overall goal for our project was to make a music box that was easy for anyone to use, originally we wanted to attach songs with objects but due to our time we had we weren’t able to do that. But we ended up having the main goal become a reality, the box is easy to use and people enjoyed being able to change the song at any point. We added a couple of LEDs to the side as an add on with a button you can press to change the color, but in the future I would like to develop them more so they will change on their own depending on the mood of the song. We lazer but the box with finger joints for easy assembly and stained the wood to make it look nice, as well as painting the front where the card slot is with chalk board paint. We added two holes in the back for the power wires and the aux cord that went to the speaker for easy access. In the end we had a working music box that I was proud of presenting and will be using in the future.

//Sarah MacDonald, Monica Chairez, Dureti Ahmed
//INTERACTIVE OBJECT: LED Button Code
//initialize led pins
//green led
int ledPin1 = 5;
//yellow led
int ledPin2 = 4;
//red led
int ledPin3 = 3;
//button
int switchPin = 7;
int count = 0;
boolean lastButton;
boolean currentButton = false;
boolean ledOn = false;
void setup() {
pinMode(switchPin, INPUT);
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
count = 0;
}
boolean debounce(boolean last)
{
boolean current = digitalRead(switchPin);
//change between lights based on button push
if (last != current)
{
delay(5);
current = digitalRead(switchPin);
}
return current;
}
void loop() {
lastButton = currentButton;
currentButton = debounce(lastButton);
if (lastButton == false && currentButton == true)
{
if (count == 0)
{
count++;
//turn on green light
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
}
else if (count == 1)
{
//turn on yellow light
count++;
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
digitalWrite(ledPin3, LOW);
}
else if (count == 2)
{
//turn on red light
count++;
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, HIGH);
}
else if (count == 3)
{
//turn off all lights
count = 0;
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
}
}
}
view raw Lights.ino hosted with ❤ by GitHub

Music Box Schematics

LED light schematics

Photos

We were required to keep the RFID on the breadboard because that was the only way we could make it work, the LED was were soldered to a breakout board.

Video

Featured

Final Project

The Portal Book ends

For my final project I took the design I made in lab 4 and continued to work on it. I modified the project in order to be the size and have an easier way to combine pieces ones fabricated. I added joints to the 90 degree connection in order to make it easier to put it together and added the second layer that would hold the half circle that balances the bookend.

I was able to lazer cut the wood pieces with 1/4 inch thick in order to get the right form that I wanted. I was able to cut all the wood and acrylic for the portal image, then I took 3 hours to 3D print the portal guy in order to have it looking amazing in the end.

After cutting out the pieces and 3d printing I stained the wood a darker color, painted the acrylic the appropriate color of each portal and then glued everything together. I super glued the 3d pieces to the wood and it help everything together pretty well.

The final product came out better than I had expected and they turned out looking better than I expected. I was able to put them to the test and it worked with holding more than 15 albums together. The sizing was perfect and it looked great after I had stained the wood and added the painted acrylic. Now it sits on my shelf holding all of my Kpop albums together.

Live Stream presentation

My live personal live stream started out kind of laggy, the computer I was using didn’t work with me to stream. I was unable to stream without lag and it was hard for the viewers to actually keep up. 

For the next couple of weeks I was unable to live stream after talking with Ian and Harrison I got good advice on getting a streaming box that I can connect to the Xbox I have and my surface. Until it arrived I was unable to stream but I did work on overlays and what I wanted to be my branding. 

For branding I decided to go with things I liked and that made it feel like me, I wanted to combine two different things so I decided to combine Halo and my favorite colors. I took lines that were similar to the helmet hud of chief and then combined purple and blue. I also liked the gradient look so I combined that. I wanted to keep my face concealed so I wore a mask which also goes along with my streaming name Stealth, I added that to my logo sign as well in the shape of a hooded figure. This makes my branding feel more like me and gives me better confidence to be on stream. 

Once I was able to get my streaming box I began streaming from my Xbox and I believe it went very well, although I didn’t get many views I still had a friend that joined in and made streaming enjoyable. I also have a bad anxiety when it comes to being on camera so having someone there was really great to continue live streaming. Although I usually had my camera stream dark in order to get a better environment with the games I think it still went well having the interaction. 

At the end of this class I learned a lot about streaming and what it takes to stream, I knew nothing other than watching streams so from going from that to being on a stream was a major jump for me. Although I had to figure out how to stream in a shared room and with minimum gear I think it went pretty successful.    

Group Live Stream Week 4:

This was the last week we did the live stream for class and it was one of the funnest ones I believe, after the first mach we just ended up hanging out and playing for rounds. Although it was the last stream for class it I think some of us will still be playing on the map and hunger games since its so well done and we can get great content from it. I heard that more maps are going to be made and even more mini games will be implemented, so that should give us more to do on the server. Overall I think my stream went well I didn’t even notice that I had streamed 2hrs, thats how fluently it went. I believe those are the best streams, I’m looking forward to playing more with this group.

Group Live Stream Week 3:

For week 3 of our group live stream we are continuing our Hunger Games in Minecraft and its actually going very well, its a lot of fun and we get great content. The things we talked about last week were implemented into the changes of the map like the parkour and the new lobby for hunger games. It looks really nice and more interesting, we also have a lot more people playing not just us but those that watch the stream come in and play. I think our dynamics on the group stream are working really well and I cant wait for next weeks stream.

Group Live Stream Week 2:

This week’s stream went really well, it was fun and entertaining. Map was good and the additions that were added worked really well, it gave enough content to keep stuff going. Like the added mini games was good and the parkour in the lobby worked out well. Personally I think I need to work on adding music during the stream when we are not all talking together, because during that time it’s just silence except when I talk. I was able to set up OBS better for streaming and my setup is working better, sadly I don’t have a camera for that computer but it still works out well. 

Work on for next week:

Test sound at beginning of stream because last time it was too quiet.

Group Live Stream Week 1:

For the group live stream we will be doing Hunger Games in Minecraft while we have Erik being the broadcaster for the entire game. Everyone will be individually live streaming but Erik will have everyone’s stream in one place in order to make commentary but we will also be able to spectate once we die in game. We scheduled to go live around 8-8:15pm on Wednesday and play about an hour with everyone, possibly doing a couple of rounds of the Hunger games.  

After live streaming week 1 with the group I think the game went very well. It was fun and entertaining. Although there were some aspects that needed to be updated on the map my biggest concern was my own stream. I realized I needed get my obs a little more set up since it was my first time using discord on stream I wasn’t sure how to set it up and it made a mess, I was also using Stream Labs and although it works well with my Xbox stream I think I’m going to switch back to OBS for the Minecraft streams. Although the stream went well I need to set up my OBS for next week a little better and get it running so that I can mute discord and talk to the stream at times. 

Things to fix for next week:

    Switch to OBS

    Set up discord so it can be muted 

    Test stream discord to see if it works out better 

Individual Live Stream: Week 11

Genesis Noir

This week I continued to play Genesis Noir and it’s going very well. I get good feedback from chat on what’s going on in the game and it’s actually fun. The stream is running smoothly so far and I’m really happy with it, although I want to work on adding maybe other widgets that will give me more interaction or incentives. But other than that I’m just continuing playing the game. 

I also know that we’re starting to wrap up the semester so I was unsure if I wanted to continue streaming but I actually ended up liking it and starting to feel comfortable with it. So I will at least finish Genesis Noir and then from there maybe stream on and off during the summer. But I would like to continue streaming with the group. At least those days are really fun.  

Individual Live Stream: Week 10

Genesis Noir 

This week I have found a new game that looks really interesting and it was free on Xbox. Genesis Noir was a game I stumbled upon while reading through a couple of gaming sites, it looked interesting and I read the description which got me hooked on it. I thought it was a good game to play on stream since it was a little long but it was a puzzle mystery game so its good for interacting with the chat.  Everything else is working for me so I will just be changing the game I’m playing and make it to a series on twitch. 

Individual Live Stream: Week 9

Unraveled
This week I decided to go with a much more feel good game since Little Nightmares was a little more horror, I decided to play Unraveled. Although it is a good game I don’t think I will continue playing it because it doesn’t give the exciting vibe to streaming. It doesn’t give me the excitement of being engaged on stream, I need a game that will make me more talkative while playing. The layout did work for me, using stream labs was a better idea because I can use the widgets that will help me engage more with my stream. Although I can’t get the premium edition, what I am using works for me. 

Individual Live Stream: Week 8

Little Nightmares Finally 

This week I was back to streaming and I was actually excited to get to finish little nightmares. After learning about Stream Labs and all the widgets you can use I decided to add the chat into the actual live stream. I think it made the stream more interactive since now I can actually keep the messages from chat and anyone else watching can see as well. This week we had interactions happen on stream which was good and I was able to finish up the game as well. It was a good conclusion to the game since both me and the chat were confused about that ending, but this week was fun to learn how to use stream labs. I did have some issues with the sound at the beginning but then I figured it out and was able to start streaming. Was honestly one of my favorite game to play.