Overall Photo

Our Double Transducer in all its glory!

Detail Photos

A festive green pipe cleaner was stuck into the arm of the servo and threaded through a straw to convert rotational motion into linear motion.

This Adafruit RGB Color Sensor used a built-in LED to help with detecting color.

Brief Movie

Narrative Description

First the RGB Color Sensor reads the color temperature of a given colored light. Lower values of the Color Sensor match to red lights, and higher values of the Color Sensor match to violet light. Then from the values read from the color sensor, the Ultrasonic Humidifier outputs lower levels of humidity for lower color readings and higher levels of humidity for higher color readings. The DHT Humidity Sensor then reads the percent humidity output from the Ultrasonic Humidifier. The reading from the Humidity sensor then corresponds to an output from the Servo Motor. Higher humidity readings lead to a higher degree of the motor’s position, and lower humidity readings lead to a lower degree in the motor’s position. Finally, the radial motor position is then translated to a linear displacement with an arm.

Progress Images

Early-on in our journey, this image shows the LCD screen, servo motor, and humidity sensor hooked up to the breadboard.

The humidity sensor is now mounted and the RGB color sensor is hooked up and mounted as well!

The Double Transducer is almost complete! This image shows the ultrasonic humidifier dipping into the Playdoh container of water.

Discussion

While certain components used in the double transducer were very kind to us, others were a little less reliable and difficult to control. For example, the humidity sensor read values very accurately, without much noise, and also had clear, concise sample code available in the libraries. However, the ultrasonic humidifier was difficult to control as it was not the most responsive of components. Sometimes when given an analogWrite value of 0, the humidifier was on full-blast, while at other times, it was off. We learned that the more complex the component, the more important quality was.  Having a higher quality humidifier could have significantly improved the reliability of our transducer.

One close-call we had was accidentally switching a ground and 5V wire connected to the humidity sensor and, thus, connecting 5V directly to the ground. This made the Arduino completely unresponsive and some boards also became hot-to-the-touch. After a few minutes of tinkering with the plugs, with a hint from Zach, we realized our error and switched the wiring back. Thankfully, nothing on the board had broken. We learned how helpful colored wires can be and how you should not rush the initial plugging in of the 5V and ground wires.

Schematic

Schematic for our Project 1 Double Transducer

Code Submission

/*
 * Project Title: The Color-Humidity-Displacement Double Transducer
 * 
 * Names: Achilles Lin, Sue Lee
 * 
 * Description: The code takes in 2 sensor inputs (RGB color sensor and
 * DHT Humidity Sensor) and produces 3 outputs (LCD Display, Ultrasonic 
 * Humidifier, and Hobby Servo Motor). The values printed to the LCD Display 
 * are mapped to the range [0, 99]. The color temperature is used as the
 * primary value which affects the Ultrasonic Humidifier value. The output 
 * to the Ultrasonic Humidifier is updated every 2 seconds.
 * 
 * Pin mapping:
 * 
 * pin   | mode   | description
 * ------|--------|------------
 * 2       input     DHT Humidity Sensor
 * 5       output    Ultrasonic Humidifier
 * 6       output    Hobby Servo Motor
 * 
 * Credit: Code samples and inspiration were taken from the following websites 
 * and example files:
 *  - DHT Humidity Sensor: https://www.electroschematics.com/arduino-dht22-am2302-tutorial-library/
 *  - timer-based periodic updating: Professor Zach <3
 *  - RGB Color Sensor: Humidity Sensor: tcs34725.ico example code
 * 
 * License Notice: 
 * Copyright 2020 Achilles Lin and Sue Lee
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.
 * 
 */
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Adafruit_TCS34725.h"
#include <Servo.h>

#define DHTPIN 2
#define DHTTYPE DHT22
#define MOTORPIN 6
#define HUMPIN 5

