Project Managment

BLUE HOME Board Game | Fab Academy Final Project 2021

This page shows the steps, designs and the process of making my final project for FAB Academy 2021.

Idea Behind Blue Home

My passion for board games and educating people about the Solar System that we live in drove me to make this board game called Blue Home.

Blue Home is an educational interactive board game, played by 1+ and for ages 6+. Basically, it is for anyone who wants to get to know more about the planets around us and their moons in a fun way. It is about an astronaut who is lost in space and his goal is to reach his Blue Home safely, facing all the quizzes, obstacles, and using all needed help. You are that astronaut and your goal is to reach the Blue Home.

How To Play To Play Blue Home, first build your path using the colored jigsaw pieces. This will be your board that you will move on. After that, role the dice, and move your astronaut. The astronaut will then react randomly by vibrating and shining different colors. Depending on the color your piece shine, you will either move forward or backward, or pick a card.

How does it work The main component of this game is the RGB built-in sensor in the Arduino. It is placed downward to detect the color of the jigsaw piece it is on and based on that there will be various reactions from the RGB LED.

A Demo Video of Blue Home

Bill of Materials

Qty Description
6 Different colors 15mm Cardboard
1 RGB LED
1 Arduino Nano 33 BLE Sense
2 Addressable RGB LED Strips each with 3 LEDs
1 Vibrating Mini
1 3D printed Astronaut Piece
30 Printed Cards
1 Dice
1 Diffusive Paper

Blue Home in the Making

The making of this board game consists of three main steps, fabrication, connecting the electronic parts and coding the game.

Testing Before Going Forward

  • Before going and doing the fabrication, I started by testing the conditions that the RGB sensor will work in.

  • I started by making a sample model prototype using cardboard, and tested the reading of the sensor.

  • It appeared that the reading were way darker than the true values, so there should be a light source lighting up the place where the piece will stand.

  • This was a successful test, then I made a further step and used another piece that will be kind of similar to the piece that I will 3D print, which is the cap of a spray bottle.

  • This gave me the conditions needed for the design I need to make for the piece, for example I need to make a placement for LED strips in the base below, and I need a placement for the Arduino.

Designing the Main Piece (The Astronaut)

  • After knowing everything I need to include in my design for the piece, I then started the process of designing it and printing it.

  • I used Fuion360 for the design, and I did it from scratch.

  • The design consists of three parts:

  • The 1st Base which holds on the Arduino, and it is tighten to the body and the 2nd base. It must have a hole for the USB wire and must be empty for the wires to be connected in the Pinouts of the Arduino.

  • The 2nd Base which tightens up to the 1st base, and has a placement for LED Strips. It must have a place for the wires of the LED strips to go all the way up and be connected to the pinouts of the Arduino.

  • The Body which tighten up to the 1st base and basically it is the shape of the piece. It must be empty from the inside.

1st Base Design

  • Started with a cylinder of diameter 7 cm.

  • Make a hole of the shape of a rectangular of the same size of the Arduino Nano 33 BLE Sense ( 45x18mm).

  • Use the Thread tool to make a thread around the base.


  • To make a thread that works when 3D printed, I followed this tutorial:
  • Thread Tutorial

  • Make a smaller cylinder hole, while keeping the base of the Arduino in the bottom, this will make up the space for all the wires and connections needed.

  • From one side make a 2.5 cm diameter hole going all the way to the rectangle, which is for the USB wire to connect to the Arduino.

  • The final result of the 1st Base design is as seen:

2nd Base Design

  • Make a new component, and start by drawing a hallow cylinder of height 3 cm.

  • Make two parallel rectangles of width 1 cm, or depending the LED strips to be placed. Also make a circular hole in the position of the built-in RGB sensor of the Arduino.

  • Make a thread in the inside of the piece, for it to tighten up with Base 1. Make sure that there is some tolerance so that after 3d printing it, the thread works.

  • make a hole similar to the one in Base 1 for the USB wire.

  • This is how the base look from upper view.

