Skip to content

11. Final Report

This report shows the detailed development process of the final project. Big reveal: It is going to be a board for Dungeons and Dragons (DnD) Session. Especially for combat scenarios where players and monsters have a certain movement/weapon/spell range. Common modular DnD game pieces does not show you how far you can go, therefore I wanted to have a board which can show you that.

Research and Planing

Since I worked every previous week for my final project, I could skip the part of creating a prototype. But before I worked hands on the material, I needed to define what components I exactly need and at which range of costs it is estimately going to be. So in the following there is a table which presents all the material and their corresponding costs. Note that I was allowed to use some compontents and machines due to the course and my matriculation at the university, so the net costs might be higher. I also got some of the items at a discount.

Material Table

Item Price # Quantites
WS2812 ECO 5M 150 LEDs RGB 21,99 € 1
Intenso 7313530 Powerbank XS 10000 11,62 € 1
VERBATIM PLA-Filament 3D-Druck 2,85mm 1kg 28,79 € 1
poplar plywood 750mm x 750mm x 6mm 27,12 € 3
Bondex Holzlack Transparent matt 250 ml 9,99 € 1
USB Type A Cable 6,79 € 1
Total 106,27 €


PCB

My old PCB had not enough Vcc and GND connections, so I needed to redo it. As a sidenote: I changed the old layout of the PCB of week07, so do not wonder why the scheme does not fit the pictures of the report in week07. The green circles shows the added Vcc and GND connections, which where not existent in the previous design of week07. In total there are seven GNDs and four Vccs since the LED stripes have a three-point-connection, I decided to do the connection seperately (the pins marked in blue). Here are the images of the Fabmodules for the new PCB:

3D Printing

I printed a caseing for the powerbank. Since it was quite expensive, I thought it would be better to be able to remove it without any big effort. So the casing has a lid. In the following images you can see the dimensions of that casing:

This hole is for the USB ports of the powerbank:

The purpose of the M4 holes are to attach the casing to the board:

Lasercutting

Since the distances of the LEDs were wider than expected, I needed to cut all the layers for the board again. I also needed to use a bigger lasercutter “Epilog Engraver Win X64 Fusion”. I also laser cutted the casing for the the PCB.

The holes in red are for the LEDs to shine through and the hole in green are for game pieces like walls or minitures of buildings.

Here are the settings for the lasercutter to cut and engrave poplar plywood:

The lasercutter work in progress:

And a picture of the casing for the PCB:

Electronics and Connections

I soldered all the wires to removable female pin headers because the board/the electronics is not supposed to move alot and I always was a fan of reusing some components (like in LEGO). In the first image below you can see which connection should be placed. I also needed to cut the LED roll into 12 stripes and solder them together.

Here are all the connections, to where the cables shold be placed:

The first signal of life:

Programming and Input/Output Devices

The following code shows the current position, select the current position for further calculations, the maximum movemment range of the presets of “10ft” (1 tile), “20ft” (2 tiles) and “30ft” (3 tiles). If any action is taken (select a position etc), With the FDTI connection you can see with the serial monitor of the Arduino IDE the taken actions. The Input devices are a joystick for the position and selection (2 analog and 1 digital input) and three buttons for the movement ranges (all three are digital inputs). The output device are 12 LEDs seperated in 12 stripes. In the code you find further informations about the code at the corresponding line. The working code can be found below in the “Gallery” section.

#include <FastLED.h>



#define LED_PIN A0
#define NUM_LEDS 48

#define ANALOG_JOYSTICK_X A1
#define ANALOG_JOYSTICK_Y A2
#define DIGITAL_JOYSTICK_BUTTON A3

#define DIGITAL_10FT_BUTTON 5
#define DIGITAL_20FT_BUTTON 6
#define DIGITAL_30FT_BUTTON 7

int xPos;
int yPos;
int currentPosition = 0;
int selectPosition = 0;
int buttonState;
int mov10FtState;
int mov20FtState;
int mov30FtState;


CRGB leds[NUM_LEDS];  // set an array for the used LEDs




void setup() {
  // put your setup code here, to run once:
  FastLED.addLeds<WS2812, LED_PIN, RGB>(leds, NUM_LEDS);  // set the manufacturing type of LED stripes, the LED pin and the type of the LED
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 2000);        // set the maximum Volts and Ampere

  FastLED.clear();    //clear out the data
  FastLED.show();     //send the data to the LEDs


  //the LEDs needs to be activated first
  for (int i=0; i<NUM_LEDS; i++ )
  {
      leds[i] = CRGB(255, 255, 255 );   //configures the color of the LEDs
      FastLED.setBrightness(255);       //configures the brightness
      FastLED.show();
      leds[i] = CRGB(255, 255, 255 );   //configures the color of the LEDs
      FastLED.setBrightness(0);       //configures the brightness
      FastLED.show();

  }

  pinMode(ANALOG_JOYSTICK_X, INPUT);
  pinMode(ANALOG_JOYSTICK_Y, INPUT);
  pinMode(DIGITAL_JOYSTICK_BUTTON, INPUT);

  digitalWrite(DIGITAL_JOYSTICK_BUTTON, HIGH);



  pinMode(DIGITAL_10FT_BUTTON, INPUT);
  pinMode(DIGITAL_20FT_BUTTON, INPUT);
  pinMode(DIGITAL_30FT_BUTTON, INPUT);

  digitalWrite(DIGITAL_10FT_BUTTON, HIGH);
  digitalWrite(DIGITAL_20FT_BUTTON, HIGH);
  digitalWrite(DIGITAL_30FT_BUTTON, HIGH);


  Serial.begin(9600); // BAUD rate should not be more than 4800

}







