Caden Gamache
Published © MIT

Smart Room Controller 3-Pawn Game

This was a midterm assignment for CNM internet of things. The task was to control 6 smart lights, and 2 wemos with a unique design and theme

BeginnerWork in progress63
Smart Room Controller 3-Pawn Game

Things used in this project

Hardware components

Resistor 1k ohm
Resistor 1k ohm
×1
Through Hole Resistor, 560 ohm
Through Hole Resistor, 560 ohm
×1
Resistor 2.21k ohm
Resistor 2.21k ohm
×1
NeoPixel Ring: WS2812 5050 RGB LED
Adafruit NeoPixel Ring: WS2812 5050 RGB LED
×1
0.96" OLED 64x128 Display Module
ElectroPeak 0.96" OLED 64x128 Display Module
×1
Argon
Particle Argon
×1

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)
3D Printer (generic)
3D Printer (generic)
I used an Ender 3 Max Neo
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Photodiode Pawn P1 STL

Photodiode Pawn P2 STL

Pawn Prototype Drawing

This is a prototype for testing purposes. I had to figure out a way to complete a circuit with 360 rotation. With this prototype you put a bolt through the top and a washer on the bottom. The bolt allows you to adjust the height. There is also a hole to fit a resister which would then be attached to the washer and bolt.

Pawn w/ Resistor

Pawn prototype STL

Schematics

3-Pawn Game Fritz

Basic 3x3 chess board diagram

3x3 chess board diagram

Using wires to transfer to a 1x18 header to allow the lid to be easily removed.

Schematic showing the final circuitry

Code

3PawnGame_RoomController.ino

C/C++
This code sends a high output through three D pins one at a time and reads the voltage using three A pins. This allows a 3x3 array to be stored. It later takes the stored values and converts them to either 0, 1, or 2 which translates to a pawns side.
/*
 * Project 3PawnGame_RoomController
 * Description: A smart room controller that reads an active 3-pawn game to control hue lights and wemos
 * Author: Caden Gamache
 * Date: 03/01/2023 - 03/09/2023
 */

SYSTEM_MODE(SEMI_AUTOMATIC);

#include <IoTClassroom_CNM.h>
#include <Adafruit_SSD1306.h>
#include <neopixel.h>

float actualRead [3][3];  //untouched array storing the volages read
float nominalRead [3][3]; //rounded array based on actual read
//the cordinates for the center of every square. x (even columns 0,2,4) and y (odd columns 1,3,5)
int piecePos [3][6] {
  {15, 48, 15, 31, 15, 15},
  {31, 48, 31, 31, 31, 15},
  {48, 48, 48, 31, 48, 15}
};
const int COLORS [] {0,62309,59086,53714,48343,45120,42971}; //gradient from red to blue (HSV)
const int NEOCOLORS [] {0xFF0000,0xD5002B,0xAA0055,0x800080,0x5500AA,0x2B00D5,0x0000FF}; //gradient from red to blue (RGB)
int i,j,k;
int currentRow,currentColor; //variables called in multiple functions
int redPiece,bluePiece; //stores the number of red (1's) or blue (2's) pieces
int wemo1 = 2,wemo2 = 3;

void checkPiecePos ();
void rowSetup ();
void determineAdvantage ();
void drawBoard();
void drawPieces();

Adafruit_NeoPixel neopix(12,A4,WS2812B);
Adafruit_SSD1306 display(D2);


void setup() {

  WiFi.on();
  WiFi.setCredentials("IoTNetwork");
  WiFi.connect();
  //forces the system to wait for the wifi to connect
  while(WiFi.connecting()) {
  delay(1);
  }

  neopix.setBrightness(8);
  neopix.show();

  display.begin(SSD1306_SWITCHCAPVCC,0x3C);
  display.clearDisplay();
  display.display();

  Serial.begin(9600);
  waitFor(Serial.isConnected,10000);

  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(D8,OUTPUT);
  pinMode(D7,OUTPUT);
  pinMode(D6,OUTPUT);
}