Body Design

  • Start by making a third component, make a hallow cylinder slightly bigger than the bases.

  • use the Torus to make an upper part on the cylinder. Make threads to be tighten up with Base 1.

  • Use Coil attached to a sphere to make the hands.

  • Mirror the hands and attach it to the body.

  • Add two more torus on top to attach the body to the helmet of the astronaut.

  • Make the helmet using a sphere.

  • Make a smaller sphere a little bit coming out from the first one.

  • Erase the second sphere from the first one.

  • Make sure there is an empty path for the wires all the way from the helmet to down the body.

  • The final Body Design is as seen:

Download The Piece Design (3 Parts)


3D Printing

  • The 3 parts were 3D printed using Prusa i3 MK3S

  • I did the slicing in Ultimaker Cura; for further reading about the printer settings and how to 3D print Read This Page

Designing the Steps Pieces (The Board)

  • To make the game more interesting and adjustable, The steps were made as jigsaw pieces of different colors. This will allow the players to design their own path, whether it is a short one, or a long path with twists.

Steps Design

  • The pieces were designed in Fusion 360.


Download The Steps Design


Laser Cutting

  • The design then was cut using a laser cutter, on different colored cardboards of height ~ 15mm.

  • To know more about the laser cutting process and the setting of the machine Read This Page

  • The pieces could be adjusted and connected to each others from all the sides.

Designing the Cards

  • After having the piece you will play with and the board you will build to play on, finally the accessories of this game are the cards that have valuable educating questions and information.

  • To download the file for the cards designs and the instructions see below.

  • Make sure to print the cards correctly as they are two-sided.


PDF File


Electronic Connections

The electronic parts of this project are:

  • The Arduino Nano 33 BLE Sense.
  • Addressable LED Strips (6 LED): Placed under on the base, facing downward so that they light up where they are placed for the RGB sensor to work fine.
  • LED Light: Placed in the head of the astronaut, lighten up to get reactions and know what is the next step of the game.
  • A Buzzer: to get reactions through out the game.
  • Wires for connections.

  • The electronic parts were connected as seen in the figure below:

Simulation is done by TnkerCAD Note that Arduino Nano 33 BLE Sense was used in this project and not UNO.

Put The Pieces Together

  • The LED strips are in the base facing down as seen.

  • The RGB LED is connected and facing upward to be then placed in the helmet, so is the vibration mini.

  • This is how the base looks before tightening the body on top.

  • Now place the body part on top to cover all the electronics.

  • Make sure that the cords of the LED RGB are long enough for it to stick on the inside of the helmet of the astronaut.

  • Then using diffusive paper make a helmet.

  • And place it on the astronaut's head.

Code

