Useful Links
Carvera PCB Tutorial
gerber2img
Files
PCB Traces.png
PCB Edges.png
I initially wanted to create a device that could measure the temperature of liquids. However, I didn't fully understand how thermistors worked until after I had already built the first version of the board.
How a Thermistor Works: A thermistor is a temperature-sensitive resistor whose resistance changes with temperature. Most thermistors are NTC (Negative Temperature Coefficient), meaning their resistance decreases as temperature increases. To read a thermistor with a microcontroller, you create a voltage divider circuit: one fixed resistor (typically 10kΩ) and the thermistor are placed in series between power (3.3V) and ground. The microcontroller's analog pin reads the voltage at the junction between them. As temperature changes, the thermistor's resistance changes, which changes the voltage at this junction. The microcontroller converts this analog voltage to a digital value (0-1023 on most boards), and then mathematical formulas (like the Steinhart-Hart equation or Beta parameter equation) convert the resistance back into temperature.
I had initially designed a custom PCB using an AVR128DB32 microcontroller, but encountered multiple design errors including insufficient copper clearance and a ground air wire (an unconnected trace). Christof was instrumental in catching some of these errors before fabrication, which saved me from printing a completely unusable board. However, I struggled to fix all the design issues, so I decided to pivot to using a Seeed Xiao RP2040 development board instead, which simplified the design significantly.
When I milled my first board, it had many burrs and rough edges - the cuts were not clean at all. Christof helped troubleshoot the milling machine, and after switching to a different end mill, the board cut beautifully and required no sanding. This demonstrated how much the quality and condition of tools affects the final product.
After assembling the board, I realized that I hadn't connected the OLED display to any of the correct pins. I had to redesign and mill a third version to get the pin connections correct - third time was the charm.
Unfortunately, my assembled board does not work properly. After several days of troubleshooting, I've identified two major issues:
1. A0 Pin Failure: The A0 analog pin appears to be damaged or non-functional. When nothing is connected to it, it should read random floating values, but instead it consistently reads "2" (out of 1023). When the thermistor circuit is connected, it shows extreme and unchanging temperature values (around 554°F), regardless of whether I heat the thermistor. This suggests the pin is stuck at a near-zero voltage. It could also be an issue with the 10k resistor.
2. OLED Display Not Working: The OLED screen won't turn on at all, despite everything appearing to be wired correctly both visually and when tested with a multimeter. The display is receiving power (verified with multimeter between VCC and GND), and the I2C connections to D4 (SDA) and D5 (SCL) appear correct. However, I2C scanner code cannot detect any device on the bus.
While using AI tools like Claude to generate debugging code was helpful in providing different approaches to tests and code modifications, I found myself going in circles. The AI would often suggest the same methods and couldn't explain why the meter reading appeared correct, yet nothing was functioning properly. Without a solid foundational knowledge of I2C protocols, voltage dividers, and microcontroller architecture, I struggled to effectively interpret the results and determine the next steps.
Useful Links
Carvera PCB Tutorial
gerber2img
Files
PCB Traces.png
PCB Edges.png
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED Display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // No reset pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Thermistor settings
#define THERMISTOR_PIN A0 // Analog pin connected to thermistor
#define SERIES_RESISTOR 10000 // Value of the series resistor (10K ohm)
#define THERMISTOR_NOMINAL 10000 // Resistance at 25°C (10K ohm)
#define TEMPERATURE_NOMINAL 25 // Temperature for nominal resistance (25°C)
#define B_COEFFICIENT 3950 // Beta coefficient of the thermistor
void setup() {
Serial.begin(115200);
// Initialize OLED display (0x3C is the common I2C address)
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Loop forever if display fails
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Thermistor Ready!");
display.display();
delay(2000);
}
void loop() {
// Read analog value from thermistor
int analogValue = analogRead(THERMISTOR_PIN);
// Convert to resistance
float resistance = SERIES_RESISTOR / ((1023.0 / analogValue) - 1);
// Calculate temperature using Beta parameter equation
float steinhart;
steinhart = resistance / THERMISTOR_NOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= B_COEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURE_NOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // Convert to Celsius
// Convert to Fahrenheit (optional)
float fahrenheit = steinhart * 9.0 / 5.0 + 32.0;
// Display on OLED
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.println("Temperature:");
display.setTextSize(2);
display.setCursor(0,20);
display.print(steinhart, 1);
display.println(" C");
display.setCursor(0,45);
display.print(fahrenheit, 1);
display.println(" F");
display.display();
// Also print to Serial Monitor
Serial.print("Temperature: ");
Serial.print(steinhart);
Serial.print(" °C / ");
Serial.print(fahrenheit);
Serial.println(" °F");
delay(1000); // Update every second
}
Front of PCB
Back of PCB
First Circuit Schematic
Original Design Issues