Double Transducer: Rotation to Temperature
Indie Lee and Merlin Enriquez
Indie Lee and Merlin Enriquez
Indie's double transducer that transforms a rotation angle input via potentiometer, into temperature via heatpad.
Merlin Enriquez double transducer
LED brightness middle step, measured by a photoresistor. (Indie)
Up close of heatpad's barrel plug (above) and LED housing (right). (Indie)
Video documentation of Indie's double transducer. Rotation of the potentiometer translates into LED brightness, which translates into heat. The skip the middle button translates rotation of the potentiometer directly into heat, and the LED turns off.
Student 2 documentation video with caption, same advice and requirements as listed above.
When the user turns the potentiometer, the LED brightness increases. The LED is positioned in front of a photoresistor that detects the light intensity. This sensor sends data to an electric heating pad controller. As the photoresistor detects more light, the heating pad produces more heat.
At this point, I was excited about the progress I made and thought I had finished the basic setup. Little did I know that some wires that should've been in the same row weren't, and some of my code was completely wrong! (Indie)
Middle step before soldering. Note that I switched to unhoused wires! and organize the protoboard a bit better (one ground pin, components flush against board). (Indie)
Merlin Enriquez
Merlin Enriquez
Merlin:
I have a bit of experience with electronics because I took intro to arduino. At first, it was relatively easy for me to understand the basics of wiring and electronics. Since I have previous coding experience, the logic of the code felt easy for me to understand---the skills were transferable. It was still a new coding language so there are differences I had to get adjusted to. I found it easier for me to understand the connection by connecting all of the pieces together instead of testing it out one by one. Although, it helped with me writing the code, it was detrimental for me when debugging the wiring. I ran into very small, yet impactful mistakes in my wiring that costed me a lot of time and mental headache to fix. Next time, I plan to do each step little by little to fully understand the wiring.
Indie:
This was a fun introductory project to Arduino. I enjoyed the hands-on aspect of it, I really liked snapping the wires into place and the soldering step. I've never done anything like this before and it felt like solving a fun puzzle. Like Merlin, I also found the wiring part more intuitive. Although I made some wiring mistakes, working through possible wire mistakes by going component to component was a lot easier, visually and physically, than working through my coding mistakes..
One very interesting aspect of my process is that I thought I had my project up and running midway through, only to go to office hours and find some things fundamentally incorrect with my code. What happened there, I have little idea, but this is one potentially frustrating aspect of working between hardware and software that I will look out for in the future. I also had difficulty mapping the input to output values, and this is one thing I couldn't get just right. Mapping the LED brightness to the photoresistor especially was finnicky since the photoresistor was sensitive to surrounding lights in the room. Even though I made housing for the LED, I still found the mapping values a bit strange since the LED brightness wouldn't map one to one to the photoresistor input. Looking back though, I am proud of what I achieved because this is my first time using an Arduino and even using the mapping function at all! I felt accomplished when it came together, and I do think the process went as smoothly as it could've gone.
Working with new components such as the LCD screen and the heatpad was super interesting to me. At the beginning of the year when we looked through former students' projects, I was impressed with their LCD screens. Now I am glad to know that most of the code is already done by someone else and downloadable into a library so that I can easily use one myself! Using the heatpad was also interesting because it was difficult to tell if it was working or not. But honestly, the worse things worked, the better I felt when I fixed it so there's that I guess. All in all, this project was a really fun way to get into arduino and execute something functional.
Although Merlin and I used different types of LEDs for the middle step, we both wrote similar code in which we mapped potentiometer value to LED brightness, and LED brightness to heatpad temperature.
/*
Project 1: Double Transducer
60-223 Intro to Physical Computing
Indie Lee
Pin mapping:
Arduino pin | role | description
-------------------------------------
A0 input potentiometer
A1 input photoresistor
6 output heatpad
8 input button
9 output LED
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// pin assignments
const int POTPIN = A0, //white
PHOTOPIN = A1, //dark green
HEATPIN = 6, //purple
BUTTONPIN = 8, //green
LEDPIN = 9; //blue
LiquidCrystal_I2C screen(0x27, 16, 2);
const unsigned long LCD_WAIT = 500;
unsigned long lcd_timer = 0;
// input data variables
int potVal, photoVal, buttonVal;
// internal mapping values
int mappedPotVal, mappedPhotoVal;
// output variables
int ledVal, heatVal;
//LCD variables
int i, mo, mi, o;
void setup() {
pinMode(HEATPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT_PULLUP);
pinMode(LEDPIN, OUTPUT);
pinMode(PHOTOPIN, INPUT);
pinMode(POTPIN, INPUT);
Serial.begin(9600);
screen.init(); //initialize the screen
screen.backlight(); //turn on backlight
}
void loop() {
// step 1: read all of the sensors
readInputs();
// step 2: make decisions about what to do
updateInternalState();
// step 3: drive all of the outputs
driveOutputs();
// step 4: report data back to the user
reportBack();
// step 5: update LCD
updateLCD();
// a brief delay at the bottom of the loop is usually a good idea
delay(5);
}
void readInputs() {
// read potentiometer
potVal = analogRead(POTPIN);
// read photoresistor
photoVal = analogRead(PHOTOPIN);
// read button
buttonVal = digitalRead(BUTTONPIN); // will be LOW when pressed
}
void updateInternalState() {
// map the potentiometer value to a range of 0 to 99
mappedPotVal = map(potVal, 0, 1023, 0, 99);
// map the photoresistor value to a range of 99 to 0
// photoresistor values are 1000 low, 50 high, map it reverse
mappedPhotoVal = map(photoVal, 50, 1000, 99, 0);
}
void driveOutputs() {
if (buttonVal == HIGH) { //button is not pressed
ledVal = map(mappedPotVal, 0, 99, 0, 255);
analogWrite(LEDPIN, ledVal);
//heatpad values are 640 low (cold), 40 high (hot)
heatVal = map(mappedPhotoVal, 0, 99, 0, 255);
analogWrite(HEATPIN, heatVal);
} else {
//button is pressed
ledVal = 0;
analogWrite(LEDPIN, ledVal);
heatVal = map(mappedPotVal, 0, 99, 0, 255);
analogWrite(HEATPIN, heatVal);
}
}
void updateLCD() {
unsigned long cur_time = millis();
if ((cur_time - lcd_timer) >= LCD_WAIT) {
screen.setCursor(0, 0);
screen.print("i:");
i = mappedPotVal;
screen.print(i);
screen.setCursor(6, 0);
screen.print("m:");
mo = map(ledVal, 0, 255, 0, 99);
screen.print(mo);
screen.setCursor(8, 1);
mi = mappedPhotoVal;
screen.print(mi);
screen.setCursor(12, 1);
screen.print("o:");
o = map(heatVal, 0, 255, 0, 99);
o = constrain(o, 0, 99);
screen.print(o);
lcd_timer = cur_time;
}
}
void reportBack() {
Serial.print("potVal = ");
Serial.print(potVal);
Serial.print(", ledVal = ");
Serial.print(ledVal);
Serial.print(", photoVal = ");
Serial.print(photoVal);
Serial.print(", heatVal = ");
Serial.println(heatVal);
}
// Project 1: Double Transducer
// 60-223 Intro to Physical Computing
// Merlin Enriquez
// button = button(input) (skip middle button)
// pot = potentiometer (input) (first)
// photo = photoresister (input)
// ledring = NeoPixel LED (output) (middle)
// heat = eletric heating pad(output) (final)
// lcd = LCD screen (output)
#include <Adafruit_NeoPixel.h>
#include <LiquidCrystal_I2C.h>
#define LED_COUNT 12 // amt of led bulbs
#define LEDRING_PIN 3 // wire clr = white
LiquidCrystal_I2C screen(0x27, 16, 2);
Adafruit_NeoPixel ring = Adafruit_NeoPixel(LED_COUNT, LEDRING_PIN, NEO_GRB + NEO_KHZ800);
const int BUTTON_PIN = 5; // wire clr = green
const int POT_PIN = A0; // wire clr = purple
const int PHOTO_PIN = A3; // wire clr = yellow
const int HEAT_PIN = 6; // wire clr = blue
const int LCD_SDA_PIN = A4; // wire clr = orange
const int LCD_SCL_PIN = A5; // wire clr = brown
// input values
int buttonVal;
int potVal;
int photoVal;
//output values
int LcdBrightness;
int heatVal = 0;
//mapped values
int mappedNeoPixelVal;
int mappedPhotoVal;
int mappedNeoLCD; //(converts output into a 0-99)
int mappedPhotoLCD; //(converts input into a 0-99)
//controls opacity
int opacityMin;
int opacityMax;
int brightnessVal;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP); // far leg button to ground
pinMode(POT_PIN, INPUT);
pinMode(PHOTO_PIN, INPUT);
pinMode(LEDRING_PIN, OUTPUT);
pinMode(HEAT_PIN, OUTPUT);
analogWrite(HEAT_PIN, heatVal); // converts to analog signal (0,255)
// the ring led is rgba based so im giving a min + max value
// constrain the brightness value between 0,255
opacityMin = 0;
opacityMax = 255;
brightnessVal = 0;
// brightnessVal = constrain(brightnessVal, opacityMin, opacityMax);
ring.begin();
ring.show();
// make sures all led is white
for (int i = 0; i < LED_COUNT; i++) {
ring.setPixelColor(i, ring.Color(255, 255, 255));
}
ring.show();
//lcd
screen.init();
screen.backlight();
screen.clear();
}
void loop() {
readInputs();
updateInternalState();
updateOutputs();
updateLCD();
reportBack();
delay(250);
}
void readInputs() {
photoVal = analogRead(PHOTO_PIN);
potVal = analogRead(POT_PIN);
buttonVal = digitalRead(BUTTON_PIN);
}
void updateInternalState() {
mappedNeoPixelVal = map(potVal, 0, 1023, opacityMin, opacityMax);
mappedPhotoVal = map(photoVal, 0, 1023, 0, 255);
heatVal = mappedPhotoVal;
mappedNeoLCD = map(mappedNeoPixelVal, 0, 255, 0, 99);
mappedPhotoLCD = map(mappedPhotoVal, 0, 255, 0, 99);
//if button is pressed(low)
//then the heat value switches pot val (input) directly
//to controlling eletric heating pad(output)
if (buttonVal == LOW) {
heatVal = map(potVal, 0, 1023, 0, 255);
} else {
heatVal = mappedPhotoVal;
}
}
void updateOutputs() {
ring.setBrightness(mappedNeoPixelVal);
//so this shows up again when pot is turned back and forth
for (int i = 0; i < LED_COUNT; i++) {
ring.setPixelColor(i, ring.Color(255, 255, 255));
}
ring.show();
analogWrite(HEAT_PIN, heatVal);
Serial.println(heatVal);
//debug neopixel
Serial.print("NeoPixel brightness set to: ");
Serial.println(mappedNeoPixelVal);
}
void updateLCD() {
static unsigned long lastUpdate = 0; // stores last update time
unsigned long currentMillis = millis();
// updates every 5 secs
if (currentMillis - lastUpdate >= 5000) {
lastUpdate = currentMillis;
screen.clear();
screen.setCursor(0, 0);
screen.print("LED:");
screen.print(mappedNeoLCD);
screen.print(" PHO:");
screen.print(mappedPhotoLCD);
screen.setCursor(0, 1);
screen.print("HEAT:");
screen.print(map(heatVal, 0, 255, 0, 99));
if (buttonVal == LOW) {
screen.print(" [BTN]");
}
}
}
void reportBack() {
//displays on serial monitor
Serial.print("photoVal = ");
Serial.print(photoVal);
Serial.print(", potVal = ");
Serial.print(potVal);
Serial.print(", buttonVal = ");
Serial.println(buttonVal);
}