Capstone Project

Tutorial Link: https://www.youtube.com/watch?v=l3-y371RlI4&t=4s

created by youtuber: How to Mechatronics

Final Project Intro Paragraph

I decided to do a weather station. The reason why I chose this project is that I always want a mini weather station that can tell me the temperature and the humidity of my room so that I can adjust the air conditioner and decide what to wear to school everyday. It also helps me with my Fablab project since there is a display screen included in it. A successful weather station would tell me the temperature and the humidity of my room and detect the data every 20 seconds using the DHT22 sensor. It would display both of the data on the SSD1306 OLED display.

I used a video created by a youtuber: How to Mechatronics as my starting point and modified it as my own project.

Presentation of Final Product

Fang-Engineering Presentation

Preparation Week: 11/18-11/22 

Bill of Materials (11/18)

Fang-EE Final Project

11/18: I spent the whole class period watching the video over and over again to make sure I did not miss any components I need.

Sole components of my project

Difference Between my project and the video

I used the same display and same DHT22 sensor as the video. However, I changed the chip from Arduino Nano to XIAO Seeed RP2040 because the volume of Arduino Nano is too large and I just wanted to make a tiny project. I also changed the case design as the wood case designed by the video was too huge and heavy. Instead, I used 3D printing to make my case. I also created my own code and my own PCB board without using the same design from the video.

Gantt Chart (11/19-11/20)

I built my Gantt Chart for my project from scratch following the video linked below:

https://www.youtubeeducation.com/watch?v=8eKk0M2zGIk

Gantt Chart

I did stick with the plan since I was changing my Gantt Chart while I was making progress. Once I deviated from my plan, I would change the following due dates accordingly. Except for my digital portfolio. I was planning on doing it from beginning. However, I was too busy focusing on the building part instead of the documentation. The process is messy so I need time after I finish my whole project to arrange the pictures and describe it.

11/19: I was making the Gantt Chart following the video my teacher provided me. He gave us a template. But I decided to actually learn how to make a Gantt chart since I believe it is useful to pain other thing in the future. I finished half of the Gantt Chart which is formatting and putting equations in it.

11/20: I was finishing up the second half of my Gantt chart following the video. Then, I started to put the to do list into the Gantt Chart. Later, I created the estimated due date for each part.

Using Wokwi to design my wiring (11/21-11/22)

11/21: I was trying to figure out how the display code work. So I started a simulation in Wokwi. I did not find RP2040 in Wokwi, so I decided to use a similar microcontroller which is esp32. I searched up the code online and find a website as a reference: https://forum.arduino.cc/t/esp32-s3-and-two-i2c-buses-with-adafruit-ssd1306-library-two-oled-128x64-displays/1290094 . There is a code foe two displays and esp32. I modified it and made it work in Wokwi.

11/22: The next day, I was doing the simulation with both DHT22 sensr and display. I did not find RP20240 in either Wokwi or Tinkercad. So I decided to use Raspberry Pi Pico instead. I tried to used the same code I tested out on my real thing to make the simulation work. However, while the code worked in real life, it did not work in the simulation. Wokwi was not able to compile the code.

Code for turning on the Display in Wokwi

// OLED

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>


//Define pins

#define I2C_B_SDA 17 // GPIO17

#define I2C_B_SCL 18 // GPIO18


// OLED parameters

#define SCREEN_WIDTH 128     // OLED display width, in pixels

#define SCREEN_HEIGHT 64     // OLED display height, in pixels

#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C  // Change if required

#define ROTATION 0           // Rotates text on OLED 1=90 degrees, 2=180 degrees


// Define display object

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


void setup() {

  Serial.begin(115200);

  while (!Serial)

    ;

   Wire.begin(I2C_B_SDA, I2C_B_SCL);


  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

    Serial.println(F("Display1 SSD1306 allocation failed"));

    for (;;)

      ;  // Don't proceed, loop forever

  }


// Show splash screen

  display.display();

  delay(2000); // Pause for 2 seconds


  // Display settings

  display.clearDisplay();

  display.setTextSize(2);             // Normal 1:1 pixel scale

  display.setTextColor(WHITE);        // Draw white text

  display.setCursor(0,0);             // Start at top-left corner

  display.setRotation(ROTATION);      // Set screen rotation


  display.print("Display 1");


  display.display();

}



void loop() {

}


Week 2: 12/2-12/6

