Double Transducer: Linear Position to Variable Transparency
Final Photo & Video Documentation
Gemma's Double Transducer
A overhead view of Gemma's iteration of the double transducer.
The left and right side views of Gemma's Ultrasonic Ranger input and the beginning of the worlds most convoluted camera narrative.
A video of Gemma's Double Transducer.
Yiming's Double Transducer
A top view of Yiming's transducer.
A elevation view of the input.
Detail of how middle-step actuator connect to sensor.
Video showing the over all transition.
Narrative Description
A stand has a distance sensor on the side. Based on how close the user's hand is to the sensor, a motor turns to a position. The motor is connected with a stick to a dial. When the dial is turned, the transparency on a small screen changes.
Progress Photo & Video Documentation
Left Image - Materials used for brainstorming our mechanical connection. We struggled with the amount of friction needed to make the potentiometer turn.
Right Image - A very early prototype of the circuit itself (not completely wired) - it a lot of troubleshooting to get the whole thing to work!
Left Image - First attempt of all input and out are connect on breadbroads.
Right Image - Start to soldering middle-step actuators.
Discussion
In making this double transducer, there were many points of frustration, debugging and breakage - but there were also many moments of realization, of figuring out the solution that worked the best. It was the combination of both of these types of moments that really helped drive both of our learning. This was heightened by the fact that we spent quite a large percentage of our time working on the project, working on it together - sharing ideas, code and support - without that, we likely would not have been as successful in our final product.
We learned a lot in terms of iteration technique and the amount of prototyping it takes to get to a working feature. Other than the light valve we had used all of the components before in some way shape or form which helped speed the process up. That being said, we initially experimented with directly connecting the wiper of the potentiometer to one of the light valve’s pins, and the other pin to ground just to see how it would work with a direct input. Armed with that knowledge, we were able to use the analogWrite command to write the potentiometer inputs directly to the pin we assigned the light valve to (eventually this value was mapped). The knowledge of the experimentation we had done prior was essential in shaping the path we eventually took with the light valve programming. The other side of the prototyping that we did lied heavily in the mechanical connection. We struggled with the mechanical connection between the two, trying a variety of materials before settling on our (slightly MacGyvered) connection point complete with snap toys and balloon fragments.
Both team members became significantly more proficient solderers in this project - especially when it came to soldering to the pins of the potentiometer. While Gemma had done a bit in the past, this was one of the most fragile pieces she had worked with and it was challenging for both team members to get the stands and the solder at an angle to achieve successful, long-lasting connections between the wires and the pins. This skill will allow us to be more successful in our technical endeavors, both in and out of class.
One of the biggest points that could have changed the project was our input - we almost went with an IR sensor to detect movement - which other than completely change our input and all the code that came would it, would have functioned fundamentally differently than the Ultrasonic Ranger did in the end - it’s simply for a different use (although we did have some trouble with the Ultrasonic Ranger’s sensitivity levels). Overall, we learned a lot about our own technical abilities and how they have grown throughout the course of this class - excited to see where we go in the future with our projects!
Technical Details
Block Diagram
Electrical Schematic
Code
// Double Transducer: Linear Position to Variable Transparency
// by Gemma Tait and Yiming Jiao, Fall 2023
// Code Purpose:
// Runs a double transducer - mapping position read through an UltraSonic ranger to position on a Servo Motor.
// Reads position on a potentiometer (assumed to be mechanically connected to the Servo) and maps it to the
// light valve.
// Pin Mapping:
// Pin Number | Type | Connection
// 3 | OUTPUT | Light Valve
// 5 | OUTPUT | Servo Motor
// 9 | INPUT | UltraSonic Ranger Trigger Pin
// 10 | INPUT | UltraSonic Ranger Echo Pin
// A1 | INPUT | Potentiometer Wiper
// SDA | OUTPUT | LCD Screen SDA
// SCL | OUTPUT | LCD Screen SCL
// Libraries Used
#include <Encoder.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <NewPing.h>
LiquidCrystal_I2C screen(0x27, 16, 2);
// Motor setup
Servo gaugeMotor;
const int GAUGEMOTORPIN = 5;
// UltraSonic Ranger Pin Assignment
#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 30
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
// Setting Up Timers
long unsigned timer = 0;
int UR_Time = 250;
int ur_dist = 0;
//Potentiometer
long unsigned LCD_timer = 0;
// Light Valve
const int LV_Meter = 3;
int motorVal = 0;
int potVal = 0;
int npotVal = 0;
void setup() {
//motor setup
gaugeMotor.attach(GAUGEMOTORPIN);
//potentiometer setup
pinMode(A1, INPUT);
// Light Valve setup
pinMode(LV_Meter, OUTPUT);
//US setup
Serial.begin(115200);
// LCD Screen Code - Setting up Initial display
screen.init();
screen.backlight();
screen.home();
screen.print("i:");
screen.setCursor(7, 0);
screen.print("m:");
screen.setCursor(12, 1);
screen.print("o:");
}
void loop() {
if (millis() - timer > 500) {
// Reading inputs
potVal = analogRead(A1);
ur_dist = sonar.ping_cm();
// Mapping Ultrasonic ranger values to the motor position
motorVal = map(ur_dist, 0, 30, 1, 179);
gaugeMotor.write(motorVal);
// Writing to Light valve with mapped potentiometer read.
analogWrite(LV_Meter, map(potVal, 0, 1024, 0, 255));
npotVal = map(potVal, 0, 1024, 0, 255);
timer = millis();
}
if (millis() - LCD_timer > 500) {
// Writing Mapped values (mapping to 0-100) to the LCD screen to show the user a new display.
screen.setCursor(3, 0);
screen.print(map(ur_dist, 0, 30, 0, 100));
screen.setCursor(9, 0);
screen.print(map(motorVal, 1, 179, 0, 100));
screen.setCursor(9, 1);
screen.print(map(potVal, 0, 1024, 0, 100));
screen.setCursor(14, 1);
screen.print(map(npotVal, 0, 255, 0, 100));
LCD_timer = millis();
}