#define RED_LOWER_BOUND 2000
#define VIOLET_UPPER_BOUND 30000
#define HUMIDIFIER_UPPER_BOUND 120
#define RETRACTED_SERVO_VALUE 10
#define EXTENDED_SERVO_VALUE 180

unsigned long timer = 0;    // variable for timing
const int INTERVAL = 3000;  // milliseconds between updates

LiquidCrystal_I2C lcd(0x27, 20, 4);           // LCD I2C Display
Adafruit_TCS34725 tcs = Adafruit_TCS34725();  // RGB Color Sensor
DHT dht(DHTPIN, DHTTYPE);                     // DHT Humidity Sensor
Servo steeringMotor;                          // Hobby Servo Motor

void setup() {
  // initialize Serial port, LCD, color sensor, humidifier, humidity sensor, servo
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();
  
  tcs.begin();
  
  pinMode(HUMPIN, OUTPUT);
  
  dht.begin();
  
  steeringMotor.attach(MOTORPIN);
}

/* displayLCD takes in normalized input/output values (0 - 99) and
 * prints them to the LCD display in the format:
    i:xx m:xx
           xx o:xx*/
void displayLCD (int colorTemp, int hum, int humSensor, int servo) {
  lcd.setCursor(1, 0);
  if (colorTemp < 10) { // adds space if value is single digit
    lcd.print(String("i: ") + colorTemp + " m:" + hum);
  } else {
    lcd.print(String("i:") + colorTemp + " m:" + hum);
  }
  lcd.setCursor(8, 1);
  if (humSensor < 10) { // adds space if value is single digit
    lcd.print(humSensor + String("  o:") + servo);
  } else {
    lcd.print(humSensor + String(" o:") + servo);
  }
}

void loop() {
  delay(300);
  lcd.clear();

  // initialize variables
  int colorTemp, colorTempNorm = 0;
  int hum, humNorm = 0;
  int humSensorNorm = 0;
  int servo, servoNorm = 0;

  // TRANSDUCER 1 (color (red->violet) to humidifier)
  // read color temperature
  uint16_t r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);
  colorTemp = tcs.calculateColorTemperature(r, g, b);
  Serial.println(String("color temp: ") + colorTemp);

  // normalize color temperature
  colorTemp = constrain(colorTemp, RED_LOWER_BOUND, VIOLET_UPPER_BOUND);
  colorTempNorm = map(colorTemp, RED_LOWER_BOUND, VIOLET_UPPER_BOUND, 0, 99);
  Serial.println(String("color temp norm: ") + colorTempNorm);
  Serial.println("");

  // update humidifier value every 2 seconds
  hum = map(colorTempNorm, 0, 99, 0, HUMIDIFIER_UPPER_BOUND);
  if (millis() >= timer) {
    analogWrite(HUMPIN, hum);
    timer = millis() + INTERVAL;
  }
  Serial.println(String("hum: ") + hum);

  // normalize humidifier value
  humNorm = map(hum, 0, HUMIDIFIER_UPPER_BOUND, 0, 99);
  Serial.println(String("hum norm: ") + humNorm);
  Serial.println("");

  // TRANSDUCER 2 (humidity sensor to linear displacement (3 cm))
  // read humidity sensor percentage input
  humSensorNorm = dht.readHumidity();
  Serial.println(String("hum sensor norm: ") + humSensorNorm);
  Serial.println("");
  
  // update servo position if humidifier input is valid
  if (!isnan(humSensorNorm)) {
    int hconstr = constrain(humSensorNorm, 20, 99);
    servoNorm = map(hconstr, 20, 99, 0, 99);
    servo = map(servoNorm, 0, 99, RETRACTED_SERVO_VALUE, EXTENDED_SERVO_VALUE);
    steeringMotor.write(servo);
  }
  Serial.println(String("servo: ") + servo);
  Serial.println(String("servo norm: ") + servoNorm);
  Serial.println("");

  displayLCD(colorTempNorm, humNorm, humSensorNorm, servoNorm);
}