JUKEBOT! (jukebox With RFID Scan, Speakers, Leds and Arduino)

Introduction: JUKEBOT! (jukebox With RFID Scan, Speakers, Leds and Arduino)

About: Hi! I'm a 20 year old girl studying game design at HKU. welcome to my instructables!

For a schoolproject about arduino, we had to create an interactive system using arduino. After failing an overambitious project, I decided to lower the bar a bit and create the "JUKEBOT!".

So what is the "JUKEBOT!"? Well, I'm glad you asked.

The "JUKEBOT!" is basically a jukebox. You pick a card depending on what kind of music you are in the mood for and "JUKEBOT!" will start playing a "song" based on the card you picked. It's eyes will also light up red, green, blue or all 3 colours, depending on the genre you picked.

To be able to play the songs I had to program them as well, so this is also a tutorial on how to create bitmusic with Arduino.

This code includes the next songs:


-Never gonna give you up

-Megalovenia

-My heart will go on

-Party anthem

-Careless whisper

-Get Lucky

-Mary has a little lamb

Supplies:

So what do we need for the "JUKEBOT!"?

Technical materials:

* Arduino uno

* RFID KIT MFRC522 S50 Mifare

* 6 RFID cards

* 2 small 5v speakers

* 2 red, blue and green led lights

* 3 resistors

* wires

The box:

*Plastic box

*Fat straws

*2 plastic milkshake cups

Building materials:

* Soldering iron

* Tin(for soldering)

* Something to cut holes in a box, I used a knife but I don't recommend it

* Tape

* Glue

optional: A powerbank so you can take your "JUKEBOT" anywhere with you!

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: The Wiring

So let's start with the wiring. To make my code work you need to copy the pins from the picture, however the pins from the speakers and the leds could be changed if you also change the code. However I don't recommend changing the pins from the RFID scanner because it is SPI it needs the SPI pins. which are the pins it's using.

For my RFID scanner i connected:

SDA - 10

SCK - 13

MOSI - 11

MISO - 12

GND - GND

RST - 9

3.3V - 3.3V

For my leds i connected the 2 of each colour to eachother with a resistor before the +. I connected the - of the last led to the GND and the + side to:

Red - 2

Blue - 3

Green - 4

With the speakers I put the - and + sides together and I put the - in the GND and + to the 6th pin.

Step 2: Setting Up the RFID Scanner

To make all of this work we need the RFID scanner to work. So let's get started on the programming.

Before I could start coding my cards, I needed to read the card ID's.

I actually found code online (https://github.com/BasOnTech/Arduino-Beginners-NL/... ) to read RFID cards. I used it to read my cards and as a basis for my jukebot code.

The code to read RFID cards is this:

_____________________________________________________________________________

#include // SPI bibliotheek
#include
// MFRC522 bibliotheek

const int pinRST = 9; // Reset pin const int pinSS = 10; // Serial data pin

MFRC522 mfrc522(pinSS, pinRST); // Instance MFRC522 op pinSS en pinRST

//Read the card ID void getCardID() {

// If no card is found and no card data is being read // PICC = Proximity Integrated Circuit Card if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {

String cardIdRead = "";

for (byte i = 0; i < mfrc522.uid.size; i++) { cardIdRead.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "")); cardIdRead.concat(String(mfrc522.uid.uidByte[i], HEX)); }

cardIdRead.toUpperCase();

Serial.print("Read card ID: "); Serial.println(cardIdRead);

Serial.println("");

// Stop reading mfrc522.PICC_HaltA(); } }

void setup() { Serial.begin(9600);

SPI.begin(); mfrc522.PCD_Init();

// Print MFRC522 Card Reader details to serial monitor mfrc522.PCD_DumpVersionToSerial();

Serial.println("Scan card..."); }

void loop() { getCardID(); }

___________________________________________________________________

What you have to do:

1. Copy paste the code above into the arduino program

2. Connect your RFID to your arduino

3. When you have uploaded the code, open the serial monitor.