void loop() {
  // put your main code here, to run repeatedly:
  // RED Green Blue

   buttonState = digitalRead(DIGITAL_JOYSTICK_BUTTON);
   mov10FtState = digitalRead(DIGITAL_10FT_BUTTON);
   mov20FtState = digitalRead(DIGITAL_20FT_BUTTON);
   mov30FtState = digitalRead(DIGITAL_30FT_BUTTON);


  // readout the values of the analoge pins
  int xValue = analogRead(ANALOG_JOYSTICK_X);
  int yValue = analogRead(ANALOG_JOYSTICK_Y);

  //when the button in the joystick is pressed: it selects the currentposition to claculate the movement range later on
  if(!buttonState){
    selectPosition = currentPosition;
    Serial.println("#-----------------------------------#");
    Serial.print("Selected Position: ");
    Serial.println(selectPosition);
    Serial.println("#-----------------------------------#\n");
    delay(1000);
  }



//--------------------------------------------------------------------------------

// conntrols for the current Position

 //border 
  if( xValue > 900){
      currentPosition = currentPosition + 1;
      if(currentPosition > NUM_LEDS - 1){
        currentPosition = NUM_LEDS - 1;
      }
      delay(100);
  }

  if( xValue < 200){
    currentPosition = currentPosition - 1;
     if(currentPosition < 0){
        currentPosition = 0;
     }
     delay(100);
  }

  /*
  if( yValue > 900){
     if( (currentPosition%2) == 0){
          currentPosition = currentPosition + 23;
          if(currentPosition > 143){
             currentPosition = 143;
          }
     }
     else{
          currentPosition = currentPosition + (12 - (currentPosition%12));
          if(currentPosition > 143){
            currentPosition = 143;
          }
     }
  }


  if( yValue < 200){
     if( (currentPosition%2) == 0){
            currentPosition = currentPosition - 23;
            if(currentPosition < 0){
              currentPosition = 0;
            }
     }
     else{
          currentPosition = currentPosition - (12 - (currentPosition%12));
          if(currentPosition < 0){
            currentPosition = 0;
          }
     }
  }
  */
//-----------------------------------------------------------------------  

//Serial communiction to check if the Values are properly read
  Serial.print(xValue);
  Serial.print("|");
  Serial.print(yValue);
  Serial.print("|");
  Serial.println(currentPosition);





//-----------------------------------------------------------------------


  //light up the LEDs
  int iteration = 0;
  while(iteration < NUM_LEDS){
      //show only the current position
      if( iteration == currentPosition){
        leds[currentPosition] = CRGB(255, 255, 255 );   //configures the color of the LEDs
        FastLED.setBrightness(255);       //configures the brightness
        FastLED.show();
      }
      else{
        leds[iteration] = CRGB(0, 0, 0 );   //configures the color of the LEDs
        FastLED.setBrightness(255);       //configures the brightness
        FastLED.show();
      }
    iteration++;
  }

  // every 10ft corresponds to 1 LED position
  if(!mov10FtState){
    showMovementRange(selectPosition, 1);
  }
  if(!mov20FtState){
    showMovementRange(selectPosition, 2);
  }
  if(!mov30FtState){
    showMovementRange(selectPosition, 3);
  }



}








//method to show the entered maximum movementrange from the inserted position
void showMovementRange(int currentPosition, int range){     

  int rangePositions[4];

  rangePositions[0] = currentPosition - range;
  rangePositions[1] = currentPosition + range;
  rangePositions[2] = currentPosition - 1 * range;
  rangePositions[3] = currentPosition + 1 * range;

  selectPosition = currentPosition;
  Serial.println("#-----------------------------------#");
  Serial.print("rangePositions[0]: ");
  Serial.println(rangePositions[0]);
  Serial.print("rangePositions[1]: ");
  Serial.println(rangePositions[1]);
  Serial.print("rangePositions[2]: ");
  Serial.println(rangePositions[2]);
  Serial.print("rangePositions[3]: ");
  Serial.println(rangePositions[3]);
  Serial.println("#-----------------------------------#\n");
  delay(1000);


  //light up the LEDs
  int iteration = 0;
  while(iteration < NUM_LEDS){

       //show the max range for 1 second      
      for(int i = 0; i < sizeof(rangePositions); i ++){
        if( iteration == rangePositions[i]){
          leds[rangePositions[i]] = CRGB(255, 255, 255 );   //configures the color of the LEDs
          FastLED.setBrightness(255);       //configures the brightness
          FastLED.show();
        }

      }

      iteration++;
    }

    delay(1000);

    for(int i = 0; i < NUM_LEDS; i ++){
        leds[i] = CRGB(0, 0, 0 );   //configures the color of the LEDs
        FastLED.setBrightness(255);       //configures the brightness
        FastLED.show();
    }
 }

Downloads