Pinout for RP2040

The pinout is help helpful when wiring. So I put a picture of the pinout of RP2040 so that I don't need to find it online everytime I need to use.

Building blinking built-in led

IMG_2174.MOV

Video of Built-in LED Blinking

Testing My Sensor

Code for Sensor only

/* Circuits DIY

 * For Complete Details Visit

 * https://www.circuits-diy.com/interfacing-dht22-temperature-sensor-with-xiao-rp2040/

 */

#include "DHT.h"

#define DHTPIN 27     // Digital pin connected to the DHT sensor

 

#define DHTTYPE DHT22   // DHT 22

DHT dht(DHTPIN, DHTTYPE);


 #include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

 

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

 

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

 

void setup()

{

  Serial.begin(115200);

  Serial.println(F("DHTxx test!"));

  dht.begin();

  delay(2000);

}

 

void loop()

{

  float h = dht.readHumidity();

  float t = dht.readTemperature();

 

  // Check if any reads failed and exit early (to try again).

  if (isnan(h) || isnan(t))

  {

    Serial.println(F("Failed to read from DHT sensor!"));

    return;

  }

  Serial.print(F("Humidity: "));

  Serial.print(h);

  Serial.println("%");

  Serial.print(F("Temperature: "));

  Serial.print(t);

  Serial.println(F("°C "));

  Serial.println("");

  delay(2000);

}


Wiring with Sensor Only

IMG_2150.MOV

Video of Sensor working

12/2 : The electronic part is the most important part of the whole project. Therefore, I started from the electronic part.  Since I did not know how to create the code for DHT22 sensor, I searched up online and used a code from the link below. I also used the pinout from the website and completed my wiring for the sensor. Then I imported the code into the Arduino and made sure that the libraries included in the code were installed. Then I uploaded the code into Arduino and made the data appear in the serial monitor.

Reference Link for Code: https://www.circuits-diy.com/interfacing-dht22-temperature-sensor-with-xiao-rp2040/#google_vignette

Testing Display

Code Example for Display

/**************************************************************************

 This is an example for our Monochrome OLEDs based on SSD1306 drivers


 Pick one up today in the adafruit shop!

 ------> http://www.adafruit.com/category/63_98


 This example is for a 128x64 pixel display using I2C to communicate

 3 pins are required to interface (two I2C and one reset).


 Adafruit invests time and resources providing this open

 source code, please support Adafruit and open-source

 hardware by purchasing products from Adafruit!


 Written by Limor Fried/Ladyada for Adafruit Industries,

 with contributions from the open source community.

 BSD license, check license.txt for more information

 All text above, and the splash screen below must be

 included in any redistribution.

 **************************************************************************/


#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels


// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

// The pins for I2C are defined by the Wire-library.

// On an arduino UNO:       A4(SDA), A5(SCL)

// On an arduino MEGA 2560: 20(SDA), 21(SCL)

// On an arduino LEONARDO:   2(SDA),  3(SCL), ...

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


#define NUMFLAKES     10 // Number of snowflakes in the animation example


#define LOGO_HEIGHT   16

#define LOGO_WIDTH    16

static const unsigned char PROGMEM logo_bmp[] =

{ 0b00000000, 0b11000000,

  0b00000001, 0b11000000,

  0b00000001, 0b11000000,

  0b00000011, 0b11100000,

  0b11110011, 0b11100000,

  0b11111110, 0b11111000,

  0b01111110, 0b11111111,

  0b00110011, 0b10011111,

  0b00011111, 0b11111100,

  0b00001101, 0b01110000,

  0b00011011, 0b10100000,

  0b00111111, 0b11100000,

  0b00111111, 0b11110000,

  0b01111100, 0b11110000,

  0b01110000, 0b01110000,

  0b00000000, 0b00110000 };


