Double Transducer: Distance to Heat
Allison and Tippi
Final images
Tippi's Double Transducer
Allison's Double Transducer
Detail photos
Breadboard and connected incandescent bulb
The three parallel ultrasonic rangers, up close
Middle step soldered component close up.
Neopixel ring attached under the lego board, facing the color sensor.
Final project movies
Tippi Li's Double Transducer
In the video, I altered the input of linear distance by moving my hands away and closer to the ultrasonic ranger (a sensor that measures its distance to any objects, in this case my hand). When the hand is detects closer to the sensor, the RGB LED and bulb shines brighter. Conversely, when the hand is detects closer to the sensor, the RGB LED and bulb dims. Then I pressed the button to skip the middle step (color). As shown in the video, the distance to the ultrasonic ranger is mapped directly to the brightness of the bulb. Finally, I covered the color sensor with my fingers and altered the input of distance, the brightness of the bulb did not change. The bulb changed brightness when I uncovered the color sensor again, showing that the middle step is working properly.
Allison Feldman's Double Transducer
In this video, I demonstrate the relationship between the red-detecting ultrasonic ranger, the bottom of the three, the LED ring, and the incandescent bulb. The closer I move my hand to the ultrasonic ranger, the brighter the LED ring shines red. The color sensor then picks up on the amount of red emitted by the LED ring and maps that to a specific bulb brightness. The more red detected, the brighter the bulb. If i were to hold my had over the top (blue) ultrasonic ranger, the LED ring shines blue, but the incandescent bulb should shine minimally, if at all.
Narrative description
This double transducer turns linear distance into color, then turns color into heat.
The first transducer uses an ultrasonic ranger to detect the distance of any object to the machine. When it detects something getting closer, it adjusts the RGB LED to emit a color with higher intensity, indicating shorter distances with brighter colors. Conversely, when it detects something getting further away, the RGB LED changes to a color with lower intensity, reflecting longer distances with dimmer colors.
The second transducer detects the color of the rgb LED. When the red value is high, the bulb shines and heat up. When the red value is low, the bulb dims and cools down.
When the push button on the breadboard is pressed, the software skips the middle step(color) and directly turn linear distance into heat. When the distance to the ultrasonic ranger labeled 'R' is long, the bulb heats up. When the distance to the ultrasonic ranger is short, the bulb cools.
Progress images
In class testing for the middle step of the double transducer: producing color with a neopixel ring and reading the color with a color sensor.
At this stage, we finally get to connect everything together and testing the program as a whole.
Testing the first transducer: distance to color. We tried mapping the red, green and blue value of the neopixel ring to three separate distance values measured by the ultrasonic rangers.
This stage of the project involved testing our color sensor independently from the rest of the hardware components.
Discussion
In our physical computing project, we created a double transducer that turns linear distance into color, and then translates that color into heat. Initially, we aimed to use three ultrasonic sensors to map RGB values individually, but we quickly found that this setup involved a lot of repetitive work and made it harder to see a clear link between distance input and color output. To simplify, we decided to work with just one ultrasonic sensor and let it control a single color channel. This change made it much easier to see the direct connection between our input and output, allowing us to focus more on the core transduction process.
This project has been a meaningful learning experience, bringing together my knowledge in electronics and Arduino coding. At first, debugging was a major challenge since it wasn’t always clear whether issues is from hardware connections, sensor accuracy, or coding errors. I found myself spending a lot of time figuring out what went wrong, which sometimes felt overwhelming. However, by diving into Arduino library examples and searching online, I picked up new strategies to isolate and resolve problems. For example, I learned to check each component of the setup individually—starting with basic connections, then verifying sensor output, and finally looking into code adjustments.
This project gave me a much clearer sense of how different parts of the system work together. I also became more comfortable with trial-and-error as a tool. Overall, this project has really improved my confidence in debugging and troubleshooting, skills I know will be valuable in future projects. Now, I feel better prepared to tackle more complex setups, knowing that I can rely on my experience and problem-solving methods to work through challenges.
Functional block diagram and electrical schematic
Code
/*
Project Title: Double Transducer: Distance to Heat
Authors: Allison Feldman and Tippi Li
Description: The first transducer uses an ultrasonic ranger to detect the distance of any object to the machine.
When it detects something getting closer, it adjusts the RGB LED to emit a brighter color, indicating shorter
distances with brighter colors. Conversely, when it detects something getting further away, the RGB LED changes
to a color with lower intensity, reflecting longer distances with dimmer colors.
Arduino | Role | Details
-------------------------
2 input BUTTONPIN
3 input NEORINGPIN
5 output MOSFETPIN
6 output Trig Pin
7 output Echo Pin
8 output Trig Pin
9 output Echo Pin
11 output Trig Pin
12 output Echo Pin
*/
#include <NewPing.h> // Ultrasonic Ranger
#include <Adafruit_NeoPixel.h> // Neo Pixel Ring
#include <Arduino_APDS9960.h> // Color Sensor
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LCD Screen
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
//---------------------------------------------------
#define SONAR_NUM 3
#define MAX_DISTANCE 40 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar[SONAR_NUM] = { // Sensor object array.
NewPing(6,7, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(8,9, MAX_DISTANCE),
NewPing(11,12, MAX_DISTANCE)
};
//-------------------------
#define NEORINGPIN 3
#define NUMPIXELS 12
Adafruit_NeoPixel ring(NUMPIXELS, NEORINGPIN, NEO_GRB + NEO_KHZ800);
//-------------------------
#define MOSFETPIN 5 // Mosfet: to control the brightness of bulb
#define BUTTONPIN 2 // Push Button: skip middle step(color)
//-------------------------
LiquidCrystal_I2C screen(0x27, 16, 2); // Display I/O and middle step value
//-------------------------
void setup() {
Serial.begin(9600);
ring.begin();
ring.show();
ring.setBrightness(50);
while (!Serial);
if (!APDS.begin()) {
Serial.println("Error initializing APDS-9960 sensor.");
}
// initialize screen
screen.init();
screen.backlight();
}
void loop() {
//Ultrasonic Ranger
delay(50);
int dist_r = sonar[0].ping_cm();
int dist_g = sonar[1].ping_cm();
int dist_b = sonar[2].ping_cm();
int display_r = map(dist_r,0,40,255,0);
int display_g = 0;
int display_b = 0;
//neopixel ring: produce color
for(int i = 0; i < 12; i++){
ring.setPixelColor(i, display_r, display_g, display_b);
}
ring.show();
//color sensor: read color
while (!APDS.colorAvailable()) {
delay(2);
}
int read_r, read_g, read_b;
APDS.readColor(read_r, read_g, read_b);
int sensor_r = map(read_r,0,2600,0,255);
int sensor_g = 0;
int sensor_b = 0;
//color to heat
int buttonVal = digitalRead(BUTTONPIN);
int brightness;
// button option to skip middle step(color) and turn distance into heat directly
if(buttonVal == LOW){
brightness = map(dist_r,0,30,50,1000);
} else {
brightness = map(sensor_r,0,255,50,1000);
}
analogWrite(MOSFETPIN,brightness);
// LCD Display
screen.home();
screen.clear();
screen.print("i:");
screen.print(dist_r);
int midIn = map(display_r, 0,255,0,99);
screen.setCursor(6, 0);
screen.print("m:");
screen.print(midIn);
int mid_Out = map(sensor_r, 0,255,0,99);
screen.setCursor(8, 1);
screen.print(mid_Out);
int b = map(brightness, 50,1000,0,99);
screen.setCursor(12, 1);
screen.print("o:");
screen.print(b);
delay(4);
}