The code of the game is as follows:


											// SENSOR LIBRARY
											#include <Arduino_APDS9960.h>
											
											//ADDRESSABLE RGB LED LIBRARY
											#include <Adafruit_NeoPixel.h>
											
											#ifdef __AVR__
											 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
											#endif
											// Which pin on the Arduino is connected to the NeoPixels?
											#define PIN        6 // LED PIN
											// How many NeoPixels are attached to the Arduino?
											#define NUMPIXELS 6 // Popular NeoPixel ring size
											Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
											
											#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
											
											void setup() {
											
											#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
											  clock_prescale_set(clock_div_1);
											#endif
											  // END of Trinket-specific code.
											
											  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
											
											  Serial.begin(9600);
											  while (!Serial);
											
											  if (!APDS.begin()) {
												Serial.println("Error initializing APDS-9960 sensor.");
											  }
											
											
												 pinMode(6, OUTPUT); //LED LIGHT (BASE)
												 pinMode(9, OUTPUT); // RED
												 pinMode(10, OUTPUT); //BLUE
												 pinMode(11, OUTPUT); //GREEN
												 pinMode(5, OUTPUT); //PUZZER
											
											
											}
											
											void loop() {
											
											
											  int r, g, b, a;
											  double rh, bh, gh, cmax, cmin, del, h, hf;
											
											  // read the color
											  APDS.readColor(r, g, b);
											
											  // print the values
											  Serial.print("r = ");
											  Serial.println(r);
											  Serial.print("g = ");
											  Serial.println(g);
											  Serial.print("b = ");
											  Serial.println(b);
											  Serial.println();
											
												// wait a bit before reading again
											  delay(500);
											
											
											  // LOWER LGB
											  pixels.clear(); // Set all pixel colors to 'off'
											
											  // The first NeoPixel in a strand is #0, second is 1, all the way up
											  // to the count of pixels minus one.
											  //for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
											
												// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
											
												pixels.setPixelColor(0, pixels.Color(255, 255, 255));
												pixels.setPixelColor(2,  pixels.Color(255, 255, 255));
												pixels.setPixelColor(3,  pixels.Color(255, 255, 255));
												pixels.setPixelColor(5,  pixels.Color(255, 255, 255));
											
												pixels.show();   // Send the updated pixel colors to the hardware.
											
												//delay(DELAYVAL); // Pause before next pass through loop
											  //}
											
											
											// SENSOR
											 // check if a color reading is available
											  while (! APDS.colorAvailable()) {
												delay(1);
											  }
											
											
											  //find new r,g,b,c,del
											  //rh=r/255;
											 // gh=g/255;
											  //bh=b/255;
											  cmax= max(r,g);
											  cmax= max(cmax,b);
											
											  cmin=min(r,g);
											  cmin= min(cmin,b);
											
											  del= (cmax-cmin);
											
											   // find HUE
											
											 if (r>g & r>b)
											  {h=60*((g-b)/del);}
											
											  if (g>r & g>b)
											  {h= 60*((b-r)/del+2);}
											
											  if (b>r & b>g)
											  {h=60*((r-g)/del+4);}
											
											if (h<0)
											{h=h+360;}
											
											  Serial.println();
											  Serial.println(h);
											  Serial.println();
											
											//GAME SETTINGS
											// depending on the value of h, the output led will change colors or the puzzer will turn on
											// REFRENCE FOR HUE VALUES FOR THE PIECES OF BLUE HOME GAME:
											
											while ( abs(h-hf) > 5.0)
											{
											// PINK
											if (h>220 & h <360)
											{
											  a= random(1,3);
											  }
											
											  //BLUE
											if (h<220 & h >210)
											{
												a= random(3,4);
											  }
											
											//BLACK
											if (h>180 & h <210)
											{
											  a=random(4,6);
											  }
											
											//GREEN
											if (h<180 & h >140)
											 {
											  a =random(1,3);
											  }
											
											  //OFFWHITE
											if (h<140 & h >40)
											{
											  a= random(4,8);
											  }
											
											 //YELLOW
											if (h<40 & h >0)
											{
											  a =random(3,5);
											  }
											
											//////////////////
											
											  if (a==1)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, HIGH ); //GREEN
											}
											
											if (a==2)
											
											{ digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, HIGH ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											}
											
											if ( a==3)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, HIGH ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											
											if (a==4)
											{
											 digitalWrite(5, HIGH ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											
											if (a==5)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, HIGH ); // RED
											 digitalWrite(10, HIGH ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											
											if (a==6)
											{
											 digitalWrite(5, HIGH ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, HIGH ); // BLUE
											 digitalWrite(11, HIGH ); //GREEN
											 }
											
											
											if (a==7)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, HIGH ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											 hf = h;
											}
											
											
											  Serial.print("hf = ");
											  Serial.println(hf);
											  Serial.println();
											
											}
											

Discussion of the Code

  • The code runs the LED in the base to light up the area under the piece so it is visible for the Arduino Built-In sensor, this LED is turned on through out the game.

  • Note that the library for the addressable RGB LED strips is needed to be downloaded and included in the code. Adafruit NeoPixel Library

  • The Simple example helped me understand how to program the LED Strips, As they are vey bright I ended up using only 4 out of 6 LEDs.

  • The RGB sensor's library needs to be included in the code, the library is APDS9960.

  • The sensor reads values of RGB and then using equations convert them to a single value which is hue (h).

  • Then this value is compared to the previous calculated value of hue, and if there is a difference (meaning the piece has moved) then the piece will randomly react depending on the color it sensed.

  • The reaction is the change of the head's color (White/Red/Pink/Cyan/Yellow/Green) or a vibration.

  • A useful page to understand how RGB sensor works here