void setup() {

  Serial.begin(9600);


  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

    Serial.println(F("SSD1306 allocation failed"));

    for(;;); // Don't proceed, loop forever

  }


  // Show initial display buffer contents on the screen --

  // the library initializes this with an Adafruit splash screen.

  display.display();

  delay(2000); // Pause for 2 seconds


  // Clear the buffer

  display.clearDisplay();


  // Draw a single pixel in white

  display.drawPixel(10, 10, SSD1306_WHITE);


  // Show the display buffer on the screen. You MUST call display() after

  // drawing commands to make them visible on screen!

  display.display();

  delay(2000);

  // display.display() is NOT necessary after every single drawing command,

  // unless that's what you want...rather, you can batch up a bunch of

  // drawing operations and then update the screen all at once by calling

  // display.display(). These examples demonstrate both approaches...


  testdrawline();      // Draw many lines


  testdrawrect();      // Draw rectangles (outlines)


  testfillrect();      // Draw rectangles (filled)


  testdrawcircle();    // Draw circles (outlines)


  testfillcircle();    // Draw circles (filled)


  testdrawroundrect(); // Draw rounded rectangles (outlines)


  testfillroundrect(); // Draw rounded rectangles (filled)


  testdrawtriangle();  // Draw triangles (outlines)


  testfilltriangle();  // Draw triangles (filled)


  testdrawchar();      // Draw characters of the default font


  testdrawstyles();    // Draw 'stylized' characters


  testscrolltext();    // Draw scrolling text


  testdrawbitmap();    // Draw a small bitmap image


  // Invert and restore display, pausing in-between

  display.invertDisplay(true);

  delay(1000);

  display.invertDisplay(false);

  delay(1000);


  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps

}


void loop() {

}


void testdrawline() {

  int16_t i;


  display.clearDisplay(); // Clear display buffer


  for(i=0; i<display.width(); i+=4) {

    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);

    display.display(); // Update screen with each newly-drawn line

    delay(1);

  }

  for(i=0; i<display.height(); i+=4) {

    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);

    display.display();

    delay(1);

  }

  delay(250);


  display.clearDisplay();


  for(i=0; i<display.width(); i+=4) {

    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);

    display.display();

    delay(1);

  }

  for(i=display.height()-1; i>=0; i-=4) {

    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);

    display.display();

    delay(1);

  }

  delay(250);


  display.clearDisplay();


  for(i=display.width()-1; i>=0; i-=4) {

    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);

    display.display();

    delay(1);

  }

  for(i=display.height()-1; i>=0; i-=4) {

    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);

    display.display();

    delay(1);

  }

  delay(250);


  display.clearDisplay();


  for(i=0; i<display.height(); i+=4) {

    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);

    display.display();

    delay(1);

  }

  for(i=0; i<display.width(); i+=4) {

    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);

    display.display();

    delay(1);

  }


  delay(2000); // Pause for 2 seconds

}


void testdrawrect(void) {

  display.clearDisplay();


  for(int16_t i=0; i<display.height()/2; i+=2) {

    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);

    display.display(); // Update screen with each newly-drawn rectangle

    delay(1);

  }


  delay(2000);

}


void testfillrect(void) {

  display.clearDisplay();


  for(int16_t i=0; i<display.height()/2; i+=3) {

    // The INVERSE color is used so rectangles alternate white/black

    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);

    display.display(); // Update screen with each newly-drawn rectangle

    delay(1);

  }


  delay(2000);

}


void testdrawcircle(void) {

  display.clearDisplay();


  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {

    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);

    display.display();

    delay(1);

  }


  delay(2000);

}


void testfillcircle(void) {

  display.clearDisplay();


  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {

    // The INVERSE color is used so circles alternate white/black

    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);

    display.display(); // Update screen with each newly-drawn circle

    delay(1);

  }


  delay(2000);

}


void testdrawroundrect(void) {

  display.clearDisplay();


  for(int16_t i=0; i<display.height()/2-2; i+=2) {

    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,

      display.height()/4, SSD1306_WHITE);

    display.display();

    delay(1);

  }


  delay(2000);

}


void testfillroundrect(void) {

  display.clearDisplay();


  for(int16_t i=0; i<display.height()/2-2; i+=2) {

    // The INVERSE color is used so round-rects alternate white/black

    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,

      display.height()/4, SSD1306_INVERSE);

    display.display();

    delay(1);

  }


  delay(2000);

}


void testdrawtriangle(void) {

  display.clearDisplay();


  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {

    display.drawTriangle(

      display.width()/2  , display.height()/2-i,

      display.width()/2-i, display.height()/2+i,

      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);

    display.display();

    delay(1);

  }


  delay(2000);

}


void testfilltriangle(void) {

  display.clearDisplay();


  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {

    // The INVERSE color is used so triangles alternate white/black

    display.fillTriangle(

      display.width()/2  , display.height()/2-i,

      display.width()/2-i, display.height()/2+i,

      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);

    display.display();

    delay(1);

  }


  delay(2000);

}