4. scan your cards

5. copy the shown card idea for later...

Step 3: Making Things Happen by Scanning Your Card

So now I will give you the code I made to make a beep happen after scanning your card.

_____________________________________________________________________

#include // needed SPI library
#include
// needed MFRC522 library

const int pinRST = 9; // Reset pin const int pinSS = 10; // Serial data pin

const int card1 = "6A165383"; // This is where you put the number you had to remember

MFRC522 mfrc522(pinSS, pinRST); // Instantce MFRC522 on pinSS and pinRST

// Read card ID void getCardID() {

// If no card is found and no card data is read // PICC = Proximity Integrated Circuit Card if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {

String cardIdRead = "";

for (byte i = 0; i < mfrc522.uid.size; i++) { // cardID[i] = mfrc522.uid.uidByte[i]; cardIdRead.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "")); cardIdRead.concat(String(mfrc522.uid.uidByte[i], HEX)); }

cardIdRead.toUpperCase();

Serial.print("Read card ID: "); Serial.println(cardIdRead);

// when cardID is accepted if (cardIdRead == card1) { tone(6, 700, 100); //to let you know you scanned a card

Serial.println("Card1"); }

Serial.println("");

// Stop reading mfrc522.PICC_HaltA(); } }

void setup() { Serial.begin(9600);

SPI.begin(); mfrc522.PCD_Init(); // Initialise the MFRC522 reader

// Print MFRC522 Card Reader details to serial monitor mfrc522.PCD_DumpVersionToSerial();

Serial.println("Scan card..."); }

void loop() { getCardID(); }

_______________________________________________________________________

Step 4: Making Bit Music

So here's where the fun happens... Because I couldn't use and SD card reader, I had to come up with another way to play music. Luckily the arduino is capable of making music too! I found a very usefull things on how to create music with Arduino. So this is the code I found and adjusted.

_____________________________________________________________________________

// Pin to which pin the speaker is connected
#define speakerPin 6

// Tempo #define bpm 120

// Gap between notes. This is expressed as percentage of time between 2 beats. #define noteGapPercentage 10