void loop() {
  checkPiecePos();
  determineAdvantage();
  drawBoard();
  drawPieces();
  display.display();
  //adjusts hues if either side achieves victory
  if (nominalRead[0][0] == 2 || nominalRead[0][1] == 2 || nominalRead[0][2] == 2) {
    for (i=0;i<7;i++) {
      setHue(i,true,COLORS[6],255,255);
    }
    pixelFill(0,12,NEOCOLORS[6]);
    switchON(wemo1);
    delay(5000);
  }
  if (nominalRead[2][0] == 1 || nominalRead[2][1] == 1 || nominalRead[2][2] == 1) {
    for (i=0;i<7;i++) {
      setHue(i,true,COLORS[0],255,255);
    }
    pixelFill(0,12,NEOCOLORS[0]);
    switchON(wemo2);
    delay(5000);
  }
  //on-going (adjust hues based on the active game)
  else {
    for (i=0;i<7;i++) {
      setHue(i,true,COLORS[currentColor],100,255);
    }
    switchOFF(wemo1);
    switchOFF(wemo2);
    pixelFill(0,12,NEOCOLORS[currentColor]);
  }
}
//looks through the nominal read and adds a red or blue piece if the values match
void determineAdvantage () {
  //reset values
  redPiece = 0;
  bluePiece = 0;
  //read the number of red and blue pieces
  for (j=0;j<3;j++) {
    for (i=0;i<3;i++) {
      if (nominalRead[j][i] == 1) {redPiece ++;}
      if (nominalRead[j][i] == 2) {bluePiece ++;}
    }
  }
  //adjust colors
  if (redPiece > bluePiece) {
    currentColor = 3 - (redPiece - bluePiece); 
  }
  if (redPiece < bluePiece) {
    currentColor = 3 + (bluePiece - redPiece);
  }
  if (redPiece == bluePiece) {
    currentColor = 3;
  }
  Serial.printf("\nNumRed = %i NumBlue = %i",redPiece,bluePiece);
}
//reads the voltage of every square and stores them in an array. It then converts the stored floats into 3 values
void checkPiecePos () {
  //reads all piece positions and determines their side
  for (j=0;j<3;j++) {
    currentRow = j;
    rowSetup ();
    for (i=0;i<3;i++) {
      nominalRead [i][j] = analogRead(i+17)/723.0;
      actualRead [i][j] = nominalRead [i][j];
      //converts to three values
      if (nominalRead [i][j] > 1 && nominalRead [i][j] < 2) {nominalRead [i][j] = 1;}
      if (nominalRead [i][j] > 2) {nominalRead [i][j] = 2;}
      if (nominalRead [i][j] < 1) {nominalRead [i][j] = 0;}
    }
  }
  //these for loops flip the array values for some clarity when reading the serial monitor
  for (i=2;i>=0;i--) {
    Serial.printf("\ncol1 = %.2f col2 = %.2f col3 = %.2f",actualRead[i][0],actualRead[i][1],actualRead[i][2]);
  }
  for (i=2;i>=0;i--) {
    Serial.printf("\nPieceSide = %.2f PieceSide = %.2f PieceSide = %.2f",nominalRead[i][0],nominalRead[i][1],nominalRead[i][2]);
  }
}
//switches the D pins between input/output and high/low turning one on at a time (setting to low is required for consistent reading)
void rowSetup () { 
  //first column
  if (currentRow == 0) {
    pinMode(D8,OUTPUT);
    pinMode(D7,INPUT);
    pinMode(D6,INPUT);
    digitalWrite(D8,HIGH);
    digitalWrite(D7,LOW);
    digitalWrite(D6,LOW);
  }
  //second column
  if (currentRow == 1) { 
    pinMode(D8,INPUT);
    pinMode(D7,OUTPUT);
    pinMode(D6,INPUT);
    digitalWrite(D8,LOW);
    digitalWrite(D7,HIGH);
    digitalWrite(D6,LOW); 
  }
  //third column
  if (currentRow == 2) {
    pinMode(D8,INPUT);
    pinMode(D7,INPUT);
    pinMode(D6,OUTPUT);
    digitalWrite(D8,LOW);
    digitalWrite(D7,LOW);
    digitalWrite(D6,HIGH);
  }
}
//resets the board on the display (without showing changes)
void drawBoard () {
  display.clearDisplay();
  //left edge
  display.drawLine(6,6,6,57,WHITE);
  //right edge
  display.drawLine(57,6,57,57,WHITE);
  //top edge
  display.drawLine(6,6,57,6,WHITE);
  //bottom edge
  display.drawLine(6,57,57,57,WHITE);
  //white squares
  display.fillRect(24,7,16,16,WHITE);
  display.fillRect(7,24,16,16,WHITE);
  display.fillRect(41,24,16,16,WHITE);
  display.fillRect(24,41,16,16,WHITE);
  //text and symbols
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(68,16);
  display.printf("red  = ");
  display.setCursor(68,43);
  display.printf("blue = ");
  display.fillCircle(118,18,4,WHITE);
  display.fillTriangle(118,41,114,49,122,49,WHITE);
}
//reads the nominal array and puts a circle or triangle in the correct square
void drawPieces () {
  //ensures the color swaps between black and white with every square
  bool whiteBlack;
  for (j=0;j<3;j++) {
    k = 0;
    for (i=0;i<3;i++) {
      whiteBlack = !whiteBlack;
      //checks if there is a red piece in the nominal read array and puts it in the correct square
      if (nominalRead [i][j] == 1) {
        display.fillCircle(piecePos[j][k],piecePos[j][k+1],4,whiteBlack);
        Serial.printf(" piece found");
      }
      //checks if there is a blue piece in the nominal read array and puts it in the correct square
      if (nominalRead [i][j] == 2) {
        display.fillTriangle(piecePos[j][k],piecePos[j][k+1]-4,piecePos[j][k]-4,piecePos[j][k+1]+4,piecePos[j][k]+4,piecePos[j][k+1]+4,whiteBlack);
        Serial.printf(" piece found");
      }
      Serial.printf("\nk = %i i = %i j = %i",k,i,j);
      //k increase keeps x and y cordinates seperated in the array
      k+=2;
    }
  }
}
//takes a start and end position and runs through a for loop until all pixels are on
void pixelFill(int start, int end,int color) {
  int neopixNum;
  for ( neopixNum = start; neopixNum < end; neopixNum ++) {
    neopix.setPixelColor(neopixNum, color);
    neopix.show();
  } 
}

CadenG_SmartRoomController_3-PawnGame

This smart room controller is designed to give visual feedback of whatever is happening on an active 3-Pawn Game board. Depending on which side is winning, hero or villain (red/blue), all the lights in the room will shift towards their color. If a side rises victorious the lights will turn their teams color and turn on a wemo for either side.

Credits

Caden Gamache
4 projects • 9 followers
Finished CNM's internet of things boot-camp where I learned IoT skills. I have a passion for learning and try to build skills wherever I am!

Comments