void testdrawchar(void) {

  display.clearDisplay();


  display.setTextSize(1);      // Normal 1:1 pixel scale

  display.setTextColor(SSD1306_WHITE); // Draw white text

  display.setCursor(0, 0);     // Start at top-left corner

  display.cp437(true);         // Use full 256 char 'Code Page 437' font


  // Not all the characters will fit on the display. This is normal.

  // Library will draw what it can and the rest will be clipped.

  for(int16_t i=0; i<256; i++) {

    if(i == '\n') display.write(' ');

    else          display.write(i);

  }


  display.display();

  delay(2000);

}


void testdrawstyles(void) {

  display.clearDisplay();


  display.setTextSize(1);             // Normal 1:1 pixel scale

  display.setTextColor(SSD1306_WHITE);        // Draw white text

  display.setCursor(0,0);             // Start at top-left corner

  display.println(F("Hello, world!"));


  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text

  display.println(3.141592);


  display.setTextSize(2);             // Draw 2X-scale text

  display.setTextColor(SSD1306_WHITE);

  display.print(F("0x")); display.println(0xDEADBEEF, HEX);


  display.display();

  delay(2000);

}


void testscrolltext(void) {

  display.clearDisplay();


  display.setTextSize(2); // Draw 2X-scale text

  display.setTextColor(SSD1306_WHITE);

  display.setCursor(10, 0);

  display.println(F("scroll"));

  display.display();      // Show initial text

  delay(100);


  // Scroll in various directions, pausing in-between:

  display.startscrollright(0x00, 0x0F);

  delay(2000);

  display.stopscroll();

  delay(1000);

  display.startscrollleft(0x00, 0x0F);

  delay(2000);

  display.stopscroll();

  delay(1000);

  display.startscrolldiagright(0x00, 0x07);

  delay(2000);

  display.startscrolldiagleft(0x00, 0x07);

  delay(2000);

  display.stopscroll();

  delay(1000);

}


void testdrawbitmap(void) {

  display.clearDisplay();


  display.drawBitmap(

    (display.width()  - LOGO_WIDTH ) / 2,

    (display.height() - LOGO_HEIGHT) / 2,

    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);

  display.display();

  delay(1000);

}


#define XPOS   0 // Indexes into the 'icons' array in function below

#define YPOS   1

#define DELTAY 2


void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {

  int8_t f, icons[NUMFLAKES][3];


  // Initialize 'snowflake' positions

  for(f=0; f< NUMFLAKES; f++) {

    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());

    icons[f][YPOS]   = -LOGO_HEIGHT;

    icons[f][DELTAY] = random(1, 6);

    Serial.print(F("x: "));

    Serial.print(icons[f][XPOS], DEC);

    Serial.print(F(" y: "));

    Serial.print(icons[f][YPOS], DEC);

    Serial.print(F(" dy: "));

    Serial.println(icons[f][DELTAY], DEC);

  }


  for(;;) { // Loop forever...

    display.clearDisplay(); // Clear the display buffer


    // Draw each snowflake:

    for(f=0; f< NUMFLAKES; f++) {

      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);

    }


    display.display(); // Show the display buffer on the screen

    delay(200);        // Pause for 1/10 second


    // Then update coordinates of each flake...

    for(f=0; f< NUMFLAKES; f++) {

      icons[f][YPOS] += icons[f][DELTAY];

      // If snowflake is off the bottom of the screen...

      if (icons[f][YPOS] >= display.height()) {

        // Reinitialize to a random position, just off the top

        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());

        icons[f][YPOS]   = -LOGO_HEIGHT;

        icons[f][DELTAY] = random(1, 6);

      }

    }

  }

}



IMG_2154.MOV

Video of Display Working

12/3: I was not sure if the display is a good one. So I decided to use an example code to test the display. I first connected each pin of the display to the correct pin of the RP2040 chip and upload the example code into the microcontroller. The result shows that the display is not broken.

Combining the Wiring

Whole wiring for both Display and DHT22 Sensor

Combining The Codes

Final Code

#include "DHT.h"

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>


// Pin and type configuration for the DHT sensor

#define DHTPIN 27       // Digital pin connected to the DHT sensor

#define DHTTYPE DHT22   // Define DHT type (DHT22)


// DHT sensor object declaration

DHT dht(DHTPIN, DHTTYPE);


