Principles and Practices
- Plan and sketch a potential final project
This is where I will start defining my final project idea and start to get use to the documentation process.
Initial Project Idea - Week 1
Rough Sketch for Project Idea

Initial Research
Research on Hardware possibility - Week 3
A good source to acquire datasheets from: alldatasheet
1. Temperature Monitoring and Control: Create firmware using the Arduino IDE that utilizes an ADC channel to read the LM35
sensor.
Since the ESP32 has a **12-bit ADC** (4096 levels) and typically operates with **Vref =
3.3V**, the raw ADC reading needs to be converted to a meaningful temperature value.
However, due to the ESP32's **non-linear ADC response**, the LM35 sensor may require a
voltage offset correction. A **diode-based offset circuit** (e.g., two diodes in series)
is recommended to shift the sensor output voltage into a more linear ADC range.
Corrected Temperature Formula:
Temperature (°C) = ((ADC_Value * Vref) / ADC_Max - V_offset) * 100
Where:
- Vref = 3.3V** (ESP32 reference voltage)
- ADC_Max = 4095> (12-bit ADC resolution)
- V_offset ≈ 1.4V (using two diodes in series, if required for correction)
source:
LM35 Sensor Interfacing with ESP32 - Electronic WingsSet a threshold temperature (resource: Normal CPU Temperature); if the measured temperature exceeds this threshold, adjust the PWM duty cycle to increase fan speed automatically and display notification on the display.
Create PWM signals for every fan using the ESP32's PWM capabilities.
To optimize cooling, map the temperature data to a PWM duty cycle. For instance, if the temperature is extremely high, set the duty cycle close to 100%.
Potential Hardware Components
Research on PCB Production - Week 6
Stress Test Laptop's CPU


Exploring unfied Power Supply with Voltage Regulation
- 12V → Required for the fans.
- 5V → Used for ESP32 or Rasberry Pi Pico microcontrollers.
- 3.3V → Needed for sensors, and the display.
How a Voltage Regulator Works
- Linear Voltage Regulators (e.g., LM317, 7805, 1117-3.3V): simple mechanism where they use a transistor controlled by a negative-feedback circuit to produce a specified output voltage, but less efficient as they dissipate excess energy as heat.
- Switching Voltage Regulators (e.g., Buck Converters, LM2596 ): consist of a power switch, an inductor, and a diode to transfer energy from input to output. They are highly efficient since they convert energy with minimal heat loss. This is usually done by storing and releasing energy through an inductor.
Example Circuit Design
- 12V Power Input ├── 12V DC Fan (Direct Connection) ├── Step-Down Regulator LM2596 (Buck Converter) → 5V (Microcontroller and sensors) ├── From the Pi Pico W → 3.3V (OLED display)

2D and 3D Modeling
Designing LapTable Prototype for CNCing - Week 7

Electronics Production - Week 8
For this week, I produced the PCB that I am planning to implement in my final project. As a microcontroller I am using the Raspberry Pi Pico:. I added few extra pinheaders in case I decide later to integrate few hardward components onto my PCB. Furthermore, I soldered the capacitors that will be necessary to regulate the voltage using Linear Voltage Regulator DPAK. This will ensure providing stable power to the fan (12v), as well as the microcontroller (5v). However, I still need to procur the temperature sensors LM35 temperature sensor, the Mosfet and the diode for the PWM control of the fan. Moreover, the fan and the OLED display still have to be ordered in order to test the the functionality of the circuit as a first step before adding any modifications onto it.
PCB Soldered and Tested - Week 9
Input Device
DS18B20 Sensor Test with my personal PCB

Stress and Benchmark Test





Output Device - Week 10
Testing with DC 12V fan and the Voltage Regulator
Progress on Final Arduino Code - Week 11
Testing the Fan's Threshold for PWM Duty Cycle
/*
Analog input, analog output, serial output - Modified
Reads an analog input pin, maps the result to a range from 0 to 255 and uses
the result to set the pulse width modulation (PWM) of an output pin.
Also prints the results to the Serial Monitor.
The circuit:
- potentiometer connected to analog pin 0.
Center pin of the potentiometer goes to the analog pin.
side pins of the potentiometer go to +5V and ground
- LED connected from digital pin 9 to ground through 220 ohm resistor
created 29 Dec. 2008
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
https://docs.arduino.cc/built-in-examples/analog/AnalogInOutSerial/
*/
// These constants won't change. They're used to give names to the pins used:
const int analogInPin = A1; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 16; // Analog output pin that the Mosfet is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}
void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
// map it to the range of the analog out:
// outputValue = map(sensorValue, 0, 1023, 0, 255);
outputValue =230; // to test the Fan's threshold for PWM
// change the analog out value:
analogWrite(analogOutPin, outputValue);
// print the results to the Serial Monitor:
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
// wait 2 milliseconds before the next loop for the analog-to-digital
// converter to settle after the last reading:
delay(2);
}
Final Code Draft Explanation

