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

  1. <span class="com">/*
  2. * Project Title: The Color-Humidity-Displacement Double Transducer
  3. *
  4. * Names: Achilles Lin, Sue Lee
  5. *
  6. * Description: The code takes in 2 sensor inputs (RGB color sensor and
  7. * DHT Humidity Sensor) and produces 3 outputs (LCD Display, Ultrasonic
  8. * Humidifier, and Hobby Servo Motor). The values printed to the LCD Display
  9. * are mapped to the range [0, 99]. The color temperature is used as the
  10. * primary value which affects the Ultrasonic Humidifier value. The output
  11. * to the Ultrasonic Humidifier is updated every 2 seconds.
  12. *
  13. * Pin mapping:
  14. *
  15. * pin | mode | description
  16. * ------|--------|------------
  17. * 2 input DHT Humidity Sensor
  18. * 5 output Ultrasonic Humidifier
  19. * 6 output Hobby Servo Motor
  20. *
  21. * Credit: Code samples and inspiration were taken from the following websites
  22. * and example files:
  23. * - DHT Humidity Sensor: https://www.electroschematics.com/arduino-dht22-am2302-tutorial-library/
  24. * - timer-based periodic updating: Professor Zach <3
  25. * - RGB Color Sensor: Humidity Sensor: tcs34725.ico example code
  26. *
  27. * License Notice:
  28. * Copyright 2020 Achilles Lin and Sue Lee
  29. *
  30. * Permission is hereby granted, free of charge, to any person obtaining
  31. * a copy of this software and associated documentation files (the "Software"),
  32. * to deal in the Software without restriction, including without limitation
  33. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  34. * and/or sell copies of the Software, and to permit persons to whom the
  35. * Software is furnished to do so, subject to the following conditions:
  36. The above copyright notice and this permission notice shall be included in
  37. all copies or substantial portions of the Software.
  38. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  39. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  40. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  41. THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  42. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  43. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  44. SOFTWARE.
  45. *
  46. */</span><span class="pln">
  47. </span><span class="com">#include</span><span class="pln"> </span><span class="str">"DHT.h"</span><span class="pln">
  48. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><Wire.h></span><span class="pln">
  49. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><LiquidCrystal_I2C.h></span><span class="pln">
  50. </span><span class="com">#include</span><span class="pln"> </span><span class="str">"Adafruit_TCS34725.h"</span><span class="pln">
  51. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><Servo.h></span><span class="pln">
  52. </span><span class="com">#define</span><span class="pln"> DHTPIN </span><span class="lit">2</span><span class="pln">
  53. </span><span class="com">#define</span><span class="pln"> DHTTYPE DHT22
  54. </span><span class="com">#define</span><span class="pln"> MOTORPIN </span><span class="lit">6</span><span class="pln">
  55. </span><span class="com">#define</span><span class="pln"> HUMPIN </span><span class="lit">5</span><span class="pln">
  56. </span><span class="com">#define</span><span class="pln"> RED_LOWER_BOUND </span><span class="lit">2000</span><span class="pln">
  57. </span><span class="com">#define</span><span class="pln"> VIOLET_UPPER_BOUND </span><span class="lit">30000</span><span class="pln">
  58. </span><span class="com">#define</span><span class="pln"> HUMIDIFIER_UPPER_BOUND </span><span class="lit">120</span><span class="pln">
  59. </span><span class="com">#define</span><span class="pln"> RETRACTED_SERVO_VALUE </span><span class="lit">10</span><span class="pln">
  60. </span><span class="com">#define</span><span class="pln"> EXTENDED_SERVO_VALUE </span><span class="lit">180</span><span class="pln">
  61. </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> timer </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// variable for timing</span><span class="pln">
  62. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> INTERVAL </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">;</span><span class="pln"> </span><span class="com">// milliseconds between updates</span><span class="pln">
  63. </span><span class="typ">LiquidCrystal_I2C</span><span class="pln"> lcd</span><span class="pun">(</span><span class="lit">0x27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln"> </span><span class="com">// LCD I2C Display</span><span class="pln">
  64. </span><span class="typ">Adafruit_TCS34725</span><span class="pln"> tcs </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Adafruit_TCS34725</span><span class="pun">();</span><span class="pln"> </span><span class="com">// RGB Color Sensor</span><span class="pln">
  65. DHT dht</span><span class="pun">(</span><span class="pln">DHTPIN</span><span class="pun">,</span><span class="pln"> DHTTYPE</span><span class="pun">);</span><span class="pln"> </span><span class="com">// DHT Humidity Sensor</span><span class="pln">
  66. </span><span class="typ">Servo</span><span class="pln"> steeringMotor</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Hobby Servo Motor</span><span class="pln">
  67. </span><span class="kwd">void</span><span class="pln"> setup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  68. </span><span class="com">// initialize Serial port, LCD, color sensor, humidifier, humidity sensor, servo</span><span class="pln">
  69. </span><span class="typ">Serial</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">(</span><span class="lit">9600</span><span class="pun">);</span><span class="pln">
  70. lcd</span><span class="pun">.</span><span class="pln">init</span><span class="pun">();</span><span class="pln">
  71. lcd</span><span class="pun">.</span><span class="pln">backlight</span><span class="pun">();</span><span class="pln">
  72. tcs</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">();</span><span class="pln">
  73. pinMode</span><span class="pun">(</span><span class="pln">HUMPIN</span><span class="pun">,</span><span class="pln"> OUTPUT</span><span class="pun">);</span><span class="pln">
  74. dht</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">();</span><span class="pln">
  75. steeringMotor</span><span class="pun">.</span><span class="pln">attach</span><span class="pun">(</span><span class="pln">MOTORPIN</span><span class="pun">);</span><span class="pln">
  76. </span><span class="pun">}</span><span class="pln">
  77. </span><span class="com">/* displayLCD takes in normalized input/output values (0 - 99) and
  78. * prints them to the LCD display in the format:
  79. i:xx m:xx
  80. xx o:xx*/</span><span class="pln">
  81. </span><span class="kwd">void</span><span class="pln"> displayLCD </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> colorTemp</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> hum</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> humSensor</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> servo</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  82. lcd</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  83. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">colorTemp </span><span class="pun"><</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// adds space if value is single digit</span><span class="pln">
  84. lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"i: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTemp </span><span class="pun">+</span><span class="pln"> </span><span class="str">" m:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
  85. </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  86. lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"i:"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTemp </span><span class="pun">+</span><span class="pln"> </span><span class="str">" m:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
  87. </span><span class="pun">}</span><span class="pln">
  88. lcd</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  89. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">humSensor </span><span class="pun"><</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// adds space if value is single digit</span><span class="pln">
  90. lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">humSensor </span><span class="pun">+</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="str">" o:"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> servo</span><span class="pun">);</span><span class="pln">
  91. </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  92. lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">humSensor </span><span class="pun">+</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="str">" o:"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> servo</span><span class="pun">);</span><span class="pln">
  93. </span><span class="pun">}</span><span class="pln">
  94. </span><span class="pun">}</span><span class="pln">
  95. </span><span class="kwd">void</span><span class="pln"> loop</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  96. delay</span><span class="pun">(</span><span class="lit">300</span><span class="pun">);</span><span class="pln">
  97. lcd</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  98. </span><span class="com">// initialize variables</span><span class="pln">
  99. </span><span class="kwd">int</span><span class="pln"> colorTemp</span><span class="pun">,</span><span class="pln"> colorTempNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  100. </span><span class="kwd">int</span><span class="pln"> hum</span><span class="pun">,</span><span class="pln"> humNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  101. </span><span class="kwd">int</span><span class="pln"> humSensorNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  102. </span><span class="kwd">int</span><span class="pln"> servo</span><span class="pun">,</span><span class="pln"> servoNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  103. </span><span class="com">// TRANSDUCER 1 (color (red->violet) to humidifier)</span><span class="pln">
  104. </span><span class="com">// read color temperature</span><span class="pln">
  105. </span><span class="typ">uint16_t</span><span class="pln"> r</span><span class="pun">,</span><span class="pln"> g</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
  106. tcs</span><span class="pun">.</span><span class="pln">getRawData</span><span class="pun">(&</span><span class="pln">r</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&</span><span class="pln">g</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&</span><span class="pln">c</span><span class="pun">);</span><span class="pln">
  107. colorTemp </span><span class="pun">=</span><span class="pln"> tcs</span><span class="pun">.</span><span class="pln">calculateColorTemperature</span><span class="pun">(</span><span class="pln">r</span><span class="pun">,</span><span class="pln"> g</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
  108. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"color temp: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTemp</span><span class="pun">);</span><span class="pln">
  109. </span><span class="com">// normalize color temperature</span><span class="pln">
  110. colorTemp </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">colorTemp</span><span class="pun">,</span><span class="pln"> RED_LOWER_BOUND</span><span class="pun">,</span><span class="pln"> VIOLET_UPPER_BOUND</span><span class="pun">);</span><span class="pln">
  111. colorTempNorm </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">colorTemp</span><span class="pun">,</span><span class="pln"> RED_LOWER_BOUND</span><span class="pun">,</span><span class="pln"> VIOLET_UPPER_BOUND</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">);</span><span class="pln">
  112. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"color temp norm: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTempNorm</span><span class="pun">);</span><span class="pln">
  113. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">
  114. </span><span class="com">// update humidifier value every 2 seconds</span><span class="pln">
  115. hum </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">colorTempNorm</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> HUMIDIFIER_UPPER_BOUND</span><span class="pun">);</span><span class="pln">
  116. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">>=</span><span class="pln"> timer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  117. analogWrite</span><span class="pun">(</span><span class="pln">HUMPIN</span><span class="pun">,</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
  118. timer </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> INTERVAL</span><span class="pun">;</span><span class="pln">
  119. </span><span class="pun">}</span><span class="pln">
  120. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"hum: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
  121. </span><span class="com">// normalize humidifier value</span><span class="pln">
  122. humNorm </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">hum</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> HUMIDIFIER_UPPER_BOUND</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">);</span><span class="pln">
  123. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"hum norm: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> humNorm</span><span class="pun">);</span><span class="pln">
  124. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">
  125. </span><span class="com">// TRANSDUCER 2 (humidity sensor to linear displacement (3 cm))</span><span class="pln">
  126. </span><span class="com">// read humidity sensor percentage input</span><span class="pln">
  127. humSensorNorm </span><span class="pun">=</span><span class="pln"> dht</span><span class="pun">.</span><span class="pln">readHumidity</span><span class="pun">();</span><span class="pln">
  128. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"hum sensor norm: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> humSensorNorm</span><span class="pun">);</span><span class="pln">
  129. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">
  130. </span><span class="com">// update servo position if humidifier input is valid</span><span class="pln">
  131. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isnan</span><span class="pun">(</span><span class="pln">humSensorNorm</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  132. </span><span class="kwd">int</span><span class="pln"> hconstr </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">humSensorNorm</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">);</span><span class="pln">
  133. servoNorm </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">hconstr</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">);</span><span class="pln">
  134. servo </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">servoNorm</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">,</span><span class="pln"> RETRACTED_SERVO_VALUE</span><span class="pun">,</span><span class="pln"> EXTENDED_SERVO_VALUE</span><span class="pun">);</span><span class="pln">
  135. steeringMotor</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">servo</span><span class="pun">);</span><span class="pln">
  136. </span><span class="pun">}</span><span class="pln">
  137. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"servo: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> servo</span><span class="pun">);</span><span class="pln">
  138. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"servo norm: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> servoNorm</span><span class="pun">);</span><span class="pln">
  139. </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">
  140. displayLCD</span><span class="pun">(</span><span class="pln">colorTempNorm</span><span class="pun">,</span><span class="pln"> humNorm</span><span class="pun">,</span><span class="pln"> humSensorNorm</span><span class="pun">,</span><span class="pln"> servoNorm</span><span class="pun">);</span><span class="pln">
  141. </span><span class="pun">}</span>