// OLED display configuration

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET -1    // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C // I2C address of the OLED display


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


void setup() {

  Serial.begin(115200);

  Serial.println(F("DHTxx test!"));


  // Initialize the DHT sensor

  dht.begin();

  delay(2000);


  // Initialize the OLED display

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

    Serial.println(F("SSD1306 allocation failed"));

    while (true); // Infinite loop if display initialization fails

  }


  // Display splash screen

  display.display();

  delay(2000); // Pause for 2 seconds

  display.clearDisplay();

}


void loop() {

  // Read temperature and humidity from DHT sensor

  float temperature = dht.readTemperature();  // Temperature in Celsius

  float humidity = dht.readHumidity();        // Humidity percentage


  // Check if readings are valid

  if (isnan(temperature) || isnan(humidity)) {

    Serial.println(F("Failed to read DHT sensor!"));

    display.clearDisplay();

    display.setCursor(0, 0);

    display.print(F("Failed to read DHT sensor!"));

    display.display();

    delay(2000);

    return; // Retry on the next loop iteration

  }


  // Debug output to Serial Monitor

  Serial.print(F("Temperature: "));

  Serial.print(temperature);

  Serial.print(F("°C "));

  Serial.print(F("Humidity: "));

  Serial.print(humidity);

  Serial.println(F("%"));


  // Display the sensor data on the OLED screen

  display.clearDisplay();

  display.setTextSize(1);                // Normal 1:1 pixel scale

  display.setTextColor(SSD1306_WHITE);  // White text color

  display.setCursor(0, 0);


  display.print(F("Temp: "));

  display.print(temperature);

  display.print(F(" C"));


  display.setCursor(0, 16);

  display.print(F("Humidity: "));

  display.print(humidity);

  display.print(F(" %"));


  display.display();


  delay(2000); // Wait 2 seconds before updating

}

IMG_2166.MOV

Video of the whole Electronics

12/4: I combined the code together using ChatGPT. It helped me combined the code and helped me make the data collected from the sensor appear on the display.

IMG_2177.MOV

Video of Display rotating 180 degrees

12/5: I started to think about designing my case and my PCB board. I figured out that I needed to rotate the display 180 degrees in order to make the screen face upward instead of downward. I asked ChatGPT for help again.

12/6: Building PCB Schematic using Kicad

Step 1: Creating Symbols

Go to Symbol Editor on the left column toolbar and search up the component you need to put the PCB board.

I put a DHT22 sensor, Xiao Seeed RP2040, and a 4-pin header to connect my display with my PCB Board.

Step 1.1: Import symbols to Kicad

Since there was no DHT22 sensor symbol in the symbol library for Kicad, I had to find one myself online.

I found a DHT22 sensor symbol in a website called Snap Magic.

The instructions of importing symbols into Kicad

I downloaded the file into Downloads

I went to Preference->Manage Symbol Library->Browse Library->Select the .kicad_sym file->open. The symbol was imported in Kicad.

Step 2: Connect the Components

After I found all the component, I use the wire function and connected the matching pin of one component to another to form a circuit.

Step 3: Draw the Border

I draw a box around the whole circuit as the edge to make sure I don't exceed the edge of the board.

Week3: 12/9-12/15

12/9: Creating the PCB file

I imported the schematic file to the PCB file. I started to wire between my profile. However, I always meet the problem that the wires are crossing eachother which is not allowed. Then I figured out a trick: I could actually go through where the component is gonna be after soldering. Eventually, I managed to fix the problem and created a PCB board.

Final wiring of my PCB board

Final 3D View of My PCB Board

12/10: Milling the PCB Board

Step 1: Download the drill files and imported them into Bantom. The top is the .F_Cu file. The Outline is the edge cut file. The Holes is the combined file of PTH and NPTH files.

Step 2: Add the bits you are using and chnage the settings as needed

Step 3: Put the copper board on the drilling platform using tape. Make sure it is sticked firmly to the platform.

Step 4: Press "Start" and chnage the bits when the app tells you to.

IMG_2204.MOV

Video of milling the PCB board

Final look of my PCB board

12/11: Testing the PCB Board

IMG_2207.MOV

After milling the board, in order to make sure the board work, I used the continuity test in order to test if there's conductivity through each pin using the multimeter. There's one place that the track was so thin that you can barely see the sopper on it. However, when I place the test on the pins, it worked. Next, I am going to solder my components on.

