|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "id": "f3918b49-9476-4415-a7e9-68539c202181", |
| 6 | + "metadata": {}, |
| 7 | + "source": [ |
| 8 | + "# Project 4 - Circuit 4B: Digital Temperature Sensor\n", |
| 9 | + "\n", |
| 10 | + "Want to create a DIY environmental monitor or weather station? You can use a small, low-cost sensor like the TMP36 to make devices that track and respond to temperature. In this activity you will also use the OLED screen to display sensor readings, a common use for OLEDs in electronics projects.\n", |
| 11 | + " \n", |
| 12 | + "TODO: Update the LCD display with an OLED display.\n", |
| 13 | + "TODO: Update the jumper wires with a Qwiic connector.\n", |
| 14 | + "TODO: Remove potentiometer\n", |
| 15 | + "\n", |
| 16 | + "\n", |
| 17 | + "## New Components\n", |
| 18 | + "\n", |
| 19 | + "### TMP36 Temperature Sensor\n", |
| 20 | + "\n", |
| 21 | + "This temperature sensor has three legs. One connects to 5V, one to ground, and the voltage output from the third leg varies proportionally to changes in temperature. By doing some simple math with this voltage we can measure temperature in degrees Celsius or Fahrenheit.\n", |
| 22 | + "\n", |
| 23 | + "\n", |
| 24 | + "\n", |
| 25 | + "## New Concepts\n", |
| 26 | + "\n", |
| 27 | + "### Algorithms\n", |
| 28 | + "An algorithm is a process used in order to achieve a desired result. Often, the information needed to create an algorithm lives in the part's datasheet. This sketch uses a few formulas to turn a voltage value into a temperature value, making them all part of the larger temperature-retrieving algorithm. The first formula takes the voltage read on analog pin 0 and multiplies it to get a voltage value from 0V--5V:\n", |
| 29 | + "\n", |
| 30 | + "```python\n", |
| 31 | + "voltage = tempSensor.read_u16() * (3.3 / 65536.0)\n", |
| 32 | + "```\n", |
| 33 | + "We convert the analog \"count\" from the temperature sensor that gets returned by `read_u16()` to a voltage by multiplying by the maximum possible voltage (3.3 V) and dividing by the number of different possible counts (since read_u16() returns a 16-bit value that is 2^16 = 65536)\n", |
| 34 | + "\n", |
| 35 | + "The next formula takes that 0--5V value and calculateds degrees Centigrade:\n", |
| 36 | + "\n", |
| 37 | + "```python\n", |
| 38 | + "degreesC = (voltage - 0.5) * 100.0\n", |
| 39 | + "```\n", |
| 40 | + "The reason 0.5V is subtracted from the calculated voltage is because there is a 0.5V offset, mentioned on page 8 of the [TMP36 datasheet](https://cdn.sparkfun.com/datasheets/Sensors/Temp/TMP35_36_37.pdf). It's then multiplied by 100 to get a value that matches temperature.\n", |
| 41 | + "\n", |
| 42 | + "The last formula takes the Centigrade temperature and converts it to a Fahrenheit temperature using the standard conversion formula:\n", |
| 43 | + "\n", |
| 44 | + "```python\n", |
| 45 | + "degreesF = degreesC * (9.0 / 5.0) + 32.0\n", |
| 46 | + "```\n", |
| 47 | + "\n", |
| 48 | + "Together, these three formulas make up the algorithm that converts from the analog input counts to degrees Fahrenheit.\n", |
| 49 | + "\n", |
| 50 | + "## Hardware Hookup\n", |
| 51 | + "\n", |
| 52 | + "The temperature sensor is polarized and can only be inserted in one direction. See below for the pin outs of the temperature sensor. Pay very close attention to the markings on each side as you insert it into your circuit.\n", |
| 53 | + "\n", |
| 54 | + "\n", |
| 55 | + "\n", |
| 56 | + "<span style=\"color:#a94442\">Heads up! Double check the polarity of the TMP36 temperature sensor before powering the RedBoard. It can become very hot if it is inserted backward!</span>\n", |
| 57 | + "\n", |
| 58 | + "Ready to start hooking everything up? Check out the circuit diagram and hookup table below to see how everything is connected.\n", |
| 59 | + "\n", |
| 60 | + "### Circuit Diagram\n", |
| 61 | + "\n", |
| 62 | + "TODO: Replace with new fritzing showing the qwiic conection between the OLED and the RedBoard RP2350\n", |
| 63 | + "\n", |
| 64 | + "\n", |
| 65 | + "**Note for Advanced Users**: If you know how to read datasheets and schematics, you can also refer to the schematic below as an alternative.\n", |
| 66 | + "\n", |
| 67 | + "TODO: Replace with new schematic showing the qwiic conection between the OLED and the RedBoard RP2350\n", |
| 68 | + "\n", |
| 69 | + "\n", |
| 70 | + "### Hookup Table\n", |
| 71 | + "\n", |
| 72 | + "TODO: Change to match the new simple connection of:\n", |
| 73 | + " 5V -> temp +V \n", |
| 74 | + " GND -> temp GND\n", |
| 75 | + " A0 -> temp SIGNAL\n", |
| 76 | + " OLED Qwiic -> RedBoard Qwiic\n", |
| 77 | + "\n", |
| 78 | + "| Component | RedBoard | Breadboard | Breadboard | Breadboard |\n", |
| 79 | + "|----------------------------|--------------------|-----------------|-----------------|-----------------|\n", |
| 80 | + "| Jumper Wire | 5V | 5V Rail ( + ) | | |\n", |
| 81 | + "| Jumper Wire | GND | GND Rail ( - ) | | |\n", |
| 82 | + "| LCD | | A15-A30 (Pin 1 on A15) | | |\n", |
| 83 | + "| Jumper Wire | | E30 | GND Rail ( - ) | |\n", |
| 84 | + "| Jumper Wire | | E29 | 5V Rail ( + ) | |\n", |
| 85 | + "| Jumper Wire | Digital Pin 8 | E28 | | |\n", |
| 86 | + "| Jumper Wire | Digital Pin 9 | E27 | | |\n", |
| 87 | + "| Jumper Wire | Digital Pin 10 | E26 | | |\n", |
| 88 | + "| Jumper Wire | Digital Pin 11 | E25 | | |\n", |
| 89 | + "| Jumper Wire | Digital Pin 12 | E20 | | |\n", |
| 90 | + "| Jumper Wire | | E19 | GND Rail ( - ) | |\n", |
| 91 | + "| Jumper Wire | Digital Pin 13 | E18 | | |\n", |
| 92 | + "| Jumper Wire | | E16 | 5V Rail ( + ) | |\n", |
| 93 | + "| Jumper Wire | | E15 | GND Rail ( - ) | |\n", |
| 94 | + "| Potentiometer | | A8 | A9 | A10 |\n", |
| 95 | + "| Jumper Wire | | E9 | E17 | |\n", |
| 96 | + "| Jumper Wire | | E8 | GND Rail ( - ) | |\n", |
| 97 | + "| Jumper Wire | | E10 | 5V Rail ( + ) | |\n", |
| 98 | + "| TMP36 Temperature Sensor | | A1 (GND) | A2 (Signal) | A3 (V+) |\n", |
| 99 | + "| Jumper Wire | | E1 | GND Rail ( - ) | |\n", |
| 100 | + "| Jumper Wire | Analog Pin 0 (A0) | E2 | | |\n", |
| 101 | + "| Jumper Wire | | E3 | 5V Rail ( + ) | |\n", |
| 102 | + "\n" |
| 103 | + ] |
| 104 | + }, |
| 105 | + { |
| 106 | + "cell_type": "markdown", |
| 107 | + "id": "1bd52930-d783-460a-923b-41a3c37d2f2b", |
| 108 | + "metadata": {}, |
| 109 | + "source": [ |
| 110 | + "## Using the OLED.\n", |
| 111 | + "\n", |
| 112 | + "Now that your circuit is built, it's time to write to the OLED. This is done using MicroPython, which is running on the RedBoard.\n", |
| 113 | + "\n", |
| 114 | + "The first step is to connect your RedBoard to a USB port on this computer.\n", |
| 115 | + "\n", |
| 116 | + "Select the \"Connect\" button at the bottom right of this screen and a panel is displayed\n", |
| 117 | + "\n", |
| 118 | + "Select the \"Connect Device\" Button, and when the selection dialog appears, select the port with that displays ***Board in FS mode (...)*** or *TBD*\n", |
| 119 | + "\n", |
| 120 | + "\n", |
| 121 | + "\n", |
| 122 | + "With the RedBoard connected, use the following MicroPython commands to write to the OLED. \n", |
| 123 | + "\n", |
| 124 | + "### Using MicroPython\n", |
| 125 | + "\n", |
| 126 | + "The following MicroPython commands are entered to write to the OLED. \n", |
| 127 | + "\n", |
| 128 | + "**REMEMBER** To enter a MicroPython command, hold down either the Control (on Windows) or Command (on Mac) key when pressing *Enter*\n", |
| 129 | + "\n", |
| 130 | + "#### Step 1 - Setup\n", |
| 131 | + "\n", |
| 132 | + "Lets start by importing any of the libaries we plan on using and setting up our pins." |
| 133 | + ] |
| 134 | + }, |
| 135 | + { |
| 136 | + "cell_type": "code", |
| 137 | + "execution_count": null, |
| 138 | + "id": "4494b462-505b-4a23-8ebc-28b54152bd88", |
| 139 | + "metadata": {}, |
| 140 | + "outputs": [], |
| 141 | + "source": [ |
| 142 | + "# The qwiic_oled driver module allows for control of SparkFun OLEDs.\n", |
| 143 | + "# The QwiicLargeOled class is for the Large 1.3\" OLED display in our SIK\n", |
| 144 | + "from qwiic_oled import QwiicLargeOled\n", |
| 145 | + "from machine import ADC # Allows us to use \"ADC\" (analog-to-digital conversion) to read from our analog pin\n", |
| 146 | + "from machine import Pin # Allows us to use \"Pin\" to use code to interface with the pins on our board\n", |
| 147 | + "\n", |
| 148 | + "# Define the OLED object that we will use\n", |
| 149 | + "# Note how we don't have to provide the pins, the driver automatically selects the pins for the qwiic connector\n", |
| 150 | + "myOLED = QwiicLargeOled()\n", |
| 151 | + "\n", |
| 152 | + "# Create an ADC object for reading the temperature sensor\n", |
| 153 | + "tempSensor = ADC(Pin.board.A0) # A0 is the pin we connected the temperature sensor to\n" |
| 154 | + ] |
| 155 | + }, |
| 156 | + { |
| 157 | + "cell_type": "markdown", |
| 158 | + "id": "2d94be96-a8c9-4932-8111-58d10a8622a9", |
| 159 | + "metadata": {}, |
| 160 | + "source": [ |
| 161 | + "#### Step 2 - Reading Temperature\n", |
| 162 | + "Now let's write functions to read the temperature in both celcius and Fahrenheit using the \"algorithm\" that we discussed above. " |
| 163 | + ] |
| 164 | + }, |
| 165 | + { |
| 166 | + "cell_type": "code", |
| 167 | + "execution_count": null, |
| 168 | + "id": "cdae6523", |
| 169 | + "metadata": {}, |
| 170 | + "outputs": [], |
| 171 | + "source": [ |
| 172 | + "def temperatureC():\n", |
| 173 | + " voltage = tempSensor.read_u16() * 3.3 / 65535.0 # Convert the raw reading to a voltage (0-5V)\n", |
| 174 | + " degreesC = (voltage - 0.5) * 100.0 # Convert the voltage to degrees Celsius\n", |
| 175 | + " return degreesC\n", |
| 176 | + "\n", |
| 177 | + "def temperatureF():\n", |
| 178 | + " degreesC = temperatureC() # Get the temperature in Celsius\n", |
| 179 | + " degreesF = (degreesC * 9.0 / 5.0) + 32.0 # Convert Celsius to Fahrenheit\n", |
| 180 | + " return degreesF" |
| 181 | + ] |
| 182 | + }, |
| 183 | + { |
| 184 | + "cell_type": "markdown", |
| 185 | + "id": "bcbdc5aa", |
| 186 | + "metadata": {}, |
| 187 | + "source": [ |
| 188 | + "#### Step 3 - Displaying Temperature on the OLED\n", |
| 189 | + "\n", |
| 190 | + "Finally, lets read the temperature and display it on the OLED." |
| 191 | + ] |
| 192 | + }, |
| 193 | + { |
| 194 | + "cell_type": "code", |
| 195 | + "execution_count": null, |
| 196 | + "id": "04884e2e", |
| 197 | + "metadata": {}, |
| 198 | + "outputs": [], |
| 199 | + "source": [ |
| 200 | + "from time import sleep\n", |
| 201 | + "myOLED.begin() # Initialize the OLED\n", |
| 202 | + "\n", |
| 203 | + "# Infinite loop to continuously read the temperature and display it\n", |
| 204 | + "while True:\n", |
| 205 | + " tempC = temperatureC() # Read the temperature in Celsius\n", |
| 206 | + " tempF = temperatureF() # Read the temperature in Fahrenheit\n", |
| 207 | + "\n", |
| 208 | + " # Clear the OLED display\n", |
| 209 | + " myOLED.clear(myOLED.ALL) # Clear OLED graphic memory.\n", |
| 210 | + " myOLED.clear(myOLED.PAGE) # Clear the processor's display buffer.\n", |
| 211 | + "\n", |
| 212 | + " # Print the temperature readings to the OLED\n", |
| 213 | + " # Print temperature in Celsius\n", |
| 214 | + " myOLED.set_cursor(0, 0) # Set cursor to the top-left corner\n", |
| 215 | + " myOLED.print(f\"Temp C: {tempC:5}\") # Print temperature in Celsius (formatted to 5 characters wide)\n", |
| 216 | + " myOLED.set_cursor(0, 10) # Move cursor to the next line (down 10 pixels)\n", |
| 217 | + " myOLED.print(f\"Temp F: {tempF:5}\") # Print temperature in Fahrenheit (formatted to 5 characters wide)\n", |
| 218 | + "\n", |
| 219 | + " myOLED.display() # Display the updated text on the OLED\n", |
| 220 | + "\n", |
| 221 | + " sleep(1) # Wait for 1 second before reading again" |
| 222 | + ] |
| 223 | + }, |
| 224 | + { |
| 225 | + "cell_type": "markdown", |
| 226 | + "id": "10d5c3fe-852f-42f7-8378-85dc8c8c7c3e", |
| 227 | + "metadata": {}, |
| 228 | + "source": [ |
| 229 | + "## What You Should See\n", |
| 230 | + "The OLED will show the temperature in Celsius and Fahrenheit. The temperature readings will update every second. An easy way to see the temperature change is to press your finger to the sensor or to breath on it.\n", |
| 231 | + "\n", |
| 232 | + "## You've Completed Circuit 4B!\n", |
| 233 | + "\n", |
| 234 | + "Continue to circuit 4C to build a fun game incorporating your OLED.\n", |
| 235 | + "\n", |
| 236 | + "" |
| 237 | + ] |
| 238 | + } |
| 239 | + ], |
| 240 | + "metadata": { |
| 241 | + "kernelspec": { |
| 242 | + "display_name": "MicroPython upydevice kernel", |
| 243 | + "language": "python", |
| 244 | + "name": "micropython-upydevice" |
| 245 | + }, |
| 246 | + "language_info": { |
| 247 | + "codemirror_mode": "python", |
| 248 | + "file_extension": ".py", |
| 249 | + "mimetype": "text/x-python", |
| 250 | + "name": "python", |
| 251 | + "pygments_lexer": "python" |
| 252 | + } |
| 253 | + }, |
| 254 | + "nbformat": 4, |
| 255 | + "nbformat_minor": 5 |
| 256 | +} |
0 commit comments