<span class="com">/*
 * 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.
 * 
 */</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"DHT.h"</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str"><Wire.h></span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str"><LiquidCrystal_I2C.h></span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"Adafruit_TCS34725.h"</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str"><Servo.h></span><span class="pln">

</span><span class="com">#define</span><span class="pln"> DHTPIN </span><span class="lit">2</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> DHTTYPE DHT22
</span><span class="com">#define</span><span class="pln"> MOTORPIN </span><span class="lit">6</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> HUMPIN </span><span class="lit">5</span><span class="pln">

</span><span class="com">#define</span><span class="pln"> RED_LOWER_BOUND </span><span class="lit">2000</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> VIOLET_UPPER_BOUND </span><span class="lit">30000</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> HUMIDIFIER_UPPER_BOUND </span><span class="lit">120</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> RETRACTED_SERVO_VALUE </span><span class="lit">10</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> EXTENDED_SERVO_VALUE </span><span class="lit">180</span><span class="pln">

</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> timer </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">    </span><span class="com">// variable for timing</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> INTERVAL </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">;</span><span class="pln">  </span><span class="com">// milliseconds between updates</span><span class="pln">

</span><span class="typ">LiquidCrystal_I2C</span><span class="pln"> lcd</span><span class="pun">(</span><span class="lit">0x27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">           </span><span class="com">// LCD I2C Display</span><span class="pln">
</span><span class="typ">Adafruit_TCS34725</span><span class="pln"> tcs </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Adafruit_TCS34725</span><span class="pun">();</span><span class="pln">  </span><span class="com">// RGB Color Sensor</span><span class="pln">
DHT dht</span><span class="pun">(</span><span class="pln">DHTPIN</span><span class="pun">,</span><span class="pln"> DHTTYPE</span><span class="pun">);</span><span class="pln">                     </span><span class="com">// DHT Humidity Sensor</span><span class="pln">
</span><span class="typ">Servo</span><span class="pln"> steeringMotor</span><span class="pun">;</span><span class="pln">                          </span><span class="com">// Hobby Servo Motor</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> setup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// initialize Serial port, LCD, color sensor, humidifier, humidity sensor, servo</span><span class="pln">
  </span><span class="typ">Serial</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">(</span><span class="lit">9600</span><span class="pun">);</span><span class="pln">
  
  lcd</span><span class="pun">.</span><span class="pln">init</span><span class="pun">();</span><span class="pln">
  lcd</span><span class="pun">.</span><span class="pln">backlight</span><span class="pun">();</span><span class="pln">
  
  tcs</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">();</span><span class="pln">
  
  pinMode</span><span class="pun">(</span><span class="pln">HUMPIN</span><span class="pun">,</span><span class="pln"> OUTPUT</span><span class="pun">);</span><span class="pln">
  
  dht</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">();</span><span class="pln">
  
  steeringMotor</span><span class="pun">.</span><span class="pln">attach</span><span class="pun">(</span><span class="pln">MOTORPIN</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* 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*/</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> displayLCD </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> colorTemp</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> hum</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> humSensor</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> servo</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  lcd</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">colorTemp </span><span class="pun"><</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// adds space if value is single digit</span><span class="pln">
    lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"i: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTemp </span><span class="pun">+</span><span class="pln"> </span><span class="str">" m:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"i:"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTemp </span><span class="pun">+</span><span class="pln"> </span><span class="str">" m:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  lcd</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">humSensor </span><span class="pun"><</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// adds space if value is single digit</span><span class="pln">
    lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">humSensor </span><span class="pun">+</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="str">"  o:"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> servo</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    lcd</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">humSensor </span><span class="pun">+</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="str">" o:"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> servo</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> loop</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  delay</span><span class="pun">(</span><span class="lit">300</span><span class="pun">);</span><span class="pln">
  lcd</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">

  </span><span class="com">// initialize variables</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> colorTemp</span><span class="pun">,</span><span class="pln"> colorTempNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> hum</span><span class="pun">,</span><span class="pln"> humNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> humSensorNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> servo</span><span class="pun">,</span><span class="pln"> servoNorm </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

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

  </span><span class="com">// normalize color temperature</span><span class="pln">
  colorTemp </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">colorTemp</span><span class="pun">,</span><span class="pln"> RED_LOWER_BOUND</span><span class="pun">,</span><span class="pln"> VIOLET_UPPER_BOUND</span><span class="pun">);</span><span class="pln">
  colorTempNorm </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">colorTemp</span><span class="pun">,</span><span class="pln"> RED_LOWER_BOUND</span><span class="pun">,</span><span class="pln"> VIOLET_UPPER_BOUND</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"color temp norm: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> colorTempNorm</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">

  </span><span class="com">// update humidifier value every 2 seconds</span><span class="pln">
  hum </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">colorTempNorm</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> HUMIDIFIER_UPPER_BOUND</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">>=</span><span class="pln"> timer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    analogWrite</span><span class="pun">(</span><span class="pln">HUMPIN</span><span class="pun">,</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">
    timer </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> INTERVAL</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"hum: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> hum</span><span class="pun">);</span><span class="pln">

  </span><span class="com">// normalize humidifier value</span><span class="pln">
  humNorm </span><span class="pun">=</span><span class="pln"> map</span><span class="pun">(</span><span class="pln">hum</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> HUMIDIFIER_UPPER_BOUND</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="typ">String</span><span class="pun">(</span><span class="str">"hum norm: "</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> humNorm</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">Serial</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">

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

  displayLCD</span><span class="pun">(</span><span class="pln">colorTempNorm</span><span class="pun">,</span><span class="pln"> humNorm</span><span class="pun">,</span><span class="pln"> humSensorNorm</span><span class="pun">,</span><span class="pln"> servoNorm</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span>