ECE 4180 2 Player Quiz (mbed trivia)
By Joyita Roy, Raish Wadhwaniya, Christopher Ray
Overview
This project implements a two player trivia game with mbeds connected using GPIO pins . 1 mbed is the master/"trivia host" and the other 2 connected to it are the players. Each trivia question is multiple choice with 4 answer options. Answering a questions correctly adds 1 point, and a wrong answer subtracts 1 point.
Along with 3 mbeds, we used the Adafruit Bluefruit LE UART Friend, Adafruit VL530X LIDAR sensor, RGB LED, and a speaker with PWM output.
After you familiarize yourself with the components, you'll be well on your way to building the trivia game shown in the video below! All you have to do is connect your parts up as directed by the Pin Connections segment, import the ECE4180_master and ECE4180_player program into your compiler workspace, and then put the master program onto the master mbed and player program into both the player mbeds!
When your circuit is assembled and your code is on the mbed, then you should be good to go. Hit the Reset button on your 3 mbeds to start the game. Download the Bluefruit app for the bluetooth module. Connect 1 player mbed at a time to the bluetooth. A blue "Conn" light should light up once you are connected. You may begin the game as the first question is printed. Hover your hand close to the lidar if you are ready to answer the question (like a buzzer) and then respond to the question using your Bluefruit app. Score will be tallied after every question and the winner will be declared at the end!
Video Demo
Components
- mbed LPC1768 x3
- Adafruit Bluefruit LE UART Friend x2
- RGB LED
- Adafruit VL530X LIDAR sensor x2
- Speaker
Pin Connections
Adafruit Bluefruit LE UART Friend:
Player mbeds | Adafruit BLE |
---|---|
gnd | gnd |
VU(5v) | Vin(3.3-16V) |
nc | RTC |
p13 (Serial RC) | TXO |
p14 (Serial TX) | RXI |
RGB LED:
- connect to master mbed p24 (red) and p25 (green). Code for blue light is commented out in master program
Adafruit VL530X LIDAR sensor:
Player mbeds | VL53L0X |
---|---|
3.3V | VIN |
GND | GND |
p28 | SDA |
p27 | SCL |
p26 | SHDN |
Speaker:
- resistor connected to master mbed PWM Out pin p26
Code
Import programECE4180_Project_Master
4180 Project Master Code
main.cpp
#include "mbed.h" #include "uLCD_4DGL.h" #include "questions.h" DigitalOut myled1(LED1); // leds for debugging DigitalOut myled2(LED2); DigitalOut myled3(LED3); DigitalOut myled4(LED4); DigitalOut lidar_enable(p29); //to determine when lidar should operate DigitalIn p1_enable(p23); // data from player 1 BusIn p1_ans(p22, p21); DigitalIn p2_enable(p18); // data from player 2 BusIn p2_ans(p19, p20); uLCD_4DGL uLCD(p13, p14, p12); Serial pc(USBTX,USBRX); // for teraterm debugging PwmOut speaker(p26); int msg; int msg2; int questionIndex = 0; string *p; int player = 0; int player1Score = 0; int player2Score = 0; int p1Val = 0; int p2Val = 0; questions arr[30]; // Light class RGBLed { public: RGBLed(PinName redpin, PinName greenpin)://, PinName bluepin); _redpin(redpin), _greenpin(greenpin) //, _bluepin(bluepin) { //50Hz PWM clock default a bit too low, go to 2000Hz (less flicker) _redpin.period(0.0005); } void write(float red,float green)//, float blue); { _redpin = red; _greenpin = green; // _bluepin = blue; } private: PwmOut _redpin; PwmOut _greenpin; // PwmOut _bluepin; }; //class could be moved to include file //Setup RGB led using PWM pins and class RGBLed myRGBled(p24,p25);//,p21); //RGB PWM pins void shuffleQuestions() { for (int i = 0; i < 90; i++) { int rand1 = rand() % 30; int rand2 = rand() % 30; questions temp = arr[rand1]; arr[rand1] = arr[rand2]; arr[rand2] = temp; } } void addQuestions() { questions q1("Which of these\nchess figures is\nclosely related to'Bohemian\nRhapsody?\n","King","Queen","Pawn","Bishop","Queen"); questions q2("What religion is\nthe most practicedone in India?\n","Sikhism","Islam","Hinduism","Shinto","Hinduism"); questions q3("What is the name\nof the Jewish New\nYear?\n","Yom Kippur","Kwanzaa","Hanukkah","Rosh Hashanah","Rosh Hashanah"); questions q4("What funk/soul\nband was Lionel\nRichie a member\nof?\n","Commodores","Amigas","Ataris","Spectrums","Commodores"); questions q5("Which country\nhosted the Summer\nOlympics in 2016?\n","Greece","Brazil","China","Spain","Brazil"); questions q6("Which of these\ncities is closest\nto London, UK?\n","Boston, MA","Miami, FL","Atlanta, GA","New York, NY","Boston, MA"); questions q7("What did Alfred\nNobel Develop?\n","Atomic bomb","Nobelium","Gunpowder","Dynamite","Dynamite"); questions q8("Which US Presidentis on the far leftof the Mount\nRushmore\nNational\nMemorial?\n","Theodore\n Roosevelt","Thomas\n Jefferson","George\n Washington","Abraham\n Lincoln","George\n Washington"); questions q9("Which actress\nplays a major\nrole in the TV\nshow 'The Big\nBang Theory'\n","Portia de\n Rossi","Kaley Cuoco","Emily\n Deschanel","Sofia Vergara","Kaley Cuoco"); questions q10("Which of these\nantagonist\ncharacters was\ncreated by\nnovelist J.K.\nRowling?\n","Professor\n Moriarty","Lord Voldemort","Darth Vader","Lord Farqaad","Lord Voldemort"); questions q11("Which mammal firstreached Earth's\norbit alive?\n","Monkey","Human","Cat","Dog","Dog"); questions q12("How many spaces\nare on a standard\nmonopoly board?\n","40","20","80","60","40"); questions q13("Which actor does\nnot appear in\n'Saving Private\nRyan'?\n","Tom Hanks","Vin Diesel","Giovanni\n Ribisi","Ralph Fiennes","Ralph Fiennes"); questions q14("Which city's\nlandmard include:\nThe Pantheon, The\nSpanish Steps and\nTrevi Fountain?\n","Rome","Athens","Istanbul","Barcelone","Rome"); questions q15("How many blue\nstripes does the\nUnited States of\nAmerica national\nflag have?\n","13","6","0","7","0"); questions q16("Which of these\ncountries was not\na Soviet Republic\nin USSR?\n","Moldova","Serbia","Kyrgyzstan","Azerbaijan","Serbia"); questions q17("What temperature\nis the same in\nCelsius and\nFahrenheit?\n","0","-40","+100","+40","-40"); questions q18("What is the name\nof the boxer whoselife story is\ndepicted in the\n1999 movie 'The\nHurricane'?\n","Rubin Carter","Jake LaMotta","Muhammad Ali","Rocky Marciano","Rubin Carter"); questions q19("Adele performed\nthe theme song to\nwhich James Bond\nfilm?\n","Casino Royale","From Russia\n With Love","Quantum of\n Solace","Skyfall","Skyfall"); questions q20("What restaurant\nfranchise advises\nyou to 'Eat\nFresh'?\n","Subway","McDonald's","KFC","Taco Bell","Subway"); questions q21("In which language\nwas the book 'War\nand Peace' originally written?\n", "Russian","English","French","German","Russian"); questions q22("Which movie was\nthe first to win\n11 Academy\nAwards?\n","Sound of Music","La La Land","Ben-Hur","Titanic","Ben-Hur"); questions q23("What is the\nlargest country,\nby area, that has\nonly one time\nzone?\n", "China","Russia","Australia","Turkey","China"); questions q24("Which truck is\nproduced by the\nFord Motor\nCompany?\n", "Silverado 1500","CR-V","F-150","RAV4","F-150"); questions q25("What is the\nlargest planet in our Solar System?\n","Pluto","Earth","Saturn","Jupiter","Jupiter"); questions q26("Other than eggs,\nwhat is a primary\ningredient in\nEggs Florentine?\n", "Avocado","Gorgonzola","Spinach","Ham","Spinach"); questions q27("According to\nPersian folklore,\nwho is the\nstoryteller of\n'One Thousand and\nOne Nights'?\n","Kanaan","Hatshepsut","Homer","Scheherazade","Scheherazade"); questions q28("Which of these\nNBA franchises\nhas never signed\nLeBron James?\n", "Miami Heat","Los Angeles\n Lakers","Cleveland\n Cavaliers","Boston Celtics","Boston Celtics"); questions q29("What is the color\nof Donald Duck's\nbowtie?\n","Yellow","Green","Red","Blue","Red"); questions q30("What was the\nfirst successful\nvaccine developed\nin history?\n","Smallpox","Rabies","Cholera","Scarlet Fever","Smallpox"); arr[0] = q1; arr[1] = q2; arr[2] = q3; arr[3] = q4; arr[4] = q5; arr[5] = q6; arr[6] = q7; arr[7] = q8; arr[8] = q9; arr[9] = q10; arr[10] = q11; arr[11] = q12; arr[12] = q13; arr[13] = q14; arr[14] = q15; arr[15] = q16; arr[16] = q17; arr[17] = q18; arr[18] = q19; arr[19] = q20; arr[20] = q21; arr[21] = q22; arr[22] = q23; arr[23] = q24; arr[24] = q25; arr[25] = q26; arr[26] = q27; arr[27] = q28; arr[28] = q29; arr[29] = q30; } void readQuestion() { arr[questionIndex].shuffleOptions(); //uLCD.cls(); uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf(arr[questionIndex].getQuestion().c_str()); p = arr[questionIndex].getAllOptions(); uLCD.printf("\n1: "); uLCD.printf((*(p)).c_str()); uLCD.printf("\n2: "); uLCD.printf((*(p+1)).c_str()); uLCD.printf("\n3: "); uLCD.printf((*(p+2)).c_str()); uLCD.printf("\n4: "); uLCD.printf((*(p+3)).c_str()); } int main() { uLCD.baudrate(3000000); // lcd settings + randomize questions srand(time(NULL)); addQuestions(); shuffleQuestions(); uLCD.display_control(PORTRAIT); while(1) { if (questionIndex == 30) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); //game over + win screen uLCD.locate(0,0); uLCD.printf("The game is over;"); wait(2); uLCD.locate(0,2); uLCD.printf("Player 1: %d", player1Score); uLCD.locate(0,4); uLCD.printf("Player 2: %d", player2Score); wait(3); // gameover.... uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(1,6); if (player1Score > player2Score) { uLCD.printf("PLAYER 1 WINS!!!"); } else if (player1Score < player2Score) { uLCD.printf("PLAYER 2 WINS!!!"); } else { uLCD.locate(3,6); uLCD.printf("IT'S A TIE!!!"); } } else { readQuestion(); //print questions lidar_enable = 1; // tell players that lidar can now work as buzzer } while ((!p1Val)&&(!p2Val)) { msg = -1; msg2 = -1; if (p1_enable) { //if player 1 is ready p1Val = p1_enable; myled1 = !myled1; msg = (p1_ans + 1); //answer from player mbeds + 1 to make it numbers between 1-4 while (msg < 1); //checking if answer is right if (msg == 1) { if ((*(p)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score++; p1Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score--; p1Val = 1; break; } } else if (msg == 2) { if ((*(p+1)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0);// 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score++; p1Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score--; p1Val = 1; break; } } else if (msg == 3) { if ((*(p+2)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score++; p1Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score--; p1Val = 1; break; } } else if (msg == 4) { if ((*(p+3)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score++; p1Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player1Score--; p1Val = 1; break; } } } else if (p2_enable) { p2Val = p2_enable; myled2 = !myled2; msg2 = (p2_ans + 1); while (msg2 < 1); if (msg2 == 1) { if ((*(p)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); player2Score++; myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; p2Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score--; p2Val = 1; break; } } else if (msg2 == 2) { if ((*(p+1)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score++; p2Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score--; p2Val = 1; break; } } else if (msg2 == 3) { if ((*(p+2)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score++; p2Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score--; p2Val = 1; break; } } else if (msg2 == 4) { if ((*(p+3)).compare(arr[questionIndex].getCorrectAnswer()) == 0) { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Correct"); myRGBled.write(0.0,1.0); speaker.period(1.0/1000.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score++; p2Val = 1; break; } else { uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Incorrect"); myRGBled.write(1.0,0.0); speaker.period(1.0/500.0); // 500hz period speaker =0.5; wait(1); speaker =0.0; player2Score--; p2Val = 1; break; } } } } //reset all values wait(3); p1Val = 0; p2Val = 0; myled1 = 0; myled2 = 0; msg = -1; msg2 = -1; lidar_enable = 0; myRGBled.write(0.0,0.0); uLCD.filled_rectangle(0, 0, 130, 130, BLACK); uLCD.locate(0,0); uLCD.printf("Player 1: %d", player1Score); uLCD.locate(0,2); uLCD.printf("Player 2: %d", player2Score); wait(2); uLCD.filled_rectangle(0, 0, 130, 130, BLACK); questionIndex++; } }
Import programECE4180_Project_player1
ECE 4180 Project Player Code
main.cpp
#include "mbed.h" #include "XNucleo53L0A1.h" #include <stdio.h> DigitalOut enable(p18); BusOut answer(p19,p20); BusOut myleds(LED1, LED2, LED3, LED4); DigitalOut myled1(LED1); DigitalOut myled2(LED2); DigitalOut myled3(LED3); DigitalOut myled4(LED4); DigitalIn lidar_enable(p9); // READING DATA BETWEEN MBEDS DigitalIn other_player(p15); DigitalOut my_player(p16); Serial blue(p13, p14); // tx, rx Serial pc(USBTX,USBRX); DigitalOut shdn(p26); // This VL53L0X board test application performs a range measurement in polling mode // Use 3.3(Vout) for Vin, p28 for SDA, p27 for SCL, P26 for shdn on mbed LPC1768 //I2C sensor pins #define VL53L0_I2C_SDA p28 #define VL53L0_I2C_SCL p27 static XNucleo53L0A1 *board=NULL; int msg = -1; char bnum = 0; //button number variable char bhit = 0; void bluetooth() //function that is called after lidar distance <70 to get bluetooth inputs { while(1) { pc.printf("Start bluetooth |"); while (blue.readable()) { blue.getc(); } if (blue.getc()=='!') { if (blue.getc()=='B') { //button data bnum = blue.getc(); //button number bhit = blue.getc(); //1=hit, 0=release if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { blue.getc(); while (blue.readable()) { blue.getc(); } switch (bnum) { case '1': //number button 1 if (bhit=='1') { msg = 1; myled1 = 1; } else { msg = 0; myled1 = 1; } break; case '2': //number button 2 if (bhit=='1') { msg = 2; myled2 = 1; } else { msg = 0; myled2 = 1; } break; case '3': //number button 3 if (bhit=='1') { msg = 3; myled3 = 1; } else { msg = 0; myled3 = 1; } break; case '4': //number button 4 if (bhit=='1') { msg = 4; myled4 = 1; } else { msg = 0; myled4 = 1; } break; default: break; } //device.putc(msg); return; } } } //device.putc(msg); wait(1); } } int main() { int status; uint32_t distance; DevI2C *device_i2c = new DevI2C(VL53L0_I2C_SDA, VL53L0_I2C_SCL); /* creates the 53L0A1 expansion board singleton obj */ board = XNucleo53L0A1::instance(device_i2c, A2, D8, D2); shdn = 0; //must reset sensor for an mbed reset to work wait(0.1); shdn = 1; wait(0.1); /* init the 53L0A1 board with default values */ status = board->init_board(); while (status) { pc.printf("Failed to init board! \r\n"); status = board->init_board(); } //loop taking and printing distance while (1) { msg = 0; status = board->sensor_centre->get_distance(&distance); if (status == VL53L0X_ERROR_NONE) { if (distance < 70) { // once master mbed as already printed the question if (lidar_enable){ my_player = 1; if (!other_player) { //if the other player has not pressed buzzer yet myleds = 15; // all leds on player mbed light up using BUSOUT wait(0.5); myleds = 0; bluetooth(); if (msg > 0 && msg < 5) { answer = msg - 1;//send answer to master enable = 1; //let master mbed know youre ready wait(1); } } } } else { //reset values msg = -1; enable = 0; myleds = 0; my_player = 0; } } } }
Presentation
Please log in to post comments.