12/12: Soldering components onto the PCB Board

First, I decided to solder the chip first. I used solder paste to solder it. First, I put some solder paste on the board. Then, I put the chip onto the solder paste and then use the soldering iron to melt the solder paste.

The PCB board after I soldered 10k resistor, RP2040, and DHT22 sensor on.

Back side of the PCB

12/13: Troubleshooting the PCB

When I finished soldering the DHT22 sensor onto the PCB board, I found out that it did not pass the continuity test. Then I figured out that the copper was detached from the board. I tried to use solder to reconnect the PCB board and the copper. Unfortunately, it did not work. The thin copper track also came off next day I finished soldering.

12/14: Soldering using a PCB Port Board

Step 1: Put all the components onto the board to see if the circuit would work

Step 2: Strip the wire into the appropriate length and solder onto the board. Make sure the wire are connecting to the right place.

The board after I solder all of my components and wires

Back side of the board after soldering

IMG_2243.MOV

Video of the Board working 

Case Inspiration: https://www.youtube.com/watch?v=35zs2J3Prxo created by The Wrench

12/15: 3D Designing using Fusion 360 and 3D Printing

Creating the Box

Draft of my 3Ddesign

Before I started designing my case, I first drew a sketch in Notability. I measured all of the dimensions I needed for the case using a caliper. Then I took all the key factor into account, such as the thickness of box and calculated the final dimensions of my box and the cap.

Step1: Use caliper to measure the dimensions of the board and created a rectangle with the same dimension in Fusion 360 using "Create Sketch" feature.

Step 2: Extrude the rectangle and make it into a rectangular prism.

Step 3: Create a rectangle on top

Step 4: Extrude the rectangle and make the prism a box

Step 5: Create a rectangle in the front of the prism. In order to make sure the rectangle is in the middle, use construction feature to help.

Step 6: Extrude the rectangle for 2mm

Step 7: Create a rectangle on the side of the rectangle.

Step 8: Extrude the rectangle for 2mm

Step 9: Create a rectangle and use "Line" feature to separate the rectangle into congruent rectangles

Step 10: Extrude the selected rectangles

The look on the back of the box after extruding

Step 11: Add fillet to the edges of the box for 2.5mm

Final look of my box

Creating the Cap of the Box

Step1: Create a rectangle and extrude it using the dimensions measured by the caliper

Step2: Add an offset plane on the top of the rectangular prism

Step 3: Create a rectangle on the offset plane. I made the distance between the rectangle and the edge 2.1mm because I want to leave a little space between the cap and the case. It iseasier to open the cap.

Step 4: Extrude the rectangle for 5mm

Step 5: Add fillets to the edges of the cap

Final look of the cap

3D Printing

Step 1: Import the STL file into Bambu software

Step 2: Check all the settings and select the right printer and lick "Slice the plate". After checking, click "Print"

IMG_2252.MOV

Video of 3D printing

Fron Side of the Final Product

Back side of the Final Product

IMG_2265.MOV

Final Video of the Final Product

Problems Encountered

IMG_2248.MOV

First Version of the Case (not working)

I printed different versions of my cases for 3 times. First time, the pace for the USB C is not matching. I thought it was because the width of the box is too small to make the board lay flat so that the USB C is in the wrong position.

I changed the width of the box and printed again and I found out it was not because of the small space of the box. It is because I calculated the position of the USB C wrong. Then I printed the third time. It was right this time.

Final Summary

This is my first time actually doing my project without any pre-designed instructions. The only thing I have is the video that I chose from the beginning of this project. Besides, there's a lot of changes I needed to change from the original video. It was a interesting challenge to me and I learned a lot of things from it.

Before, when I faced some problems or challenges, I would immediately ask my teacher for help. However, this time, the strategy did not work. Since everybody was doing a different project, we encountered different problems and it was impossible for teachers to know everything. I had to learn how to solve my problems myself. I figured out that searching up on the Internet is the best way to solve my problem when building this project. 

The process of completing a big project is to plan first and then start to build the core of the project which is usually the electronic part and then troubleshoot the problems you encountered. I learned that I need to improve myself on time management. Besides, I also learned that it is better to do your documentation while you are doing your project since you are gonna remember more details at that time. This project teaches me the basics of building circuit, creating a code and how to code a display, which is very helpful for my Fablab project.