/*
The following code is a draft for my final project:
- Drive a fan based on the mean temperature recorded by two DS18B20 temperature sensors
- To control the speed of the fan, it is mapped to the PWM range of 230 to 255, where a minimum temperature threshold is set and an increment of 20% speed increase corresponds to 1°C temperature increased
- Information about fan status and mean temperature is shown on an OLED01.3 display
*/
#include
#include
#include
#include
// I2C OLED Setup
#define I2C_ADDRESS 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Initialize the OLED display using the default I2C bus (Wire)
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
// DS18B20 Temperature Sensors
// Sensors are connected to GPIO26 and GPIO27
MicroDS18B20<26> sensor1;
MicroDS18B20<27> sensor2;
// LED and Fan Definitions
#define LED_PIN 22 // LED to indicate temperature threshold
#define FAN_PIN 16 // DC fan controlled via PWM
// Temperature thresholds for fan control
const float tempThreshold = 23.0; // Fan starts running at 23°C
const float maxTempForFan = 27.0; // Fan reaches 100% speed at 27°C
// Global variable to track when the fan turns on (in milliseconds)
unsigned long fanOnStartTime = 0;
void setup() {
Serial.begin(9600);
// Initialize I2C bus
Wire.begin();
// Initialize the OLED display; if not found, pause execution
if (!display.begin(I2C_ADDRESS, true)) {
Serial.println(F("OLED not found"));
while (1);
}
// Configure the LED and Fan pins as outputs
pinMode(LED_PIN, OUTPUT);
pinMode(FAN_PIN, OUTPUT);
// Display a startup message
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SH110X_WHITE);
display.setCursor(0, 10);
display.println("Starting...");
display.display();
delay(2000);
}
void loop() {
// Request temperature readings from both sensors
sensor1.requestTemp();
sensor2.requestTemp();
// Wait for conversion.
delay(1000);
// Variables to hold temperature values and sensor status
float temp1 = 0, temp2 = 0;
bool sensor1_ok = false, sensor2_ok = false;
// Read sensor1
if (sensor1.readTemp()) {
temp1 = sensor1.getTemp();
sensor1_ok = true;
} else {
Serial.println("Error reading sensor1");
}
// Read sensor2
if (sensor2.readTemp()) {
temp2 = sensor2.getTemp();
sensor2_ok = true;
} else {
Serial.println("Error reading sensor2");
}
// Validate sensor data
bool validData = sensor1_ok && sensor2_ok;
float meanTemp = 0;
if (validData) {
meanTemp = (temp1 + temp2) / 2.0;
Serial.print("t1: ");
Serial.print(temp1);
Serial.print(" C, t2: ");
Serial.print(temp2);
Serial.print(" C, Mean: ");
Serial.print(meanTemp);
Serial.println(" C");
} else {
Serial.println("Cannot compute mean: one or more sensor readings failed");
}
// Variables for fan control
bool fanOn = false;
int fanSpeedPercent = 0;
int pwmValue = 0; // PWM value (0 - 255)
// Only control the fan if sensor data is valid
if (validData && (meanTemp >= tempThreshold)) {
digitalWrite(LED_PIN, HIGH); // Turn on LED
// Calculate fan speed percentage based on temperature between threshold and maxTempForFan
if (meanTemp >= maxTempForFan) {
fanSpeedPercent = 100;
} else {
fanSpeedPercent = (int)(((meanTemp - tempThreshold) / (maxTempForFan - tempThreshold)) * 100);
}
// Map the fan speed percentage to PWM value in the range 230 to 255
pwmValue = map(fanSpeedPercent, 0, 100, 230, 255);
analogWrite(FAN_PIN, pwmValue);
fanOn = true;
// Record fan activation time if it just started
if (fanOnStartTime == 0) {
fanOnStartTime = millis();
}
} else {
digitalWrite(LED_PIN, LOW); // Turn off LED
analogWrite(FAN_PIN, 0); // Turn off fan
fanSpeedPercent = 0;
fanOnStartTime = 0;
}
// Update the OLED display
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
if (validData) {
// First line: Mean temperature with unit Celcius degrees
display.print("Mean:");
display.print(meanTemp, 1);
display.print("C");
// Second line: Fan status/speed
display.setTextSize(2);
display.setCursor(0, 35);
if (fanOn) {
// For the first 2 seconds, display "Fan: ON"
if (millis() - fanOnStartTime < 2000) {
display.println("Fan: ON");
} else {
display.print("Speed:"); //Afterwards, show the fan speed percentage
display.print(fanSpeedPercent);
display.println("%");
}
} else {
display.println("Fan: OFF");
}
} else {
display.println("Sensor error");
}
display.display();
delay(1000);
}
Reflection and Struggles - Week 11
Assembling LapTable 1.0 Prototype - Week 12


Work Completed Up to the Midterm
I tested and experimented with the following aspects of my Lap Table:
- PCB design and production: created a board to control the fan (output device) using temperature-sensor readings (input device).
- Lap Table prototype 1.0: cut the first design and evaluated it.
- Temperature-benchmark tests: determined the threshold for driving the fan in Arduino IDE.
- DS18B20 sensor tests: verified the temperature sensor with a test fan.
- PWM mapping: mapped temperature values to the fan-speed range.
Work Remaining After the Midterm
I still need to complete the following tasks for my Lap Table:
- Redesign the Lap Table: improve stability and add new features.
- Real-fan testing: map PWM values from the DS18B20 sensor to the speed of my 12 V DC fan.
- Power-supply testing: evaluate a USB-PD (Power Delivery) trigger module with the electronics setup.
- Cable management and electronics organizer: design and 3-D-print pieces to be integrated into the table, keeping ergonomics in mind.
- Final evaluation: critically assess strengths and weaknesses to inform future projects.
Materials
Qty | Description | Price | Link |
---|---|---|---|
one | Raspberry Pi Pico W | 6.99€ | Raspberry Pi Pico W |
one | Mosfet SOT-23 | 0.37€ | Mosfet |
two | Option1: Temperature Sensors LM35 | 5.50€ | Temperature Sensor LM35 |
two | Option2: DS18B20 Temperature Sensor Module | 2,40 € | DS18B20 shield |
one | Diode SOD123 | 0.25€ | SOD123 Diode |
one | 60x60x25mm / 12V / 0,026A Fan | 2.60€ | DC 12V Fan |
one | USB PD (Power Delivery) trigger module | 11.20€ | USB PD (Power Delivery) trigger module |