Some Helpful Examples

  • Addressable RGB LED Simple Example
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
											// Released under the GPLv3 license to match the rest of the
											// Adafruit NeoPixel library
											
											#include <Adafruit_NeoPixel.h>
											#ifdef __AVR__
											 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
											#endif
											
											// Which pin on the Arduino is connected to the NeoPixels?
											#define PIN        6 // On Trinket or Gemma, suggest changing this to 1
											
											// How many NeoPixels are attached to the Arduino?
											#define NUMPIXELS 16 // Popular NeoPixel ring size
											
											// When setting up the NeoPixel library, we tell it how many pixels,
											// and which pin to use to send signals. Note that for older NeoPixel
											// strips you might need to change the third parameter -- see the
											// strandtest example for more information on possible values.
											Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
											
											#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
											
											void setup() {
											  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
											  // Any other board, you can remove this part (but no harm leaving it):
											#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
											  clock_prescale_set(clock_div_1);
											#endif
											  // END of Trinket-specific code.
											
											  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
											}
											
											void loop() {
											  pixels.clear(); // Set all pixel colors to 'off'
											
											  // The first NeoPixel in a strand is #0, second is 1, all the way up
											  // to the count of pixels minus one.
											  for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
											
												// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
												// Here we're using a moderately bright green color:
												pixels.setPixelColor(i, pixels.Color(0, 150, 0));
											
												pixels.show();   // Send the updated pixel colors to the hardware.
											
												delay(DELAYVAL); // Pause before next pass through loop
											  }
											}
											
  • RGB Sensor Example
