Michelle's double transducer from a top-down view (thermistor on the left red breadboard, magnet on the right end of the car)
Jaden's double transducer from a top-down view (thermistor on the left red breadboard, magnet on the right end of the car)
Heat from the incandescent bulb is read by the thermistor
LED is hidden by a dark box to avoid ambience light influences on the transducer
Magnet attached to the car moves based on the LED's brightness
Using the incandescent bulb as a heat source, I demonstrate warming up the thermistor to drive the LED inside the black box, which then drives the servo motors of the car to move the magnet forward and back. My LED is not very bright, so not much movement is driven by the LED. Once the box is removed to show the LED, the ambient light triggers the photoresistor to have a much stronger reaction, causing the car to move back and forth quickly. I also demonstrate the functionality of the skip-the-middle button by pressing down on it, thus stopping the ambient light from affecting the movement of the car.
Using a incandescent lightbulb to generate heat which the Thermistor will detect the change in temperature. The higher the temperature the brighter the blue LED gets which a photoresistor reads (a black box is covering the LED and photoresistor to reduce ambient light to get an more accurate reading), the photoresistor then sends that data to the two large servo motors that drive the wheels (since there is some blinking going on with the LED, it causes the car to rock back and forward). On the car is a straw with a magnet on it, therefore increasing the magnetic force as it drives forward and vice versa.
This machine converts temperature into light, which is then transformed into a magnetic force.
When the machine senses warmer temperatures, the LED inside of the black box turns brighter. This drives the motors on the back two wheels of the car to turn forwards, which brings the magnet closer to the edge of the board. Thus, a magnetic field is created. When the machine senses colder temperatures, this process is flipped. The LED turns dimmer, driving the motors backwards and pulling the magnetic force back towards the center of the board.
Trying to figure out the wiring
In early testing, the range on the thermistor was to high to change the LED's brightness with just our hands so we used a heat gun to test if the code was working correctly
Finally starting the final assembly with a freshly soldered board
Debugging the code to try make the car less jittery
Our first successful wired setup after the car was built
Our first successful wired setup after the car was built (angle 2)
Right after the car was built, ain't she a beaut?
Creating this double transducer was harder than it originally appeared to be. From a software perspective, we noticed the effects of driving two large servo motors almost instantly. We initially believed that the thermistors were unstable, as our analog reads were returning wildly fluctuating values where the temperature readings would oscillate within an approximate range of 5 even when we didn't touch them at all. Because we didn't realize that the hardware could affect our readings in this way, we tried averaging out the thermistor values to get a more steady flow of information. However, the true solution to our problem was to give the motors their own 6V power supply. From this experience, we learned that even when things are wired correctly, problems can still arise from the hardware side.
Everything was moving pretty smoothly until the day before we had to present our projects, it started with us accidentally breaking the wood for the second car, which we just glued back together but for some reason, one of the wheels refused to glue to the axles we made. After trying super glue we ended up carving the wooden axel on one side so it could just be slotted into the wheel – this worked. Another problem we ran into that day was when we were testing our board (before soldering) the car just stopped working, after a lot of debugging we realized we had two of the wires switched that connected to the car. Each of us soldered a board but both times we ran into a problem that required desoldering of some capacity, so it was a good learning experience.
We are super happy that everything worked on the day of the presentation, other than learning that our green LED is significantly less bright than the blue LED – good to know for future projects. While there ended up being frustrations and problems along the way, we never had to pivot away from our original idea. Another thing we learned was how long just fabrication takes, you're not just home-free after getting the code to work – if anything the coding took the least amount of time. This was a great project to get us ready for the rest of the class, giving us a taste of what is possible using an Arduino, giving us a base that we can build of off for the next two projects.
/*
Project Title: Double Transducer: Temperature to Magnetic Field
Authors: Michelle Chen and Jaden Scutero
Description: When the transducer senses heat through the thermistor, it brightens an LED
depending on how hot the temperature it senses is. The LED brightness is then read by a
photoresistor, which then sends that signal to the servo motors of the car to drive the
magnet (aka magnetic force) closer or further from the edge of the board. Warmer
temperatures means a brighter LED, which then means the magnet is moved towards the edge
of the board. Colder temperatures will do the opposite.
Pin mapping:
Arduino pin | role | details
------------------------------
A0 input Thermistor
A1 input Photoresistor
11 input Button
3 output LED
10 output Left Servo Motor
8 output Right Servo Motor
Released to the public domain by the authors, February 2025
Michelle Chen, mfchen@andrew.cmu.edu
Jaden Scutero, jscutero@andrew.cmu.edu
*/
/* Pin mapping section of code, creating variables to store
pin numbers. Note that the "const int" data type is used
instead of plain "int" because the pin numbers are
constant--they will never change in the code.
All-caps names are used by convention for variables whose
values won't change.
Variables values are constrained to allow the output LCD screen to display correctly.
*/
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// initializing our pin values
const int THERMISTORPIN = A0,
PHOTORESISTORPIN = A1,
LEDPIN = 3,
LEFTMOTORPIN = 10,
RIGHTMOTORPIN = 8,
BUTTONPIN = 11;
// initializing our variables
int temp,
brightIN, // photoresistor --> bright comes in
brightOUT, // LED --> bright goes out
leftMotorPos,
rightMotorPos,
buttonVal,
lcdIn,
lcdMiddle,
lcdMiddleOut,
lcdOut;
LiquidCrystal_I2C screen(0x27, 16, 2);
int i,
m,
mo,
o;
unsigned long delayTime = 150;
unsigned long lastUpdateTime = 0;
Servo LeftMotor;
Servo RightMotor;
void setup() {
Serial.begin(9600);
pinMode(THERMISTORPIN, INPUT);
pinMode(LEDPIN, OUTPUT);
pinMode(THERMISTORPIN, INPUT);
LeftMotor.attach(LEFTMOTORPIN);
RightMotor.attach(RIGHTMOTORPIN);
pinMode(BUTTONPIN, INPUT_PULLUP);
// initialize the screen (only need to do this once)
screen.init();
// turn on the backlight to start
screen.backlight();
}
void loop() {
readInputs();
updateInternalState();
driveOutputs();
reportBack();
delay(5);
}
void readInputs(){
temp = analogRead(THERMISTORPIN);
brightIN = analogRead(PHOTORESISTORPIN);
brightIN = constrain(brightIN, 150, 700);
buttonVal = digitalRead(BUTTONPIN);
}
void updateInternalState(){
temp = constrain(temp, 620, 660);
i = map(temp, 620, 660, 99, 1);
brightOUT = map(temp, 620, 660, 255, 1);
m = map(brightOUT, 255, 1, 90, 1);
// if button is pressed, ignore light
if (buttonVal == HIGH){
leftMotorPos = map(temp, 620, 660, 175, 5);
rightMotorPos = map(temp, 620, 660, 5, 175);
}
}
void driveOutputs(){
if (buttonVal == LOW){
leftMotorPos = map(brightIN, 150, 700, 175, 5);
rightMotorPos = map(brightIN, 150, 700, 5, 175);
}
mo = map(brightIN, 150, 700, 99, 1);
o = map(leftMotorPos, 175, 5, 99, 1);
// we want to delay the motors to allow them time to turn
if (millis() >= lastUpdateTime + delayTime){
lastUpdateTime = millis();
delay(delayTime);
analogWrite(LEDPIN, brightOUT);
Serial.println(temp);
LeftMotor.write(leftMotorPos);
RightMotor.write(rightMotorPos);
}
}
void reportBack(){
screen.clear();
screen.home();
screen.print("i: ");
screen.setCursor(6, 0);
screen.print("m: ");
screen.setCursor(12, 1);
screen.print("o: ");
screen.setCursor(2, 0);
screen.print(i);
screen.setCursor(8, 0);
screen.print(m);
screen.setCursor(8, 1);
screen.print(mo);
screen.setCursor(14, 1);
screen.print(o);
}