uint8_t Lucky[][2] = { {54,2}, {53,8},{54,8},{58,2},{58,8},{60,8},{61,2},{61,8},{63,8},{60,2},{0,8}, {53,8}, {54,2}, {53,8},{54,8},{58,2},{58,8},{60,8},{61,2},{58,8},{65,8},{63,2}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {53,16},{53,8},{53,8},{53,8},{51,16},{53,8},{56,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {53,16},{53,8},{53,8},{53,8},{51,16},{53,8},{56,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, };

// Time between two beats in microseconds (equal to length of a quarter note) #define beatDuration (60.0 / bpm) * 1000000L

// Time of the gap between two notes in microseconds #define noteGap beatDuration * (noteGapPercentage / 100.0)

void setup() { // Set the speakerPin as an output pinMode(speakerPin, OUTPUT);

// Iterate over the notes array for(int i = 0; i < (sizeof(lucky) / sizeof(*lucky)); i++) { // pass the key number and note type playNote(lucky[i][0], lucky[i][1]); } }

/* * Plays an individual note. * * keyNumber - The key number (1 - 88) * noteType - The note type (1, 2, 4, 8, etc.) */ void playNote(uint8_t keyNumber, uint8_t noteType) { long halfPeriod = getPeriodForKey(keyNumber) / 2; long noteDuration = beatDuration * (4.0 / noteType); long elapsed = 0;

// While we have a note to play while(halfPeriod > 0 && elapsed < (noteDuration - noteGap)) { // Set speakerPin high for half of the period digitalWrite(speakerPin, HIGH); wait(halfPeriod);

// Set speakerPin low for half of the period digitalWrite(speakerPin, LOW); wait(halfPeriod);

// Update the amount of time that has elapsed elapsed += halfPeriod * 2; }

/* * Gap between notes. Calculated using 'elapsed' to minimise timing errors * and ensure that the correct gap occurs whenever getPeriodForKey() returns * zero. */ wait(noteDuration - elapsed); }

/* * Returns the period for a key or zero for key numbers outside the range of 1 - * 88. * * keyNumber - The key number (1 - 88) */ long getPeriodForKey(uint8_t keyNumber) { // If the key is between 1 and 88 if(keyNumber >= 1 && keyNumber <= 88) { // Return the period (one second divided by the frequency of the key) return 1000000L / (pow(2.0, (keyNumber - 49.0) / 12.0) * 440.0); }

// Otherwise return zero return 0; }

void wait(long us) { // First delay for the number of whole milliseconds using delay() delay(us / 1000); // Then delay for the remainder of microseconds using delayMicroseconds() delayMicroseconds(us % 1000); }

void loop() {

}

_________________________________________________________________________________

So this all looks quite complicated, but all you need to know is how to make the music.

uint8_t rickroll[][2] = {
{52,16}, {54,16}, {57,16}, {54,16},{61,6},{61,6},{59,8},{0,8}, {52,16}, {54,16}, {57,16}, {54,16},{59,6},{59,6},{57,6},{0,8}, {52,16}, {54,16}, {57,16}, {54,16},{57,6},{59,6},{57,6},{54,6},{52,8},{54,8},{59,6},{57,4},{0,5},

{52,16}, {54,16}, {57,16}, {54,16},{61,6},{61,6},{59,8},{0,8}, {52,16}, {54,16}, {57,16}, {54,16},{64,6},{59,6},{57,6},{56,16},{54,8}, {52,16}, {54,16}, {57,16}, {54,16},{57,6},{59,6},{57,6},{54,6},{52,8},{54,8},{59,6},{57,6}, };

This is the part where you need to make changes if you want to create your own songs. one note looks like this: {54,8};

If you want an empty note you put 0: {0,8};

The first number stands for the keynumber of a piano. (I had to use a picture of a piano with all 88 numbers to figure out what numbers i had to put in.) The lower the number the lower the note.

The second numbers stand for the toneduration. It takes some practice to perfect the duration of the notes. The lower the number the longer the note.


I took some piano sheets, read the notes using a cheatsheet because I couldn't read notes(now I can), translated them to the code, listened to the songs over and over again to perfect the timing, and repeat.

Step 5: Putting It All Together

Now we have this beautiful code, we need to put it all together! I didn't include seperate steps about the lights and speakers because they are pretty easy to put in. So this is my code in it's full glory:

______________________________________________________________________

#include

// Pin to which an 8 Ohm speaker is connected (use a 150 - 220 Ohm resistor) #define speakerPin 6

// Tempo (beats per minute) #define bpm 120

// Gap between notes. This is expressed as percentage of time between 2 beats. #define noteGapPercentage 10

//the songs uint8_t marylittlelamb[][2] = { {35,4}, {35,4}, {42,4}, {42,4}, {44,4}, {44,4}, {42,2}, {40,4}, {40,4}, {39,4}, {39,4}, {37,4}, {37,4}, {35,2}, {42,4}, {42,4}, {40,4}, {40,4}, {39,4}, {39,4}, {37,2}, {42,4}, {42,4}, {40,4}, {40,4}, {39,4}, {39,4}, {37,2}, {35,4}, {35,4}, {42,4}, {42,4}, {44,4}, {44,4}, {42,2}, {40,4}, {40,4}, {39,4}, {39,4}, {37,4}, {37,4}, {35,2} };

uint8_t megalovenia[][2] = { {18,16}, {18,16}, {30,8}, {25,8},{0,16}, {25,8}, {23,8}, {21,8}, {18,16}, {21,16}, {23,16}, {16,16}, {16,16}, {30,8}, {25,8},{0,16}, {25,8}, {23,8}, {21,8}, {18,16}, {21,16}, {23,16}, {16,16}, {16,16}, {30,8}, {25,8},{0,16}, {25,8}, {23,8}, {21,8}, {18,16}, {21,16}, {23,16}, {16,16}, {16,16}, {30,8}, {25,8},{0,16}, {25,8}, {23,8}, {21,8}, {18,16}, {21,16}, {23,16}, {45,8}, {45,16}, {45,8}, {45,8}, {45,8}, {42,8}, {42,4}, {45,8}, {45,16}, {45,8}, {47,8}, {48,8}, {49,16}, {47,16}, {45,16}, {42,16}, {45,16}, {47,8}, {45,8}, {45,16}, {45,8}, {47,8}, {48,8}, {50,8}, {52,8},{49,8}, {54,8}, {54,8}, {54,16}, {49,16}, {54,16}, {52,2}, {0,8}, };

uint8_t rickroll[][2] = { {52,16}, {54,16}, {57,16}, {54,16},{61,6},{61,6},{59,8},{0,8}, {52,16}, {54,16}, {57,16}, {54,16},{59,6},{59,6},{57,6},{0,8}, {52,16}, {54,16}, {57,16}, {54,16},{57,6},{59,6},{57,6},{54,6},{52,8},{54,8},{59,6},{57,4},{0,5},

{52,16}, {54,16}, {57,16}, {54,16},{61,6},{61,6},{59,8},{0,8}, {52,16}, {54,16}, {57,16}, {54,16},{64,6},{59,6},{57,6},{56,16},{54,8}, {52,16}, {54,16}, {57,16}, {54,16},{57,6},{59,6},{57,6},{54,6},{52,8},{54,8},{59,6},{57,6}, };

uint8_t careless[][2] = { {56,4}, {54,8}, {49,4},{45,4},{0,32},{56,3},{54,8},{49,4},{45,4},{0,8}, {54,4}, {52,8}, {45,4},{42,4},{0,32},{54,3}, {52,8}, {45,4},{42,4},{0,8}, {52,4}, {51,8}, {44,4},{42,4},{42,4},{40,2}, {0,4}, {39,4}, {40,4}, {42,4},{43,4},{44,4},{45,4}, {46,4},{47,3}, {56,4}, {54,8}, {49,4},{45,4},{0,32},{56,3},{54,8},{49,4},{45,4},{0,8}, {54,4}, {52,8}, {45,4},{42,4},{0,32},{54,3}, {52,8}, {45,4},{42,4},{0,8}, {52,4}, {51,8}, {44,4},{42,4},{42,4},{40,4},{39,4},{37,2},{38,1}, };

uint8_t partyrock[][2] = { {57,6}, {64,10}, {64,10},{55,10},{55,10},{55,10},{55,10}, {67,4}, {67,10}, {65,3}, {0,16},{57,6},{60,10},{62,10},{64,10}, {62,10},{55,6},{55,10},{55,10},{62,6},{60,3},{0,10}, {57,4}, {64,10},{55,10},{55,10},{55,10},{55,10}, {67,4}, {67,10}, {65,3}, {0,16},{57,6},{60,10},{62,10},{64,10}, {62,10},{55,6},{55,10},{55,10},{62,6},{60,3}, };

uint8_t heartgoeson[][2] = { {55,3}, {55,6},{55,4},{55,4},{54,4},{55,3},{0,4},{55,4},{54,8},{55,8},{55,4},{0,4}, {57,4}, {59,2},{57,2},{0,10}, {55,3}, {55,6},{55,4},{55,4},{54,4},{55,3},{0,4},{55,4},{50,1},{52,8},{50,8}, {52,8}, {55,8},{60,8},{62,8},{64,8},{66,8}, {55,1}, {57,2},{0,8},{50,4},{62,2},{60,4},{59,6},{57,2},{0,10},{59,4},{60,4}, {59,2},{57,4},{0,6}, {55,6}, {54,4},{55,2},{0,6},{54,6},{52,1},{50,2},{0,4}, {55,1}, {57,2},{0,8},{50,4},{62,2},{60,4},{59,6},{57,2},{0,10},{59,4},{60,4}, {59,2},{57,4},{0,6}, {55,6}, {54,4},{55,2},{0,6},{55,6},{54,4},{55,2},{0,6},{57,4},{59,2},{57,2},{55,1},{0,6},

};

uint8_t lucky[][2] = { {54,2}, {53,8},{54,8},{58,2},{58,8},{60,8},{61,2},{61,8},{63,8},{60,2},{0,8}, {53,8}, {54,2}, {53,8},{54,8},{58,2},{58,8},{60,8},{61,2},{58,8},{65,8},{63,2},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {53,16},{53,8},{53,8},{53,8},{51,16},{53,8},{56,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {54,16},{54,8},{54,8},{54,8},{53,16},{54,8},{56,4},{0,8}, {53,16},{53,8},{53,8},{53,8},{51,16},{53,8},{56,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, {51,16},{51,8},{51,8},{51,8},{53,16},{51,8},{49,4},{0,8}, };

// Time between two beats in microseconds (equal to length of a quarter note) #define beatDuration (60.0 / bpm) * 1000000L

// Time of the gap between two notes in microseconds #define noteGap beatDuration * (noteGapPercentage / 100.0) //________________________________ #include // SPI library #include // MFRC522 library

const int pinRST = 9; // Reset pin const int pinSS = 10; // Serial data pin

const int cardeen = "0B6D3412"; const int cardtwee = "7BC73B12"; const int carddrie = "EB773E12"; const int cardvier = "FB7A3212"; const int cardvijf = "8BC73312"; const int cardzes = "8B3D4412";

MFRC522 mfrc522(pinSS, pinRST); // Instantce MFRC522 op pinSS en pinRST

// Read card ID void getCardID() { // If no card is found and no card data is read // PICC = Proximity Integrated Circuit Card if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {

String cardIdRead = "";

for (byte i = 0; i < mfrc522.uid.size; i++) { // cardID[i] = mfrc522.uid.uidByte[i]; cardIdRead.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "")); cardIdRead.concat(String(mfrc522.uid.uidByte[i], HEX)); }

cardIdRead.toUpperCase();

Serial.print("Read ID: "); Serial.println(cardIdRead); if (cardIdRead == cardeen) { long randomizer; randomizer = random(2); //if you want multiple different songs on one card you need tone(6, 700, 100); //to put in the if statement and int. delay(1000); Serial.println("lucky");

if (randomizer == 1){ for(int i = 0; i < (sizeof(marylittlelamb) / sizeof(*marylittlelamb)); i++) { // pass the key number and note type playNote(marylittlelamb[i][0], marylittlelamb[i][1]); } } if (randomizer == 0){ for(int i = 0; i < (sizeof(lucky) / sizeof(*lucky)); i++) { // pass the key number and note type playNote(lucky[i][0], lucky[i][1]); } } }

if (cardIdRead == cardtwee) { tone(6, 700, 100); Serial.println("Videogames!"); delay(1000); for(int i = 0; i < (sizeof(megalovenia) / sizeof(*megalovenia)); i++) { // pass the key number and note type playNote(megalovenia[i][0], megalovenia[i][1]); digitalWrite(3, HIGH); //lights turning on and off on the beat digitalWrite(2, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW); digitalWrite(2, LOW); } }

if (cardIdRead == carddrie) { tone(6, 700, 100); Serial.println("Happy!"); delay(1000); for(int i = 0; i < (sizeof(rickroll) / sizeof(*rickroll)); i++) { // pass the key number and note type playNote(rickroll[i][0], rickroll[i][1]); digitalWrite( 3, HIGH); } }

if (cardIdRead == cardvier) { tone(6, 700, 100); Serial.println("Romantic ;)"); delay(1000); for(int i = 0; i < (sizeof(careless) / sizeof(*careless)); i++) { // pass the key number and note type playNote(careless[i][0], careless[i][1]); digitalWrite(2, HIGH); } }

if (cardIdRead == cardvijf) { tone(6, 700, 100); Serial.println("Party!"); delay(1000); for(int i = 0; i < (sizeof(partyrock) / sizeof(*partyrock)); i++) { // pass the key number and note type playNote(partyrock[i][0], partyrock[i][1]); digitalWrite(2, HIGH); digitalWrite(3, HIGH); digitalWrite(4, HIGH); } }

if (cardIdRead == cardzes) { tone(6, 700, 100); Serial.println("Sad"); delay(1000); for(int i = 0; i < (sizeof(heartgoeson) / sizeof(*heartgoeson)); i++) { // pass the key number and note type playNote(heartgoeson[i][0], heartgoeson[i][1]); digitalWrite(4, HIGH);

} }

Serial.println("");

// Stop reading mfrc522.PICC_HaltA(); } }

void setup() { Serial.begin(9600); // Set serial monitor

SPI.begin(); // Initialise the SPI bus mfrc522.PCD_Init(); // Initialise the MFRC522 reader

// Print MFRC522 Card Reader details to serial monitor mfrc522.PCD_DumpVersionToSerial();

Serial.println("Scan card...");

//_____________ // Set the speakerPin as an output pinMode(speakerPin, OUTPUT); randomSeed(analogRead(0));

pinMode(2, OUTPUT); //red pinMode(3, OUTPUT); //green pinMode(4, OUTPUT); //blue

}

void loop() { getCardID(); }

//________________________ void playNote(uint8_t keyNumber, uint8_t noteType) { long halfPeriod = getPeriodForKey(keyNumber) / 2; long noteDuration = beatDuration * (4.0 / noteType); long elapsed = 0; // While we have a note to play while(halfPeriod > 0 && elapsed < (noteDuration - noteGap)) { // Set speakerPin high for half of the period

digitalWrite(speakerPin, HIGH); wait(halfPeriod);

// Set speakerPin low for half of the period digitalWrite(speakerPin, LOW); wait(halfPeriod);

// Update the amount of time that has elapsed elapsed += halfPeriod * 2; }

/* * Gap between notes. Calculated using 'elapsed' to minimise timing errors * and ensure that the correct gap occurs whenever getPeriodForKey() returns * zero. */ wait(noteDuration - elapsed); }

/* * Returns the period for a key or zero for key numbers outside the range of 1 - * 88. * * keyNumber - The key number (1 - 88) */ long getPeriodForKey(uint8_t keyNumber) { // If the key is between 1 and 88 if(keyNumber >= 1 && keyNumber <= 88) { // Return the period (one second divided by the frequency of the key) return 1000000L / (pow(2.0, (keyNumber - 49.0) / 12.0) * 440.0); }

// Otherwise return zero return 0; }

void wait(long us) { // First delay for the number of whole milliseconds using delay() delay(us / 1000); // Then delay for the remainder of microseconds using delayMicroseconds() delayMicroseconds(us % 1000); }

_______________________________________________________________________

Step 6: Making the Box

I used a plastic box as body for the "JUKEBOT!".

First I cut out all the holes for the eyes, speakers and RFID scanner.

Next I made the eyes. I made the eyes by cutting the top of the milkshake lid to the size of the eyes I wanted. The I used the lower half of the cup to make the inside of the eyes. I painted the inside and the pupils black and i put the lights through the eyes. one blue, red and green led through each eye. I glued the pupil side of the cup to the outside of the box and the led side to the inside of the holes.

Next I glued the speakers and taped the RFID, wires and arduino to the inside of the lid as well. creating the masterpiece as seen on the picture above.

For the sides I cut straws to the right size and glued them to the side of the box.

Step 7: ENJOY YOUR "JUKEBOT!"

Be the First to Share

    Recommendations

    • Magnets Challenge

      Magnets Challenge
    • Raspberry Pi Contest 2020

      Raspberry Pi Contest 2020
    • Wearables Contest

      Wearables Contest

    Discussions