/*
											  APDS-9960 - Color Sensor
											
											  This example reads color data from the on-board APDS-9960 sensor of the
											  Nano 33 BLE Sense and prints the color RGB (red, green, blue) values
											  to the Serial Monitor once a second.
											
											  The circuit:
											  - Arduino Nano 33 BLE Sense
											
											  This example code is in the public domain.
											*/
											
											#include <Arduino_APDS9960.h>
											
											void setup() {
											  Serial.begin(9600);
											  while (!Serial);
											
											  if (!APDS.begin()) {
												Serial.println("Error initializing APDS-9960 sensor.");
											  }
											}
											
											void loop() {
											  // check if a color reading is available
											  while (! APDS.colorAvailable()) {
												delay(5);
											  }
											  int r, g, b;
											
											  // read the color
											  APDS.readColor(r, g, b);
											
											  // print the values
											  Serial.print("r = ");
											  Serial.println(r);
											  Serial.print("g = ");
											  Serial.println(g);
											  Serial.print("b = ");
											  Serial.println(b);
											  Serial.println();
											
											  // wait a bit before reading again
											  delay(1000);
											}
											
  • A code I made that makes the piece shine the same color it sense:

											// SENSOR LIBRARY
											#include <Arduino_APDS9960.h>
											
											//ADDRESSABLE RGB LED LIBRARY
											#include <Adafruit_NeoPixel.h>
											
											#ifdef __AVR__
											 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
											#endif
											// Which pin on the Arduino is connected to the NeoPixels?
											#define PIN        6 // LED PIN
											// How many NeoPixels are attached to the Arduino?
											#define NUMPIXELS 6 // Popular NeoPixel ring size
											Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
											
											#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
											
											void setup() {
											
											#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
											  clock_prescale_set(clock_div_1);
											#endif
											  // END of Trinket-specific code.
											
											  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
											
											  Serial.begin(9600);
											  while (!Serial);
											
											  if (!APDS.begin()) {
												Serial.println("Error initializing APDS-9960 sensor.");
											  }
											
											
												 pinMode(6, OUTPUT); //LED LIGHT (BASE)
												 pinMode(9, OUTPUT); // RED
												 pinMode(10, OUTPUT); //BLUE
												 pinMode(11, OUTPUT); //GREEN
												 pinMode(5, OUTPUT); //PUZZER
											
											
											}
											
											void loop() {
											
											
											  int r, g, b;
											  double rh, bh, gh, cmax, cmin, del, h;
											
											  // read the color
											  APDS.readColor(r, g, b);
											
											  // print the values
											  Serial.print("r = ");
											  Serial.println(r);
											  Serial.print("g = ");
											  Serial.println(g);
											  Serial.print("b = ");
											  Serial.println(b);
											  Serial.println();
											
												// wait a bit before reading again
											  delay(500);
											
											
											  // LOWER LGB
											  pixels.clear(); // Set all pixel colors to 'off'
											
											  // The first NeoPixel in a strand is #0, second is 1, all the way up
											  // to the count of pixels minus one.
											  //for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
											
												// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
											
												pixels.setPixelColor(0, pixels.Color(255, 255, 255));
												pixels.setPixelColor(2,  pixels.Color(255, 255, 255));
												pixels.setPixelColor(3,  pixels.Color(255, 255, 255));
												pixels.setPixelColor(5,  pixels.Color(255, 255, 255));
											
												pixels.show();   // Send the updated pixel colors to the hardware.
											
												//delay(DELAYVAL); // Pause before next pass through loop
											  //}
											
											
											// SENSOR
											 // check if a color reading is available
											  while (! APDS.colorAvailable()) {
												delay(1);
											  }
											
											
											  //find new r,g,b,c,del
											  //rh=r/255;
											 // gh=g/255;
											  //bh=b/255;
											  cmax= max(r,g);
											  cmax= max(cmax,b);
											
											  cmin=min(r,g);
											  cmin= min(cmin,b);
											
											  del= (cmax-cmin);
											
											   // find HUE
											
											 if (r>g & r>b)
											  {h=60*((g-b)/del);}
											
											  if (g>r & g>b)
											  {h= 60*((b-r)/del+2);}
											
											  if (b>r & b>g)
											  {h=60*((r-g)/del+4);}
											
											if (h<0)
											{h=h+360;}
											
											  Serial.println();
											  Serial.println(h);
											  Serial.println();
											
											
											
											
											
											//GAME SETTINGS
											// depending on the value of h, the output led will change colors or the puzzer will turn on
											// REFRENCE FOR HUE VALUES FOR THE PIECES OF BLUE HOME GAME:
											
											
											// PINK
											if (h>220 & h <360)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, HIGH ); //GREEN
											 }
											
											//BLUE
											if (h<220 & h >210)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, HIGH ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											
											//BLACK
											if (h>180 & h <210)
											{
											 digitalWrite(5, HIGH ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, LOW ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											//GREEN
											if (h<180 & h >140)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, HIGH ); // RED
											 digitalWrite(10, HIGH ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											
											//OFFWHITE
											if (h<140 & h >40)
											{
											 digitalWrite(5, HIGH ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, HIGH ); // BLUE
											 digitalWrite(11, HIGH ); //GREEN
											 }
											
											
											 //YELLOW
											if (h<40 & h >0)
											{
											 digitalWrite(5, LOW ); // Turn the VIBRATING on
											 digitalWrite(9, LOW ); // RED
											 digitalWrite(10, HIGH ); // BLUE
											 digitalWrite(11, LOW ); //GREEN
											 }
											
											}
											

Download the Final Code


Final Result

  • The video below shows the final game setup and how to play the game briefly.

Development of Blue Home

  • The Piece that is used in this game could be programmed and used in any different game with different setups. Now that it is working perfectly, anyone could design their board and change the code to what is suitable. Another fitting piece could be used instead of the astronaut design and tighten up to the base.

  • Another improvement will be using a mobile phone application connected to the game which will make it more interactive.

Acknowledgement

  • By the end of this journey through Fab Academy, my words are not enough to thank my supervisor Dr. Salman Oraibi for providing all the support needed to finish this project. Also, for the instructors who helped me make the impossible possible all along the way: Duaa, Abdulla, Abdulghufoor, Haitham and Mohammed. It was such an unforgettable journey filled with joy, learning new skills, and learning that an obstacle is just a station to gain more knowledge and wisdom.