From 8bdf805342ae8f89f3f7071f1e7e6e4128621a7a Mon Sep 17 00:00:00 2001 From: root Date: Wed, 29 Jul 2020 17:52:58 +0000 Subject: [PATCH 1/7] added ath20 and th02 example notebooks --- .../3_led_bar-checkpoint.ipynb | 526 +++++++++++++++++ bootcamp_sessions/3_led_bar.ipynb | 18 +- ...ensors_and_board_to_board-checkpoint.ipynb | 454 +++++++++++++++ .../1_2_temp_sensor_AHT20-checkpoint.ipynb | 141 +++++ .../2_1_computer_vision-checkpoint.ipynb | 550 ++++++++++++++++++ .../1_1_sensors_and_board_to_board.ipynb | 1 - breakout_sessions/1_2_temp_sensor_AHT20.ipynb | 27 +- breakout_sessions/sds_trace_data.dat | Bin 0 -> 32 bytes ...temp_ledbar_example_ATH20-checkpoint.ipynb | 277 +++++++++ .../temp_ledbar_example_TH02-checkpoint.ipynb | 268 +++++++++ extra/sds_trace_data.dat | Bin 0 -> 32 bytes extra/temp_ledbar_example_ATH20.ipynb | 277 +++++++++ extra/temp_ledbar_example_TH02.ipynb | 268 +++++++++ 13 files changed, 2796 insertions(+), 11 deletions(-) create mode 100644 bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb create mode 100644 breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb create mode 100644 breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb create mode 100644 breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb create mode 100644 breakout_sessions/sds_trace_data.dat create mode 100644 extra/.ipynb_checkpoints/temp_ledbar_example_ATH20-checkpoint.ipynb create mode 100644 extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb create mode 100644 extra/sds_trace_data.dat create mode 100644 extra/temp_ledbar_example_ATH20.ipynb create mode 100644 extra/temp_ledbar_example_TH02.ipynb diff --git a/bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb b/bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb new file mode 100644 index 0000000..eb5ac6c --- /dev/null +++ b/bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb @@ -0,0 +1,526 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.overlays.base import BaseOverlay\n", + "base = BaseOverlay(\"base.bit\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. Tell PYNQ About the LED Bar\n", + "\n", + "The LED bar will be connected to connector G1 on the PYNQ Grove adapter. The PYNQ Grove adapter will be connected to PMODA on the PYNQ-Z2 board." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.pmod import Grove_LEDbar\n", + "from pynq.lib.pmod import PMOD_GROVE_G1\n", + "\n", + "ledbar = Grove_LEDbar(base.PMODA, PMOD_GROVE_G1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Reset the LED Bar\n", + "\n", + "The default state of the LED could be all sorts of things. Let's turn it fully of so we have somewhere to work from." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Turn the LED bar off\n", + "ledbar.reset()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The LED bar should be blank now.\n", + "\n", + "### 4. Lighting Up the LED Bar\n", + "\n", + "The LED Bar supports a lot of different display configurations. Let's start with something simple, turning on all the bars." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ledbar.write_binary(0b1111111111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Your LED bar should be all lit up now. How did writing `0b1111111111` to the ledbar turn it on?\n", + "\n", + "The LED bar speaks binary. Binary is a alternate number base used in computing. We could get into a much longer discussion about binary, but for now let's just se how the LED bar responds to different inputs.\n", + "\n", + "Run the cell below and observe the output!" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from time import sleep\n", + "ledbar.write_binary(0b0000000000)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0000000001)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0000000011)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0000000111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0000001111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0000011111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0000111111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0001111111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0011111111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b0111111111)\n", + "sleep(0.25)\n", + "ledbar.write_binary(0b1111111111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Any guesses on how the LED bar interprets the binary numbers?\n", + "\n", + "### 5. Light up each element of the LED Bar\n", + "\n", + "Last time we blinked the LED over and over. Let's do something similar with the LED bar! Let's light up each element in sequence." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Loop 5 times\n", + "for i in range(5):\n", + " ledbar.write_binary(0b0000000001)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0000000010)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0000000100)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0000001000)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0000010000)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0000100000)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0001000000)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0010000000)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b0100000000)\n", + " sleep(0.25)\n", + " ledbar.write_binary(0b1000000000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Writing out the entire binary number each time can prove annoying. Let's write a quick python function to make this easier.\n", + "\n", + "If we want to light up a specific element on the LED bar we use the following algorithm to convert our index to a binary number.\n", + "\n", + "$binary = 2^{index}$\n", + "\n", + "We can implement that in a python function as follows. Functions are a powerful tool that most programming languages provide. Functions allow us to write a single piece of code and use it again from anywhere we want. Many of the operations we have been doing (`read()`, `write_binary()`, `sleep()`) are all functions. \n", + "\n", + "If you have never worked with Python functions before there is a short tutorial you can run through [here](https://www.w3schools.com/python/python_functions.asp).\n", + "\n", + "We can create functions with the `def` keyword.\n", + "\n", + "We are going to name our function `element` and have it take one argument called `index`.\n", + "\n", + "Finally, the function is going to return the algorithm we defined before." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def element(index):\n", + " # In python the ** operator is exponentiation\n", + " return 2**index" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's use it to light up the middle of the LED bar. Try replacing the 5 with different numbers.\n", + "\n", + "Now let's do our scrolling LED bar from before. This time, notice how much more concisely we can write it." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(5):\n", + " for j in range(10):\n", + " ledbar.write_binary(element(j))\n", + " sleep(0.25)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 6. Light up part of the LED bar\n", + "\n", + "Let's try to light up part of the LED Bar. A display like this would be good for a battery or volume meter. A simple way to do this is to hard code the binary value we want." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Light up half the LED bar\n", + "ledbar.write_binary(0b0000011111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This works but, again, this is annoying to enter. Let's use our function technique from before.\n", + "\n", + "The algorithm for calculating the binary number required to light up part of the LED bar is:\n", + "\n", + "$binary = 2^{index+1} - 1$\n", + "\n", + "Now let's implement this in a function." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def up_to(index):\n", + " return 2**(index+1) - 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's test it out!" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "ledbar.write_binary(up_to(5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have a easy way to do this, let's try our loop method from before." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(5):\n", + " for j in range(10):\n", + " ledbar.write_binary(up_to(j))\n", + " sleep(0.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is great, but only works if we want to light up the LED bar from one end. What happens if we want to do the\n", + "other direction?\n", + "\n", + "Luckily, Python has an inverse operator we can use. Check out the following cell!" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "ledbar.write_binary(~up_to(5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By putting the `~` character in front, we can covert a number like `0b0000111111` into `0b1111000000`.\n", + "\n", + "Question: What would happen if we applied the `~` operator to the `element` function we wrote before?\n", + "\n", + "Talk about this in your groups and when you have a guess give the next cell a try!" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "ledbar.write_binary(~element(5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Cool?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Controlling the LED Bar with Other Peripherals\n", + "\n", + "Similar to before, we are going to combine the on board buttons with the external LED Bar.\n", + "\n", + "### 1. Setup the Buttons\n", + "\n", + "First let's setup the on-board switches so we can read their state. " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "buttons = base.buttons" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. Check the Status of the Buttons\n", + "\n", + "Next, let's check is the status of the buttons. You can run this cell multiple times to see how the output changes when you hold the buttons." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Button 0 is off\n", + "Button 1 is off\n", + "Button 2 is off\n", + "Button 3 is on\n" + ] + } + ], + "source": [ + "print(f'Button 0 {\"is on\" if buttons[0].read() else \"is off\"}')\n", + "print(f'Button 1 {\"is on\" if buttons[1].read() else \"is off\"}')\n", + "print(f'Button 2 {\"is on\" if buttons[2].read() else \"is off\"}')\n", + "print(f'Button 3 {\"is on\" if buttons[3].read() else \"is off\"}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Control the LED Bar with the Buttons\n", + "\n", + "Now, let's build a program to cycle the LED bar every time button 0 is pressed!\n", + "\n", + "First, we need to to be able to wait for a button to be pressed. Run the cell below and then press button 0." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Button 0 was pressed\n" + ] + } + ], + "source": [ + "while buttons[0].read() == 0:\n", + " pass\n", + "print('Button 0 was pressed')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have that down, let's bring back some of the LED Bar scrolling code from before." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "for i in range(10):\n", + " ledbar.write_binary(element(i))\n", + " sleep(0.25)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we need to combine the two previous cells to create our program. I'll leave you an empty cell below to try it yourself. If you get stuck, run the next cell for a hint!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(10):\n", + " ledbar.write_binary(element(i))\n", + " while buttons[0].read() == 0:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Woah, that probably didn't do what you expected. Why did the element jump so much?\n", + "\n", + "This in cause by the python code running too quickly. Before you are able to let go of the button, the for loop has already iterated 5 or more times. We can fix this by adding a sleep statement to add some delay to account for our slow reflexes!\n", + "\n", + "Run the next cell and try pressing the button a few times. Try holding the button too!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(10):\n", + " ledbar.write_binary(element(i))\n", + " while buttons[0].read() == 0:\n", + " pass\n", + " sleep(0.25)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "You're done! You now hopefully have some understanding of how the LED bar works and how we can interact with it. Here are some more advanced activities you can give a try.\n", + "\n", + "1. Flash alternating sets of lights (try using a function to make this easier).\n", + "2. Count how many times a button is pressed and display it on the LED bar.\n", + "3. Display which built in buttons and switches are being pressed (if button 0 is pressed -> led bar element 0 is lit, etc)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/bootcamp_sessions/3_led_bar.ipynb b/bootcamp_sessions/3_led_bar.ipynb index 44fd859..a4b9cb4 100644 --- a/bootcamp_sessions/3_led_bar.ipynb +++ b/bootcamp_sessions/3_led_bar.ipynb @@ -207,7 +207,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -227,9 +227,21 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'ledbar' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mledbar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite_binary\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melement\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.25\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'ledbar' is not defined" + ] + } + ], "source": [ "for i in range(5):\n", " for j in range(10):\n", diff --git a/breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb b/breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb new file mode 100644 index 0000000..72e359b --- /dev/null +++ b/breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb @@ -0,0 +1,454 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Sensors and Board to Board Communication\n", + "\n", + "This session will cover reading data from the Grove TH02 Temperature and Humidity Sensor as well as transmitting data from one board to another over the internet." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 1: Setup" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 Initialize Overlay\n", + "Our PYNQ Board has a Field Programmable Gate Array (FPGA) on it that must be programmed before we begin using the board. We apply designs called overlays that we can design however we want. For the first part of this tutorial, we are going to use the pre-built base overlay." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.overlays.base import BaseOverlay\n", + "base = BaseOverlay(\"base.bit\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Import Temperature Sensor Libraries\n", + "Here we tell the board what libraries we want to use in our project." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.arduino import Grove_TH02\n", + "from pynq.lib.arduino import ARDUINO_GROVE_I2C" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 2: Reading Temperature and Humidity" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Plugging in your TH02 Sensor\n", + "\n", + "Plug your PMOD to Grove adaptor (shown in picture below) into one of your PMOD connectors on your PYNQ board. Then plug you TH02 humidity sensor into the one of the four white Grove adaptor ports\n", + "\n", + "![grove_adaptor](https://cdn10.bigcommerce.com/s-7gavg/products/531/images/4194/PYNQ_Shield_-_Oblique_-_600__81639.1473444236.1280.1280.png?c=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Initialize the Temperature Sensor\n", + "\n", + "We create an variable called \"th02\" that represents the sensor. From this object we can call functions that retrieve data from the sensor." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "th02 = Grove_TH02(base.ARDUINO,ARDUINO_GROVE_I2C)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Read the Temperature and Humidity\n", + "Calling the function read() returns a tuple (two values separated by a comma). The first value is temperature and the second value is humidity." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "temp_c, humidity = th02.read()\n", + "print('The temperature is {} degrees celsius and the relative humidity is {} %'.format(temp_c, humidity))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.4 Convert to Fahrenheit\n", + "\n", + "Converting to Fahrenheit is done by the following equation: \n", + "\n", + "fahrenheit = celsius * (9/5) + 32" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "temp_f = temp_c * (9/5) + 32\n", + "print(f'The temperature is {temp_f} F')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.5 Averaging the Temperature" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Both computers and the world aren't always perfect. This means that there can be some variation in values that we see. Averaging is a technique that can help up try to hone in on the \"correct\" answer that we are looking for. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, let's read a number of values from the temperature sensor." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create temperatures as an empty array\n", + "temps = []\n", + "# read 5 temperature values and store then in the \"temps\" array\n", + "for i in range(5):\n", + " # read temp in C\n", + " temp_c, _ = th02.read()\n", + " # convert to F\n", + " temp_f = temp_c * (9/5) + 32\n", + " # append temp_f to temps\n", + " temps.append(temp_f)\n", + "print(temps)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have all 5 temperature values stored in an array, let's average them! To average the values, we want to sum them up and then divide the total number of values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "average_sum = 0\n", + "# sum up all the values\n", + "for temp in temps:\n", + " average_sum = average_sum + temp\n", + "print(f\"average_sum: {average_sum}\")\n", + "average = average_sum / len(temps)\n", + "print(f\"average: {average}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 3: Board to Board Communication\n", + "\n", + "In many situations, sensors will need to be a distance away from where the data is needed. For instance, you may want to know the temperature at different locations around a city and be able to monitor this from one central location. To do this, we can send data over the internet. You can also send many types of data beyond this sensor such as text." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!pip3 install getmac\n", + "!pip3 install ./pynq-p2p" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pynqp2p" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.1 Register with the central server\n", + "In order to ensure not just anyone can access our data, we use a secret passcode to verify our identity and register with the server that will store our data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ip_address = '[IP address of the server goes here]'\n", + "key = '[secret passcode goes here]'\n", + "pynqp2p.register(ip_address, key)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.2 Make sure we are able to communicate with the server\n", + "The function ping() simply sends a message to our server and the server sends a message back saying it heard us." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pynqp2p.ping()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.3 Get a unique ID from your Board\n", + "Your board has a unique ID number called a MAC address. The function get_id() returns a unique number based on this MAC address that you can share with people you want to be able to send you messages. Make sure that the way you share this is secure (such as email) so that you don't have people spamming you with unwanted information." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "myid = pynqp2p.get_id()\n", + "print(f\"Your ID is {myid}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.4 Send a message to a board with a particular ID\n", + "The function send() sends a message to the board with the particular ID number you pass it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "recipient_id = 'put your teammates ID here'\n", + "pynqp2p.send(recipient_id, \"Hello!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.5 Receive Messages\n", + "The function receive() asks the server to give you the most recent message sent to you. Afterwards, it deletes the message (which means you can only receive it once). The function receive_all() retrieves all the messages in the server at once and returns them as a list." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pynqp2p.receive()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.6 Sending Multiple Messages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sometimes it is helpful to send multiple messages in a row to another PYNQ board. A really simple way to do this is to run the send(id) command multiple times;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pynqp2p.send(myid, \"Hello 0\")\n", + "pynqp2p.send(myid, \"Hello 1\")\n", + "pynqp2p.send(myid, \"Hello 2\")\n", + "pynqp2p.send(myid, \"Hello 3\")\n", + "pynqp2p.send(myid, \"Hello 4\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now in order to recieve these messages, we'll have to call the recieve() function a few times." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(pynqp2p.receive())\n", + "print(pynqp2p.receive())\n", + "print(pynqp2p.receive())\n", + "print(pynqp2p.receive())\n", + "print(pynqp2p.receive())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This seems tedious, there must be a better way! If you remember earlier, we used a for loop to read multiple temperatures from the temperature sensor and put them in an array. We can use the same technique here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(5):\n", + " pynqp2p.send(myid, \"Hello \" + str(i))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we will use another for loop to retrieve all the messages we just sent. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(5):\n", + " print(pynqp2p.receive())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, this is a lot less tedious and required a lot less code to achieve the same goal. The only problem here is that we can only access the retrieved messages one at a time. pynqp2p containes a really useful function called recieve_all() that helps us here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# first, let's send ourselves 5 messages\n", + "for i in range(5):\n", + " pynqp2p.send(myid, \"Hello \" + str(i))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# now, let's see what the recieve_all() functions does for us\n", + "print(pynqp2p.receive_all())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now you've learned the basics of pynqp2p! Let's try something new. Can you figure out how to send some of the temperature data from earlier? Can you send your Celcius measurement to someone else to be converted into Fahrenheit? Can you send your temperature measurement to someone else and have them respond with weather it's larger or smaller?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The possibilites are endless!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb b/breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb new file mode 100644 index 0000000..eb43f2d --- /dev/null +++ b/breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb @@ -0,0 +1,141 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Grove AHT20 (Humidity & Temperature Sensor)\n", + "\n", + "This notebook shows how to install the Python driver for the AHT20 temperature sensor and use it to make a humidity/temperature measurement.\n", + "\n", + "### 1. Initialize Overlay" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from pynq.overlays.base import BaseOverlay\n", + "base = BaseOverlay(\"base.bit\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. Install Python Driver" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting git+https://github.com/LewisMcL/pynq_drivers\n", + " Cloning https://github.com/LewisMcL/pynq_drivers to /tmp/pip-ap5mlg2i-build\n", + "Installing collected packages: pmod-grove-aht20\n", + " Running setup.py install for pmod-grove-aht20 ... \u001b[?25ldone\n", + "\u001b[?25hSuccessfully installed pmod-grove-aht20-1.0\n" + ] + } + ], + "source": [ + "!pip3 install git+https://github.com/LewisMcL/pynq_drivers --no-deps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Import Libraries\n", + "\n", + "Make sure your PMOD to Grove adapter is connected to the PMODB port. We are importing PMOD_GROVE_G3, because the AHT20 sensor is connected to the 3rd Grove adaptor port. If you have it plugged into G4, you will have to do `from pynq.lib.pmod import PMOD_GROVE_G4` instead. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from grove import Grove_AHT20\n", + "from pynq.lib.pmod import PMOD_GROVE_G3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4. Receiving Measurements" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Humidity: 38.73 %\n", + "Temperature: 27.34 °C\n" + ] + } + ], + "source": [ + "py_ht = Grove_AHT20(base.PMODB, PMOD_GROVE_G3)\n", + "\n", + "humidity = py_ht.get_humidity()\n", + "temperature = py_ht.get_temp()\n", + "print('Humidity: ', float(\"{0:.2f}\".format(humidity)), '%')\n", + "print('Temperature: ', float(\"{0:.2f}\".format(temperature)), '°C')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb b/breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb new file mode 100644 index 0000000..bbfc141 --- /dev/null +++ b/breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb @@ -0,0 +1,550 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Computer Vision\n", + "\n", + "### In this tutorial, we are going to learn how to take a photo with a webcam attached to our Pynq Board, display this image in our Jupyter Notebook, and then detect faces in the photo. For extra credit, we will use a neural net to predict the objects in a photo." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 1: Setup" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 Load Overlay\n", + "Our PYNQ Board has a Field Programmable Gate Array (FPGA) on it that must be programmed before we begin using the board. We apply designs called overlays that we can design however we want. For the first part of this tutorial, we are going to use the pre-built base overlay." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.overlays.base import BaseOverlay\n", + "from pynq.lib.video import *\n", + "base = BaseOverlay(\"base.bit\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Import Libraries\n", + "Here we tell the board what libraries we want to use in our project." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import cv2\n", + "from matplotlib import pyplot as plt\n", + "import numpy as np\n", + "from IPython import display" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.3 Initialize Webcam\n", + "After plugging in our USB webcam, we must tell the board what size images it is going to be recording and sending to the board. We also need to create a python object that will store the images we read from the webcam." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#create object\n", + "videoIn = cv2.VideoCapture(0)\n", + "\n", + "#set input width and height\n", + "input_frame_width = 640\n", + "input_frame_height = 480\n", + "videoIn.set(cv2.CAP_PROP_FRAME_WIDTH, input_frame_width);\n", + "videoIn.set(cv2.CAP_PROP_FRAME_HEIGHT, input_frame_height);\n", + "\n", + "#check to ensure the webcam is open\n", + "if(videoIn.isOpened()):\n", + " print('camera is ready')\n", + "else:\n", + " print('error starting camera, run this cell again')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 2: Face Detection" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Take Photo\n", + "Once we have our board setup and webcam working, it is time to use it! using videoIn.read(), we can read what the webcam is looking at at any given moment. This function has two return values. The first tells us if we successfully read an image or not. True means we did, false means there was a problem. The second return value is a frame object, which is the actual image we read." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#read frame\n", + "success, frame = videoIn.read()\n", + "#if there was an error, tell us!\n", + "if (success != True):\n", + " print(\"Video Read Error\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Display Photo\n", + "Using matplotlib imported earlier, we can display our image right in our Jupyter notebook" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#display input\n", + "plt.imshow(frame[:,:,[2,1,0]])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Look for Faces\n", + "Now that we can take a photo, let's have our board look for faces in our photo. We are going to use something called a Haar Cascade Classifier. This is a model that has been training to understand what a face looks like. It has already been built and trained, so we simply need to load it and pass our image to it. Below is what the model is looking for when it tries to find faces, can you trick it?\n", + "![HaarClassifier](data/haar.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#create our own instance of the classifier\n", + "face_cascade = cv2.CascadeClassifier(\n", + " '/home/xilinx/jupyter_notebooks/base/video/data/'\n", + " 'haarcascade_frontalface_default.xml')\n", + "\n", + "#our classifier prefers to work on a gray image\n", + "gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n", + "faces = face_cascade.detectMultiScale(gray, 1.3, 5)\n", + "\n", + "#draw a rectangle around any faces we find\n", + "for (x,y,w,h) in faces:\n", + " cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)\n", + " roi_gray = gray[y:y+h, x:x+w]\n", + " roi_color = frame[y:y+h, x:x+w]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.4 Show our image again with the face detection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "plt.imshow(frame[:,:,[2,1,0]])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.5 Look for Eyes\n", + "The board also have another classifier for detecting features that look like eyes. We will do the same thing we did with the face classifier for the eye classifier." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#create our own instance of the classifier\n", + "eye_cascade = cv2.CascadeClassifier(\n", + " '/home/xilinx/jupyter_notebooks/base/video/data/'\n", + " 'haarcascade_eye.xml')\n", + "\n", + "eyes = eye_cascade.detectMultiScale(roi_gray)\n", + "for (ex,ey,ew,eh) in eyes:\n", + " cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.6 Show image with eye and face detection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "plt.imshow(frame[:,:,[2,1,0]])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.7 Counting Faces\n", + "The faces our program found are contained in an array. This stores the location of the faces within the image. If we want to count the faces found in the image, we can simply print the length of this array." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(len(faces))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 3: Guess the object with a neural net" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.1 Import a Neural Network" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "! sudo pip3 install git+https://github.com/Xilinx/QNN-MO-PYNQ.git" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import qnn\n", + "from qnn import Dorefanet\n", + "from qnn import utils\n", + "import os, pickle, random\n", + "from PIL import Image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.2 Take Another Image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "success, frame2 = videoIn.read()\n", + "\n", + "#if there was an error, tell us!\n", + "if (success != True):\n", + " print(\"Video Read Error\")\n", + " \n", + "#display the image\n", + "plt.imshow(frame2[:,:,[2,1,0]])\n", + "plt.show() \n", + "\n", + "#save the image just taken to memory\n", + "cv2.imwrite(\"photo.jpg\", frame2)\n", + "\n", + "videoIn.release()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.3 Set Up the Object Classifier\n", + "This classifier has been trained to recognize a wide variety of objects. It requires us to reconfigure the FPGA on the board (replacing the base overlay with a custom overlay that will help accelerate the classification). This is automatically done with the init_accelerator() function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "classifier = Dorefanet()\n", + "classifier.init_accelerator()\n", + "net = classifier.load_network(json_layer=\"/usr/local/lib/python3.6/dist-packages/qnn/params/dorefanet-layers.json\")\n", + "\n", + "conv0_weights = np.load('/usr/local/lib/python3.6/dist-packages/qnn/params/dorefanet-conv0.npy', encoding=\"latin1\").item()\n", + "fc_weights = np.load('/usr/local/lib/python3.6/dist-packages/qnn/params/dorefanet-fc-normalized.npy', encoding='latin1').item()\n", + "\n", + "with open(\"/home/xilinx/jupyter_notebooks/qnn/imagenet-classes.pkl\", 'rb') as f:\n", + " classes = pickle.load(f)\n", + " names = dict((k, classes[k][1].split(',')[0]) for k in classes.keys())\n", + " synsets = dict((classes[k][0], classes[k][1].split(',')[0]) for k in classes.keys())\n", + " \n", + "conv0_W = conv0_weights['conv0/W']\n", + "conv0_T = conv0_weights['conv0/T']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.4 Run the Image through the Classifier\n", + "Once our classifier is set up, we input our image to the neural net." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "img, img_class = classifier.load_image(\"photo.jpg\")\n", + "\n", + "# 1st convolutional layer execution, having as input the image and the trained parameters (weights)\n", + "conv0 = utils.conv_layer(img, conv0_W, stride=4)\n", + "# The result in then quantized to 2 bits representation for the subsequent HW offload\n", + "conv0 = utils.threshold(conv0, conv0_T)\n", + "\n", + "\n", + "# Compute offloaded convolutional layers\n", + "out_dim = net['merge4']['output_dim']\n", + "out_ch = net['merge4']['output_channels']\n", + "\n", + "conv_output = classifier.get_accel_buffer(out_ch, out_dim);\n", + "conv_input = classifier.prepare_buffer(conv0)\n", + "\n", + "classifier.inference(conv_input, conv_output)\n", + "\n", + "conv_output = classifier.postprocess_buffer(conv_output)\n", + "\n", + "\n", + "# Normalize results\n", + "fc_input = conv_output / np.max(conv_output)\n", + "\n", + "# FC Layer 0\n", + "fc0_W = fc_weights['fc0/Wn']\n", + "fc0_b = fc_weights['fc0/bn']\n", + "\n", + "fc0_out = utils.fully_connected(fc_input, fc0_W, fc0_b)\n", + "fc0_out = utils.qrelu(fc0_out)\n", + "fc0_out = utils.quantize(fc0_out, 2)\n", + "\n", + "# FC Layer 1\n", + "fc1_W = fc_weights['fc1/Wn']\n", + "fc1_b = fc_weights['fc1/bn']\n", + "\n", + "fc1_out = utils.fully_connected(fc0_out, fc1_W, fc1_b)\n", + "fc1_out = utils.qrelu(fc1_out)\n", + "\n", + "# FC Layer 2\n", + "fct_W = fc_weights['fct/W']\n", + "fct_b = np.zeros((fct_W.shape[1], ))\n", + "\n", + "fct_out = utils.fully_connected(fc1_out, fct_W, fct_b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.5 Use Softmax to Estimate the Probability of the Top 5 Most Likely Classes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Softmax\n", + "out = utils.softmax(fct_out)\n", + "\n", + "# Top-5 results\n", + "topn = utils.get_topn_indexes(out, 5) \n", + "for k in topn: print(\"class:{0:>20}\\tprobability:{1:>8.2%}\".format(names[k].lower(), out[k]))\n", + "\n", + "#display results\n", + "x_pos = np.arange(len(topn))\n", + "plt.barh(x_pos, out[topn], height=0.4, color='g', zorder=3)\n", + "plt.yticks(x_pos, [names[k] for k in topn])\n", + "plt.gca().invert_yaxis()\n", + "plt.xlim([0,1])\n", + "plt.grid(zorder=0)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 4: Gesture Sensor\n", + "\n", + "Now we will explore the Grove Gesture Sensor and use it to take pictures with our webcam.\n", + "\n", + "[Grove gesture sensor](http://wiki.seeedstudio.com/Grove-Gesture_v1.0/) on the board.\n", + "The gesture sensor can detect 10 gestures as follows:\n", + "\n", + "| Value the Sensor Returns | Gesture |\n", + "|--------------------------|--------------------|\n", + "| 0 | No detection |\n", + "| 1 | forward |\n", + "| 2 | backward |\n", + "| 3 | right |\n", + "| 4 | left |\n", + "| 5 | up |\n", + "| 6 | down |\n", + "| 7 | clockwise |\n", + "| 8 | counter-clockwise |\n", + "| 9 | wave |\n", + "\n", + "\n", + "For this notebook, a PYNQ Arduino shield is also required.\n", + "The grove gesture sensor is attached to the I2C interface on the shield. \n", + "This grove sensor should also work with PMOD interfaces on the board." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.1 Import Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.arduino import Grove_Gesture\n", + "from pynq.lib.arduino import ARDUINO_GROVE_I2C\n", + "\n", + "sensor = Grove_Gesture(base.ARDUINO, ARDUINO_GROVE_I2C)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Set speed\n", + "There are currently 2 modes available for users to use: `far` and `near`.\n", + "The corresponding fps are 120 and 240, respectively.\n", + "For more information, please refer to [Grove gesture sensor](http://wiki.seeedstudio.com/Grove-Gesture_v1.0/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sensor.set_speed(240)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.3 Read gestures\n", + "The following code will read 10 gestures within 30 seconds. \n", + "Try to change your gesture in front of the sensor and check the results." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from time import sleep\n", + "\n", + "for i in range(10):\n", + " print(sensor.read_gesture())\n", + " sleep(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/breakout_sessions/1_1_sensors_and_board_to_board.ipynb b/breakout_sessions/1_1_sensors_and_board_to_board.ipynb index 26af88c..72e359b 100644 --- a/breakout_sessions/1_1_sensors_and_board_to_board.ipynb +++ b/breakout_sessions/1_1_sensors_and_board_to_board.ipynb @@ -60,7 +60,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/breakout_sessions/1_2_temp_sensor_AHT20.ipynb b/breakout_sessions/1_2_temp_sensor_AHT20.ipynb index eb43f2d..589726c 100644 --- a/breakout_sessions/1_2_temp_sensor_AHT20.ipynb +++ b/breakout_sessions/1_2_temp_sensor_AHT20.ipynb @@ -78,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -95,15 +95,21 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Humidity: 38.73 %\n", - "Temperature: 27.34 °C\n" + "ename": "RuntimeError", + "evalue": "Timeout when writing IIC.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpy_ht\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mGrove_AHT20\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbase\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mPMODB\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mPMOD_GROVE_G3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mhumidity\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpy_ht\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_humidity\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mtemperature\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpy_ht\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_temp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Humidity: '\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{0:.2f}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhumidity\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'%'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/grove/pmod_grove_aht20.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, pmod_id, gr_pins)\u001b[0m\n\u001b[1;32m 78\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpmod_id\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mscl_pin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msda_pin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0x38\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 80\u001b[0;31m \u001b[0mstatus\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_status\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 81\u001b[0m \u001b[0;32mif\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mnot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstatus\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 82\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Device not calibrated\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/grove/pmod_grove_aht20.py\u001b[0m in \u001b[0;36mget_status\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 109\u001b[0m \"\"\"\n\u001b[0;32m--> 110\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0x71\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 111\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreceive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pynq/lib/pmod/pmod_iic.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, iic_bytes)\u001b[0m\n\u001b[1;32m 196\u001b[0m \u001b[0mtimeout\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 197\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtimeout\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 198\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Timeout when writing IIC.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 199\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 200\u001b[0m \u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mI2C_DELAY\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mRuntimeError\u001b[0m: Timeout when writing IIC." ] } ], @@ -115,6 +121,13 @@ "print('Humidity: ', float(\"{0:.2f}\".format(humidity)), '%')\n", "print('Temperature: ', float(\"{0:.2f}\".format(temperature)), '°C')" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/breakout_sessions/sds_trace_data.dat b/breakout_sessions/sds_trace_data.dat new file mode 100644 index 0000000000000000000000000000000000000000..6b7d177c88cc176229e67aae6f7179773de92f8d GIT binary patch literal 32 icmZQ!U| max_temp:\n", + " ledbar.write_binary(up_to(10))\n", + "# if temperature is below our range of measurement\n", + "elif temp_c < min_temp:\n", + " ledbar.write_binary(up_to(0))\n", + "# otherwise is falls within our range\n", + "else:\n", + " temp_index = int(round(((temp_c - min_temp)/temp_range)*10))\n", + " ledbar.write_binary(up_to(temp_index))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb b/extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb new file mode 100644 index 0000000..32c40d1 --- /dev/null +++ b/extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb @@ -0,0 +1,268 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Displaying Sensor Data on the LED Bar\n", + "\n", + "A key concept in computers is taking an input from a sensor, processing that data in a meaningful way, and outputting that to the user in a format that is intuitive and easy to read. This concept can be found in almost every computing system. \n", + "\n", + "We are going to create this type of system with our sensors and LED bar. The end product will be a sort of \"digital thermometer\".\n", + "\n", + "### This notebook will walk you through using the TH02 sensor\n", + "\n", + "If your sensor looks like this, it is a TH02 and you should follow this notebook. If not, you should use the ATH20 sensor notebook [here](temp_ledbar_example_ATH20.ipynb).\n", + "\n", + "![TH02](https://files.seeedstudio.com/wiki/Grove-TemptureAndHumidity_Sensor-High-Accuracy_AndMini-v1.0/img/main.jpg)\n", + "\n", + "As usual, apply the base overlay to the board:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from pynq.overlays.base import BaseOverlay\n", + "base = BaseOverlay(\"base.bit\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Read Temperature Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.arduino import Grove_TH02\n", + "from pynq.lib.arduino import ARDUINO_GROVE_I2C" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plugging in your TH02 Sensor\n", + "\n", + "This sensor uses the Arduino shield to communicate with your PYNQ Board. Attach the Arduino shield to the top of your PYNQ Board. Then, plug in the TH02 Sensor to one of the ports labeled I2C on the Arduino shield.\n", + "\n", + "![grove_adaptor](https://cdn10.bigcommerce.com/s-7gavg/products/531/images/4194/PYNQ_Shield_-_Oblique_-_600__81639.1473444236.1280.1280.png?c=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize the Temperature Sensor\n", + "\n", + "We create an variable called \"th02\" that represents the sensor. From this object we can call functions that retrieve data from the sensor." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "th02 = Grove_TH02(base.ARDUINO,ARDUINO_GROVE_I2C)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read the Temperature and Humidity\n", + "Calling the function read() returns a tuple (two values separated by a comma). The first value is temperature and the second value is humidity." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The temperature is 28.21875 degrees celsius and the relative humidity is 40.0625 %\n" + ] + } + ], + "source": [ + "temp_c, humidity = th02.read()\n", + "print('The temperature is {} degrees celsius and the relative humidity is {} %'.format(temp_c, humidity))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Display the Data to the LED Bar\n", + "\n", + "## Connecting the LED Bar\n", + "\n", + "Plug the LED bar into the port labeled G1 on your PMOD to Grove Adaptor. Then plug the PMOD to Grove adaptor into the port labeled PMODB on your PYNQ-Z2 Board" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setup\n", + "\n", + "When the hardware is connected, run the following code to tell the PYNQ Board how you connected everything. If you plugged into a port besides G1, such as G2, then you will need to import `PMOD_GROVE_G2` instead." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.pmod import Grove_LEDbar\n", + "from pynq.lib.pmod import PMOD_GROVE_G1\n", + "\n", + "ledbar = Grove_LEDbar(base.PMODB, PMOD_GROVE_G1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reset the LED Bar\n", + "\n", + "The default state of the LED could be all sorts of things. Let's turn it fully of so we have somewhere to work from." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Turn the LED bar off\n", + "ledbar.reset()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Decide on Your Temperature Scale\n", + "\n", + "We want to make a visual thermometer that displays the temperature across a range that we care about. Perhaps this is simply comfortable room temperature (somewhere between 60 and 80 degrees fahrenheit), or it's the temperature of industrial equipment that cannot get above 150 degrees fahrenheit. What we will do next is establish this range and \"map\" it to the 10 bars on the LED indicator, with the red being the highest end of the range and the green being the lowest. For this example, lets the temperature we might find in a house in Colorado, 60 to 80 degrees fahrenheit, or about 15 to 25 degrees celsius (remember, our sensors read celsius, so make sure to convert when necessary)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "max_temp = 25\n", + "min_temp = 15\n", + "temp_range = max_temp - min_temp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We should consider \"edge cases\" where our temperature falls above or below our range. These are always good to check before we proceed. In this situation, we will illuminate all LEDs if the temperature is above the range, and 1 LED if it is below the range.\n", + "\n", + "Once we have ruled out edge cases, we can deal with the case where our temperature falls within our allotted range. Because there are 10 bars, we can only only display the temperature in tenths of our range. Knowing what our range is, we can calculate a number between 0 and 10 to represent where within the range we fall. Note that we multiply by 10 and round to the nearest whole number to make sure we pass an integer between 0 and 10 to the function up_to().\n", + "\n", + "Because our LED bar speaks in binary, We are going to use a function \"up_to\" which produces the binary value required to light up the bars \"up to\" a certain index on the led bar, given that index. This is covered more in depth in the [LED Bar notebook](../bootcamp_sessions/3_led_bar.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def up_to(index):\n", + " return ~(2**(10 - index) - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# if temperature is above our range of measurement\n", + "if temp_c > max_temp:\n", + " ledbar.write_binary(up_to(10))\n", + "# if temperature is below our range of measurement\n", + "elif temp_c < min_temp:\n", + " ledbar.write_binary(up_to(0))\n", + "# otherwise is falls within our range\n", + "else:\n", + " temp_index = int(round(((temp_c - min_temp)/temp_range)*10))\n", + " ledbar.write_binary(up_to(temp_index))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra/sds_trace_data.dat b/extra/sds_trace_data.dat new file mode 100644 index 0000000000000000000000000000000000000000..eeee3df35c7f0cfdb6957aa048df8d7c67a47e05 GIT binary patch literal 32 ecmZQ!00M92d%QsE7e507E0B)!k~uB| max_temp:\n", + " ledbar.write_binary(up_to(10))\n", + "# if temperature is below our range of measurement\n", + "elif temp_c < min_temp:\n", + " ledbar.write_binary(up_to(0))\n", + "# otherwise is falls within our range\n", + "else:\n", + " temp_index = int(round(((temp_c - min_temp)/temp_range)*10))\n", + " ledbar.write_binary(up_to(temp_index))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra/temp_ledbar_example_TH02.ipynb b/extra/temp_ledbar_example_TH02.ipynb new file mode 100644 index 0000000..32c40d1 --- /dev/null +++ b/extra/temp_ledbar_example_TH02.ipynb @@ -0,0 +1,268 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Displaying Sensor Data on the LED Bar\n", + "\n", + "A key concept in computers is taking an input from a sensor, processing that data in a meaningful way, and outputting that to the user in a format that is intuitive and easy to read. This concept can be found in almost every computing system. \n", + "\n", + "We are going to create this type of system with our sensors and LED bar. The end product will be a sort of \"digital thermometer\".\n", + "\n", + "### This notebook will walk you through using the TH02 sensor\n", + "\n", + "If your sensor looks like this, it is a TH02 and you should follow this notebook. If not, you should use the ATH20 sensor notebook [here](temp_ledbar_example_ATH20.ipynb).\n", + "\n", + "![TH02](https://files.seeedstudio.com/wiki/Grove-TemptureAndHumidity_Sensor-High-Accuracy_AndMini-v1.0/img/main.jpg)\n", + "\n", + "As usual, apply the base overlay to the board:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from pynq.overlays.base import BaseOverlay\n", + "base = BaseOverlay(\"base.bit\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Read Temperature Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.arduino import Grove_TH02\n", + "from pynq.lib.arduino import ARDUINO_GROVE_I2C" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plugging in your TH02 Sensor\n", + "\n", + "This sensor uses the Arduino shield to communicate with your PYNQ Board. Attach the Arduino shield to the top of your PYNQ Board. Then, plug in the TH02 Sensor to one of the ports labeled I2C on the Arduino shield.\n", + "\n", + "![grove_adaptor](https://cdn10.bigcommerce.com/s-7gavg/products/531/images/4194/PYNQ_Shield_-_Oblique_-_600__81639.1473444236.1280.1280.png?c=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initialize the Temperature Sensor\n", + "\n", + "We create an variable called \"th02\" that represents the sensor. From this object we can call functions that retrieve data from the sensor." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "th02 = Grove_TH02(base.ARDUINO,ARDUINO_GROVE_I2C)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read the Temperature and Humidity\n", + "Calling the function read() returns a tuple (two values separated by a comma). The first value is temperature and the second value is humidity." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The temperature is 28.21875 degrees celsius and the relative humidity is 40.0625 %\n" + ] + } + ], + "source": [ + "temp_c, humidity = th02.read()\n", + "print('The temperature is {} degrees celsius and the relative humidity is {} %'.format(temp_c, humidity))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Display the Data to the LED Bar\n", + "\n", + "## Connecting the LED Bar\n", + "\n", + "Plug the LED bar into the port labeled G1 on your PMOD to Grove Adaptor. Then plug the PMOD to Grove adaptor into the port labeled PMODB on your PYNQ-Z2 Board" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setup\n", + "\n", + "When the hardware is connected, run the following code to tell the PYNQ Board how you connected everything. If you plugged into a port besides G1, such as G2, then you will need to import `PMOD_GROVE_G2` instead." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq.lib.pmod import Grove_LEDbar\n", + "from pynq.lib.pmod import PMOD_GROVE_G1\n", + "\n", + "ledbar = Grove_LEDbar(base.PMODB, PMOD_GROVE_G1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reset the LED Bar\n", + "\n", + "The default state of the LED could be all sorts of things. Let's turn it fully of so we have somewhere to work from." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Turn the LED bar off\n", + "ledbar.reset()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Decide on Your Temperature Scale\n", + "\n", + "We want to make a visual thermometer that displays the temperature across a range that we care about. Perhaps this is simply comfortable room temperature (somewhere between 60 and 80 degrees fahrenheit), or it's the temperature of industrial equipment that cannot get above 150 degrees fahrenheit. What we will do next is establish this range and \"map\" it to the 10 bars on the LED indicator, with the red being the highest end of the range and the green being the lowest. For this example, lets the temperature we might find in a house in Colorado, 60 to 80 degrees fahrenheit, or about 15 to 25 degrees celsius (remember, our sensors read celsius, so make sure to convert when necessary)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "max_temp = 25\n", + "min_temp = 15\n", + "temp_range = max_temp - min_temp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We should consider \"edge cases\" where our temperature falls above or below our range. These are always good to check before we proceed. In this situation, we will illuminate all LEDs if the temperature is above the range, and 1 LED if it is below the range.\n", + "\n", + "Once we have ruled out edge cases, we can deal with the case where our temperature falls within our allotted range. Because there are 10 bars, we can only only display the temperature in tenths of our range. Knowing what our range is, we can calculate a number between 0 and 10 to represent where within the range we fall. Note that we multiply by 10 and round to the nearest whole number to make sure we pass an integer between 0 and 10 to the function up_to().\n", + "\n", + "Because our LED bar speaks in binary, We are going to use a function \"up_to\" which produces the binary value required to light up the bars \"up to\" a certain index on the led bar, given that index. This is covered more in depth in the [LED Bar notebook](../bootcamp_sessions/3_led_bar.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def up_to(index):\n", + " return ~(2**(10 - index) - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# if temperature is above our range of measurement\n", + "if temp_c > max_temp:\n", + " ledbar.write_binary(up_to(10))\n", + "# if temperature is below our range of measurement\n", + "elif temp_c < min_temp:\n", + " ledbar.write_binary(up_to(0))\n", + "# otherwise is falls within our range\n", + "else:\n", + " temp_index = int(round(((temp_c - min_temp)/temp_range)*10))\n", + " ledbar.write_binary(up_to(temp_index))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 3b99696eb1a625c53a4ee0ccc12506472e84912c Mon Sep 17 00:00:00 2001 From: Dustin Ramsay Date: Wed, 29 Jul 2020 15:50:30 -0600 Subject: [PATCH 2/7] Delete 3_led_bar-checkpoint.ipynb --- .../3_led_bar-checkpoint.ipynb | 526 ------------------ 1 file changed, 526 deletions(-) delete mode 100644 bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb diff --git a/bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb b/bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb deleted file mode 100644 index eb5ac6c..0000000 --- a/bootcamp_sessions/.ipynb_checkpoints/3_led_bar-checkpoint.ipynb +++ /dev/null @@ -1,526 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.overlays.base import BaseOverlay\n", - "base = BaseOverlay(\"base.bit\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2. Tell PYNQ About the LED Bar\n", - "\n", - "The LED bar will be connected to connector G1 on the PYNQ Grove adapter. The PYNQ Grove adapter will be connected to PMODA on the PYNQ-Z2 board." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.lib.pmod import Grove_LEDbar\n", - "from pynq.lib.pmod import PMOD_GROVE_G1\n", - "\n", - "ledbar = Grove_LEDbar(base.PMODA, PMOD_GROVE_G1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3. Reset the LED Bar\n", - "\n", - "The default state of the LED could be all sorts of things. Let's turn it fully of so we have somewhere to work from." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Turn the LED bar off\n", - "ledbar.reset()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The LED bar should be blank now.\n", - "\n", - "### 4. Lighting Up the LED Bar\n", - "\n", - "The LED Bar supports a lot of different display configurations. Let's start with something simple, turning on all the bars." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "ledbar.write_binary(0b1111111111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Your LED bar should be all lit up now. How did writing `0b1111111111` to the ledbar turn it on?\n", - "\n", - "The LED bar speaks binary. Binary is a alternate number base used in computing. We could get into a much longer discussion about binary, but for now let's just se how the LED bar responds to different inputs.\n", - "\n", - "Run the cell below and observe the output!" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "from time import sleep\n", - "ledbar.write_binary(0b0000000000)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0000000001)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0000000011)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0000000111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0000001111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0000011111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0000111111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0001111111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0011111111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b0111111111)\n", - "sleep(0.25)\n", - "ledbar.write_binary(0b1111111111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Any guesses on how the LED bar interprets the binary numbers?\n", - "\n", - "### 5. Light up each element of the LED Bar\n", - "\n", - "Last time we blinked the LED over and over. Let's do something similar with the LED bar! Let's light up each element in sequence." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Loop 5 times\n", - "for i in range(5):\n", - " ledbar.write_binary(0b0000000001)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0000000010)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0000000100)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0000001000)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0000010000)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0000100000)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0001000000)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0010000000)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b0100000000)\n", - " sleep(0.25)\n", - " ledbar.write_binary(0b1000000000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Writing out the entire binary number each time can prove annoying. Let's write a quick python function to make this easier.\n", - "\n", - "If we want to light up a specific element on the LED bar we use the following algorithm to convert our index to a binary number.\n", - "\n", - "$binary = 2^{index}$\n", - "\n", - "We can implement that in a python function as follows. Functions are a powerful tool that most programming languages provide. Functions allow us to write a single piece of code and use it again from anywhere we want. Many of the operations we have been doing (`read()`, `write_binary()`, `sleep()`) are all functions. \n", - "\n", - "If you have never worked with Python functions before there is a short tutorial you can run through [here](https://www.w3schools.com/python/python_functions.asp).\n", - "\n", - "We can create functions with the `def` keyword.\n", - "\n", - "We are going to name our function `element` and have it take one argument called `index`.\n", - "\n", - "Finally, the function is going to return the algorithm we defined before." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "def element(index):\n", - " # In python the ** operator is exponentiation\n", - " return 2**index" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's use it to light up the middle of the LED bar. Try replacing the 5 with different numbers.\n", - "\n", - "Now let's do our scrolling LED bar from before. This time, notice how much more concisely we can write it." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(5):\n", - " for j in range(10):\n", - " ledbar.write_binary(element(j))\n", - " sleep(0.25)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 6. Light up part of the LED bar\n", - "\n", - "Let's try to light up part of the LED Bar. A display like this would be good for a battery or volume meter. A simple way to do this is to hard code the binary value we want." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Light up half the LED bar\n", - "ledbar.write_binary(0b0000011111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This works but, again, this is annoying to enter. Let's use our function technique from before.\n", - "\n", - "The algorithm for calculating the binary number required to light up part of the LED bar is:\n", - "\n", - "$binary = 2^{index+1} - 1$\n", - "\n", - "Now let's implement this in a function." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "def up_to(index):\n", - " return 2**(index+1) - 1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's test it out!" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "ledbar.write_binary(up_to(5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have a easy way to do this, let's try our loop method from before." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(5):\n", - " for j in range(10):\n", - " ledbar.write_binary(up_to(j))\n", - " sleep(0.1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is great, but only works if we want to light up the LED bar from one end. What happens if we want to do the\n", - "other direction?\n", - "\n", - "Luckily, Python has an inverse operator we can use. Check out the following cell!" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "ledbar.write_binary(~up_to(5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By putting the `~` character in front, we can covert a number like `0b0000111111` into `0b1111000000`.\n", - "\n", - "Question: What would happen if we applied the `~` operator to the `element` function we wrote before?\n", - "\n", - "Talk about this in your groups and when you have a guess give the next cell a try!" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "ledbar.write_binary(~element(5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Cool?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Controlling the LED Bar with Other Peripherals\n", - "\n", - "Similar to before, we are going to combine the on board buttons with the external LED Bar.\n", - "\n", - "### 1. Setup the Buttons\n", - "\n", - "First let's setup the on-board switches so we can read their state. " - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "buttons = base.buttons" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2. Check the Status of the Buttons\n", - "\n", - "Next, let's check is the status of the buttons. You can run this cell multiple times to see how the output changes when you hold the buttons." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Button 0 is off\n", - "Button 1 is off\n", - "Button 2 is off\n", - "Button 3 is on\n" - ] - } - ], - "source": [ - "print(f'Button 0 {\"is on\" if buttons[0].read() else \"is off\"}')\n", - "print(f'Button 1 {\"is on\" if buttons[1].read() else \"is off\"}')\n", - "print(f'Button 2 {\"is on\" if buttons[2].read() else \"is off\"}')\n", - "print(f'Button 3 {\"is on\" if buttons[3].read() else \"is off\"}')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3. Control the LED Bar with the Buttons\n", - "\n", - "Now, let's build a program to cycle the LED bar every time button 0 is pressed!\n", - "\n", - "First, we need to to be able to wait for a button to be pressed. Run the cell below and then press button 0." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Button 0 was pressed\n" - ] - } - ], - "source": [ - "while buttons[0].read() == 0:\n", - " pass\n", - "print('Button 0 was pressed')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have that down, let's bring back some of the LED Bar scrolling code from before." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for i in range(10):\n", - " ledbar.write_binary(element(i))\n", - " sleep(0.25)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we need to combine the two previous cells to create our program. I'll leave you an empty cell below to try it yourself. If you get stuck, run the next cell for a hint!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(10):\n", - " ledbar.write_binary(element(i))\n", - " while buttons[0].read() == 0:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Woah, that probably didn't do what you expected. Why did the element jump so much?\n", - "\n", - "This in cause by the python code running too quickly. Before you are able to let go of the button, the for loop has already iterated 5 or more times. We can fix this by adding a sleep statement to add some delay to account for our slow reflexes!\n", - "\n", - "Run the next cell and try pressing the button a few times. Try holding the button too!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(10):\n", - " ledbar.write_binary(element(i))\n", - " while buttons[0].read() == 0:\n", - " pass\n", - " sleep(0.25)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Conclusion\n", - "\n", - "You're done! You now hopefully have some understanding of how the LED bar works and how we can interact with it. Here are some more advanced activities you can give a try.\n", - "\n", - "1. Flash alternating sets of lights (try using a function to make this easier).\n", - "2. Count how many times a button is pressed and display it on the LED bar.\n", - "3. Display which built in buttons and switches are being pressed (if button 0 is pressed -> led bar element 0 is lit, etc)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 7b4f6dc59a2b1173d904a1bd78b7e99a64f98c13 Mon Sep 17 00:00:00 2001 From: Dustin Ramsay Date: Wed, 29 Jul 2020 15:50:46 -0600 Subject: [PATCH 3/7] Delete 1_1_sensors_and_board_to_board-checkpoint.ipynb --- ...ensors_and_board_to_board-checkpoint.ipynb | 454 ------------------ 1 file changed, 454 deletions(-) delete mode 100644 breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb diff --git a/breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb b/breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb deleted file mode 100644 index 72e359b..0000000 --- a/breakout_sessions/.ipynb_checkpoints/1_1_sensors_and_board_to_board-checkpoint.ipynb +++ /dev/null @@ -1,454 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Sensors and Board to Board Communication\n", - "\n", - "This session will cover reading data from the Grove TH02 Temperature and Humidity Sensor as well as transmitting data from one board to another over the internet." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 1: Setup" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.1 Initialize Overlay\n", - "Our PYNQ Board has a Field Programmable Gate Array (FPGA) on it that must be programmed before we begin using the board. We apply designs called overlays that we can design however we want. For the first part of this tutorial, we are going to use the pre-built base overlay." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.overlays.base import BaseOverlay\n", - "base = BaseOverlay(\"base.bit\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Import Temperature Sensor Libraries\n", - "Here we tell the board what libraries we want to use in our project." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.lib.arduino import Grove_TH02\n", - "from pynq.lib.arduino import ARDUINO_GROVE_I2C" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 2: Reading Temperature and Humidity" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Plugging in your TH02 Sensor\n", - "\n", - "Plug your PMOD to Grove adaptor (shown in picture below) into one of your PMOD connectors on your PYNQ board. Then plug you TH02 humidity sensor into the one of the four white Grove adaptor ports\n", - "\n", - "![grove_adaptor](https://cdn10.bigcommerce.com/s-7gavg/products/531/images/4194/PYNQ_Shield_-_Oblique_-_600__81639.1473444236.1280.1280.png?c=2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Initialize the Temperature Sensor\n", - "\n", - "We create an variable called \"th02\" that represents the sensor. From this object we can call functions that retrieve data from the sensor." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "th02 = Grove_TH02(base.ARDUINO,ARDUINO_GROVE_I2C)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Read the Temperature and Humidity\n", - "Calling the function read() returns a tuple (two values separated by a comma). The first value is temperature and the second value is humidity." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "temp_c, humidity = th02.read()\n", - "print('The temperature is {} degrees celsius and the relative humidity is {} %'.format(temp_c, humidity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.4 Convert to Fahrenheit\n", - "\n", - "Converting to Fahrenheit is done by the following equation: \n", - "\n", - "fahrenheit = celsius * (9/5) + 32" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "temp_f = temp_c * (9/5) + 32\n", - "print(f'The temperature is {temp_f} F')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.5 Averaging the Temperature" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Both computers and the world aren't always perfect. This means that there can be some variation in values that we see. Averaging is a technique that can help up try to hone in on the \"correct\" answer that we are looking for. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First, let's read a number of values from the temperature sensor." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# create temperatures as an empty array\n", - "temps = []\n", - "# read 5 temperature values and store then in the \"temps\" array\n", - "for i in range(5):\n", - " # read temp in C\n", - " temp_c, _ = th02.read()\n", - " # convert to F\n", - " temp_f = temp_c * (9/5) + 32\n", - " # append temp_f to temps\n", - " temps.append(temp_f)\n", - "print(temps)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have all 5 temperature values stored in an array, let's average them! To average the values, we want to sum them up and then divide the total number of values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "average_sum = 0\n", - "# sum up all the values\n", - "for temp in temps:\n", - " average_sum = average_sum + temp\n", - "print(f\"average_sum: {average_sum}\")\n", - "average = average_sum / len(temps)\n", - "print(f\"average: {average}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 3: Board to Board Communication\n", - "\n", - "In many situations, sensors will need to be a distance away from where the data is needed. For instance, you may want to know the temperature at different locations around a city and be able to monitor this from one central location. To do this, we can send data over the internet. You can also send many types of data beyond this sensor such as text." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!pip3 install getmac\n", - "!pip3 install ./pynq-p2p" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import pynqp2p" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.1 Register with the central server\n", - "In order to ensure not just anyone can access our data, we use a secret passcode to verify our identity and register with the server that will store our data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ip_address = '[IP address of the server goes here]'\n", - "key = '[secret passcode goes here]'\n", - "pynqp2p.register(ip_address, key)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.2 Make sure we are able to communicate with the server\n", - "The function ping() simply sends a message to our server and the server sends a message back saying it heard us." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pynqp2p.ping()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.3 Get a unique ID from your Board\n", - "Your board has a unique ID number called a MAC address. The function get_id() returns a unique number based on this MAC address that you can share with people you want to be able to send you messages. Make sure that the way you share this is secure (such as email) so that you don't have people spamming you with unwanted information." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "myid = pynqp2p.get_id()\n", - "print(f\"Your ID is {myid}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.4 Send a message to a board with a particular ID\n", - "The function send() sends a message to the board with the particular ID number you pass it." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "recipient_id = 'put your teammates ID here'\n", - "pynqp2p.send(recipient_id, \"Hello!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.5 Receive Messages\n", - "The function receive() asks the server to give you the most recent message sent to you. Afterwards, it deletes the message (which means you can only receive it once). The function receive_all() retrieves all the messages in the server at once and returns them as a list." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pynqp2p.receive()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.6 Sending Multiple Messages" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Sometimes it is helpful to send multiple messages in a row to another PYNQ board. A really simple way to do this is to run the send(id) command multiple times;" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pynqp2p.send(myid, \"Hello 0\")\n", - "pynqp2p.send(myid, \"Hello 1\")\n", - "pynqp2p.send(myid, \"Hello 2\")\n", - "pynqp2p.send(myid, \"Hello 3\")\n", - "pynqp2p.send(myid, \"Hello 4\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now in order to recieve these messages, we'll have to call the recieve() function a few times." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(pynqp2p.receive())\n", - "print(pynqp2p.receive())\n", - "print(pynqp2p.receive())\n", - "print(pynqp2p.receive())\n", - "print(pynqp2p.receive())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This seems tedious, there must be a better way! If you remember earlier, we used a for loop to read multiple temperatures from the temperature sensor and put them in an array. We can use the same technique here." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(5):\n", - " pynqp2p.send(myid, \"Hello \" + str(i))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we will use another for loop to retrieve all the messages we just sent. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(5):\n", - " print(pynqp2p.receive())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you can see, this is a lot less tedious and required a lot less code to achieve the same goal. The only problem here is that we can only access the retrieved messages one at a time. pynqp2p containes a really useful function called recieve_all() that helps us here." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# first, let's send ourselves 5 messages\n", - "for i in range(5):\n", - " pynqp2p.send(myid, \"Hello \" + str(i))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# now, let's see what the recieve_all() functions does for us\n", - "print(pynqp2p.receive_all())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now you've learned the basics of pynqp2p! Let's try something new. Can you figure out how to send some of the temperature data from earlier? Can you send your Celcius measurement to someone else to be converted into Fahrenheit? Can you send your temperature measurement to someone else and have them respond with weather it's larger or smaller?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The possibilites are endless!" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From d2199d1b6cc5624e39b8af026177811d3e13436e Mon Sep 17 00:00:00 2001 From: Dustin Ramsay Date: Wed, 29 Jul 2020 15:51:42 -0600 Subject: [PATCH 4/7] Delete 1_2_temp_sensor_AHT20-checkpoint.ipynb --- .../1_2_temp_sensor_AHT20-checkpoint.ipynb | 141 ------------------ 1 file changed, 141 deletions(-) delete mode 100644 breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb diff --git a/breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb b/breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb deleted file mode 100644 index eb43f2d..0000000 --- a/breakout_sessions/.ipynb_checkpoints/1_2_temp_sensor_AHT20-checkpoint.ipynb +++ /dev/null @@ -1,141 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Grove AHT20 (Humidity & Temperature Sensor)\n", - "\n", - "This notebook shows how to install the Python driver for the AHT20 temperature sensor and use it to make a humidity/temperature measurement.\n", - "\n", - "### 1. Initialize Overlay" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "\n", - "require(['notebook/js/codecell'], function(codecell) {\n", - " codecell.CodeCell.options_default.highlight_modes[\n", - " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", - " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", - " Jupyter.notebook.get_cells().map(function(cell){\n", - " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", - " });\n", - "});\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from pynq.overlays.base import BaseOverlay\n", - "base = BaseOverlay(\"base.bit\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2. Install Python Driver" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting git+https://github.com/LewisMcL/pynq_drivers\n", - " Cloning https://github.com/LewisMcL/pynq_drivers to /tmp/pip-ap5mlg2i-build\n", - "Installing collected packages: pmod-grove-aht20\n", - " Running setup.py install for pmod-grove-aht20 ... \u001b[?25ldone\n", - "\u001b[?25hSuccessfully installed pmod-grove-aht20-1.0\n" - ] - } - ], - "source": [ - "!pip3 install git+https://github.com/LewisMcL/pynq_drivers --no-deps" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3. Import Libraries\n", - "\n", - "Make sure your PMOD to Grove adapter is connected to the PMODB port. We are importing PMOD_GROVE_G3, because the AHT20 sensor is connected to the 3rd Grove adaptor port. If you have it plugged into G4, you will have to do `from pynq.lib.pmod import PMOD_GROVE_G4` instead. " - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "from grove import Grove_AHT20\n", - "from pynq.lib.pmod import PMOD_GROVE_G3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4. Receiving Measurements" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Humidity: 38.73 %\n", - "Temperature: 27.34 °C\n" - ] - } - ], - "source": [ - "py_ht = Grove_AHT20(base.PMODB, PMOD_GROVE_G3)\n", - "\n", - "humidity = py_ht.get_humidity()\n", - "temperature = py_ht.get_temp()\n", - "print('Humidity: ', float(\"{0:.2f}\".format(humidity)), '%')\n", - "print('Temperature: ', float(\"{0:.2f}\".format(temperature)), '°C')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 410a5313c330224fd07366420728fe0d1a76fb4b Mon Sep 17 00:00:00 2001 From: Dustin Ramsay Date: Wed, 29 Jul 2020 15:51:55 -0600 Subject: [PATCH 5/7] Delete 2_1_computer_vision-checkpoint.ipynb --- .../2_1_computer_vision-checkpoint.ipynb | 550 ------------------ 1 file changed, 550 deletions(-) delete mode 100644 breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb diff --git a/breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb b/breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb deleted file mode 100644 index bbfc141..0000000 --- a/breakout_sessions/.ipynb_checkpoints/2_1_computer_vision-checkpoint.ipynb +++ /dev/null @@ -1,550 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Computer Vision\n", - "\n", - "### In this tutorial, we are going to learn how to take a photo with a webcam attached to our Pynq Board, display this image in our Jupyter Notebook, and then detect faces in the photo. For extra credit, we will use a neural net to predict the objects in a photo." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 1: Setup" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.1 Load Overlay\n", - "Our PYNQ Board has a Field Programmable Gate Array (FPGA) on it that must be programmed before we begin using the board. We apply designs called overlays that we can design however we want. For the first part of this tutorial, we are going to use the pre-built base overlay." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.overlays.base import BaseOverlay\n", - "from pynq.lib.video import *\n", - "base = BaseOverlay(\"base.bit\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Import Libraries\n", - "Here we tell the board what libraries we want to use in our project." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import cv2\n", - "from matplotlib import pyplot as plt\n", - "import numpy as np\n", - "from IPython import display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.3 Initialize Webcam\n", - "After plugging in our USB webcam, we must tell the board what size images it is going to be recording and sending to the board. We also need to create a python object that will store the images we read from the webcam." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#create object\n", - "videoIn = cv2.VideoCapture(0)\n", - "\n", - "#set input width and height\n", - "input_frame_width = 640\n", - "input_frame_height = 480\n", - "videoIn.set(cv2.CAP_PROP_FRAME_WIDTH, input_frame_width);\n", - "videoIn.set(cv2.CAP_PROP_FRAME_HEIGHT, input_frame_height);\n", - "\n", - "#check to ensure the webcam is open\n", - "if(videoIn.isOpened()):\n", - " print('camera is ready')\n", - "else:\n", - " print('error starting camera, run this cell again')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 2: Face Detection" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Take Photo\n", - "Once we have our board setup and webcam working, it is time to use it! using videoIn.read(), we can read what the webcam is looking at at any given moment. This function has two return values. The first tells us if we successfully read an image or not. True means we did, false means there was a problem. The second return value is a frame object, which is the actual image we read." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#read frame\n", - "success, frame = videoIn.read()\n", - "#if there was an error, tell us!\n", - "if (success != True):\n", - " print(\"Video Read Error\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Display Photo\n", - "Using matplotlib imported earlier, we can display our image right in our Jupyter notebook" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#display input\n", - "plt.imshow(frame[:,:,[2,1,0]])\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Look for Faces\n", - "Now that we can take a photo, let's have our board look for faces in our photo. We are going to use something called a Haar Cascade Classifier. This is a model that has been training to understand what a face looks like. It has already been built and trained, so we simply need to load it and pass our image to it. Below is what the model is looking for when it tries to find faces, can you trick it?\n", - "![HaarClassifier](data/haar.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#create our own instance of the classifier\n", - "face_cascade = cv2.CascadeClassifier(\n", - " '/home/xilinx/jupyter_notebooks/base/video/data/'\n", - " 'haarcascade_frontalface_default.xml')\n", - "\n", - "#our classifier prefers to work on a gray image\n", - "gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n", - "faces = face_cascade.detectMultiScale(gray, 1.3, 5)\n", - "\n", - "#draw a rectangle around any faces we find\n", - "for (x,y,w,h) in faces:\n", - " cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)\n", - " roi_gray = gray[y:y+h, x:x+w]\n", - " roi_color = frame[y:y+h, x:x+w]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.4 Show our image again with the face detection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "plt.imshow(frame[:,:,[2,1,0]])\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.5 Look for Eyes\n", - "The board also have another classifier for detecting features that look like eyes. We will do the same thing we did with the face classifier for the eye classifier." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#create our own instance of the classifier\n", - "eye_cascade = cv2.CascadeClassifier(\n", - " '/home/xilinx/jupyter_notebooks/base/video/data/'\n", - " 'haarcascade_eye.xml')\n", - "\n", - "eyes = eye_cascade.detectMultiScale(roi_gray)\n", - "for (ex,ey,ew,eh) in eyes:\n", - " cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.6 Show image with eye and face detection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "plt.imshow(frame[:,:,[2,1,0]])\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.7 Counting Faces\n", - "The faces our program found are contained in an array. This stores the location of the faces within the image. If we want to count the faces found in the image, we can simply print the length of this array." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(len(faces))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 3: Guess the object with a neural net" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.1 Import a Neural Network" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "! sudo pip3 install git+https://github.com/Xilinx/QNN-MO-PYNQ.git" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import qnn\n", - "from qnn import Dorefanet\n", - "from qnn import utils\n", - "import os, pickle, random\n", - "from PIL import Image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.2 Take Another Image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "success, frame2 = videoIn.read()\n", - "\n", - "#if there was an error, tell us!\n", - "if (success != True):\n", - " print(\"Video Read Error\")\n", - " \n", - "#display the image\n", - "plt.imshow(frame2[:,:,[2,1,0]])\n", - "plt.show() \n", - "\n", - "#save the image just taken to memory\n", - "cv2.imwrite(\"photo.jpg\", frame2)\n", - "\n", - "videoIn.release()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.3 Set Up the Object Classifier\n", - "This classifier has been trained to recognize a wide variety of objects. It requires us to reconfigure the FPGA on the board (replacing the base overlay with a custom overlay that will help accelerate the classification). This is automatically done with the init_accelerator() function" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "classifier = Dorefanet()\n", - "classifier.init_accelerator()\n", - "net = classifier.load_network(json_layer=\"/usr/local/lib/python3.6/dist-packages/qnn/params/dorefanet-layers.json\")\n", - "\n", - "conv0_weights = np.load('/usr/local/lib/python3.6/dist-packages/qnn/params/dorefanet-conv0.npy', encoding=\"latin1\").item()\n", - "fc_weights = np.load('/usr/local/lib/python3.6/dist-packages/qnn/params/dorefanet-fc-normalized.npy', encoding='latin1').item()\n", - "\n", - "with open(\"/home/xilinx/jupyter_notebooks/qnn/imagenet-classes.pkl\", 'rb') as f:\n", - " classes = pickle.load(f)\n", - " names = dict((k, classes[k][1].split(',')[0]) for k in classes.keys())\n", - " synsets = dict((classes[k][0], classes[k][1].split(',')[0]) for k in classes.keys())\n", - " \n", - "conv0_W = conv0_weights['conv0/W']\n", - "conv0_T = conv0_weights['conv0/T']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.4 Run the Image through the Classifier\n", - "Once our classifier is set up, we input our image to the neural net." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "img, img_class = classifier.load_image(\"photo.jpg\")\n", - "\n", - "# 1st convolutional layer execution, having as input the image and the trained parameters (weights)\n", - "conv0 = utils.conv_layer(img, conv0_W, stride=4)\n", - "# The result in then quantized to 2 bits representation for the subsequent HW offload\n", - "conv0 = utils.threshold(conv0, conv0_T)\n", - "\n", - "\n", - "# Compute offloaded convolutional layers\n", - "out_dim = net['merge4']['output_dim']\n", - "out_ch = net['merge4']['output_channels']\n", - "\n", - "conv_output = classifier.get_accel_buffer(out_ch, out_dim);\n", - "conv_input = classifier.prepare_buffer(conv0)\n", - "\n", - "classifier.inference(conv_input, conv_output)\n", - "\n", - "conv_output = classifier.postprocess_buffer(conv_output)\n", - "\n", - "\n", - "# Normalize results\n", - "fc_input = conv_output / np.max(conv_output)\n", - "\n", - "# FC Layer 0\n", - "fc0_W = fc_weights['fc0/Wn']\n", - "fc0_b = fc_weights['fc0/bn']\n", - "\n", - "fc0_out = utils.fully_connected(fc_input, fc0_W, fc0_b)\n", - "fc0_out = utils.qrelu(fc0_out)\n", - "fc0_out = utils.quantize(fc0_out, 2)\n", - "\n", - "# FC Layer 1\n", - "fc1_W = fc_weights['fc1/Wn']\n", - "fc1_b = fc_weights['fc1/bn']\n", - "\n", - "fc1_out = utils.fully_connected(fc0_out, fc1_W, fc1_b)\n", - "fc1_out = utils.qrelu(fc1_out)\n", - "\n", - "# FC Layer 2\n", - "fct_W = fc_weights['fct/W']\n", - "fct_b = np.zeros((fct_W.shape[1], ))\n", - "\n", - "fct_out = utils.fully_connected(fc1_out, fct_W, fct_b)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.5 Use Softmax to Estimate the Probability of the Top 5 Most Likely Classes" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Softmax\n", - "out = utils.softmax(fct_out)\n", - "\n", - "# Top-5 results\n", - "topn = utils.get_topn_indexes(out, 5) \n", - "for k in topn: print(\"class:{0:>20}\\tprobability:{1:>8.2%}\".format(names[k].lower(), out[k]))\n", - "\n", - "#display results\n", - "x_pos = np.arange(len(topn))\n", - "plt.barh(x_pos, out[topn], height=0.4, color='g', zorder=3)\n", - "plt.yticks(x_pos, [names[k] for k in topn])\n", - "plt.gca().invert_yaxis()\n", - "plt.xlim([0,1])\n", - "plt.grid(zorder=0)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 4: Gesture Sensor\n", - "\n", - "Now we will explore the Grove Gesture Sensor and use it to take pictures with our webcam.\n", - "\n", - "[Grove gesture sensor](http://wiki.seeedstudio.com/Grove-Gesture_v1.0/) on the board.\n", - "The gesture sensor can detect 10 gestures as follows:\n", - "\n", - "| Value the Sensor Returns | Gesture |\n", - "|--------------------------|--------------------|\n", - "| 0 | No detection |\n", - "| 1 | forward |\n", - "| 2 | backward |\n", - "| 3 | right |\n", - "| 4 | left |\n", - "| 5 | up |\n", - "| 6 | down |\n", - "| 7 | clockwise |\n", - "| 8 | counter-clockwise |\n", - "| 9 | wave |\n", - "\n", - "\n", - "For this notebook, a PYNQ Arduino shield is also required.\n", - "The grove gesture sensor is attached to the I2C interface on the shield. \n", - "This grove sensor should also work with PMOD interfaces on the board." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.1 Import Libraries" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.lib.arduino import Grove_Gesture\n", - "from pynq.lib.arduino import ARDUINO_GROVE_I2C\n", - "\n", - "sensor = Grove_Gesture(base.ARDUINO, ARDUINO_GROVE_I2C)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Set speed\n", - "There are currently 2 modes available for users to use: `far` and `near`.\n", - "The corresponding fps are 120 and 240, respectively.\n", - "For more information, please refer to [Grove gesture sensor](http://wiki.seeedstudio.com/Grove-Gesture_v1.0/)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sensor.set_speed(240)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.3 Read gestures\n", - "The following code will read 10 gestures within 30 seconds. \n", - "Try to change your gesture in front of the sensor and check the results." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from time import sleep\n", - "\n", - "for i in range(10):\n", - " print(sensor.read_gesture())\n", - " sleep(3)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 4eff419b143f501c7ca83b0ff0a905f897c33048 Mon Sep 17 00:00:00 2001 From: Dustin Ramsay Date: Wed, 29 Jul 2020 15:53:51 -0600 Subject: [PATCH 6/7] Delete temp_ledbar_example_ATH20-checkpoint.ipynb --- ...temp_ledbar_example_ATH20-checkpoint.ipynb | 277 ------------------ 1 file changed, 277 deletions(-) delete mode 100644 extra/.ipynb_checkpoints/temp_ledbar_example_ATH20-checkpoint.ipynb diff --git a/extra/.ipynb_checkpoints/temp_ledbar_example_ATH20-checkpoint.ipynb b/extra/.ipynb_checkpoints/temp_ledbar_example_ATH20-checkpoint.ipynb deleted file mode 100644 index df5bbca..0000000 --- a/extra/.ipynb_checkpoints/temp_ledbar_example_ATH20-checkpoint.ipynb +++ /dev/null @@ -1,277 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Displaying Sensor Data on the LED Bar\n", - "\n", - "A key concept in computers is taking an input from a sensor, processing that data in a meaningful way, and outputting that to the user in a format that is intuitive and easy to read. This concept can be found in almost every computing system. \n", - "\n", - "We are going to create this type of system with our sensor and LED bar. The end product will be a sort of \"digital thermometer\".\n", - "\n", - "### This notebook will walk you through using both the ATH20 sensor\n", - "\n", - "\n", - "As usual, apply the base overlay to the board:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "\n", - "require(['notebook/js/codecell'], function(codecell) {\n", - " codecell.CodeCell.options_default.highlight_modes[\n", - " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", - " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", - " Jupyter.notebook.get_cells().map(function(cell){\n", - " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", - " });\n", - "});\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from pynq.overlays.base import BaseOverlay\n", - "base = BaseOverlay(\"base.bit\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 1. Read Temperature Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## ATH02 Sensor\n", - "\n", - "If your sensor looks like this, it is an ATH20. If not, you should use the TH02 notebook [here](temp_ledbar_example_TH02.ipynb).\n", - "\n", - "![ATH20](https://static-cdn.seeedstudio.site/media/catalog/product/cache/b2267b506d4e4594666ef83a79896a9a/1/0/101990644_4_.png)\n", - "\n", - "### Install Driver\n", - "\n", - "First, install the driver that will allow your board to communicate with this sensor (you may already have downloaded it, but run this cell just in case)." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting git+https://github.com/LewisMcL/pynq_drivers\n", - " Cloning https://github.com/LewisMcL/pynq_drivers to /tmp/pip-wqhg2o6g-build\n", - " Requirement already satisfied (use --upgrade to upgrade): pmod-grove-aht20==1.0 from git+https://github.com/LewisMcL/pynq_drivers in /usr/local/lib/python3.6/dist-packages\n" - ] - } - ], - "source": [ - "!pip3 install git+https://github.com/LewisMcL/pynq_drivers --no-deps" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plug in your ATH20 Sensor\n", - "\n", - "Connect you ATH20 Sensor to the port labeled G3 on your PMOD to Grove Adaptor (pictured below). Plug the adaptor into the port labeled PMODB on your PYNQ Board.\n", - "\n", - "![pmod_adaptor](https://ce8dc832c.cloudimg.io/fit/640x480/n@a5b92b913168a98c8e5229bb3b0b33a39779b8b3/_cdn_/8F/91/A0/00/0/662008_1.jpg?mark_url=_tme-wrk_%2Ftme_new.png&mark_pos=center&mark_size=100pp)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import Libraries\n", - "\n", - "Make sure your PMOD to Grove adapter is connected to the PMODB port. We are importing PMOD_GROVE_G3, because the AHT20 sensor is connected to the 3rd Grove adaptor port. If you have it plugged into G4, you will have to do `from pynq.lib.pmod import PMOD_GROVE_G4` instead. " - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "from grove import Grove_AHT20\n", - "from pynq.lib.pmod import PMOD_GROVE_G3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4. Receiving Measurements\n", - "We instantiate the sensor using the Grove_ATH20 constructor. This is very similar to a function, but it returns an object that represents our sensor that we can then use to call functions like get_temp()." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Humidity: 33.32 %\n", - "Temperature: 27.5 °C\n" - ] - } - ], - "source": [ - "py_ht = Grove_AHT20(base.PMODB, PMOD_GROVE_G3)\n", - "\n", - "humidity = py_ht.get_humidity()\n", - "temp_c = py_ht.get_temp()\n", - "print('Humidity: ', float(\"{0:.2f}\".format(humidity)), '%')\n", - "print('Temperature: ', float(\"{0:.2f}\".format(temp_c)), '°C')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 2. Display on LED bar" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Setup:\n", - "\n", - "Attached the arduino shield to the top of your board. Connect the LED bar to the G7 port on the Arduino shield. Connect the ATH20 to port G3 on the PMOD to Grove adaptor. Run the following code to initiate connection with the LED bar:" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.lib.arduino import Grove_LEDbar\n", - "from pynq.lib.arduino import ARDUINO_GROVE_G7\n", - "\n", - "ledbar = Grove_LEDbar(base.ARDUINO, ARDUINO_GROVE_G7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Reset the LED Bar\n", - "\n", - "The default state of the LED could be all sorts of things. Let's turn it fully of so we have somewhere to work from." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [], - "source": [ - "# Turn the LED bar off\n", - "ledbar.reset()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Decide on Your Temperature Scale\n", - "\n", - "We want to make a visual thermometer that displays the temperature across a range that we care about. Perhaps this is simply comfortable room temperature (somewhere between 60 and 80 degrees fahrenheit), or it's the temperature of industrial equipment that cannot get above 150 degrees fahrenheit. What we will do next is establish this range and \"map\" it to the 10 bars on the LED indicator, with the red being the highest end of the range and the green being the lowest. For this example, lets the temperature we might find in a house in Colorado, 60 to 80 degrees fahrenheit, or about 15 to 25 degrees celsius (remember, our sensors read celsius, so make sure to convert when necessary)" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "max_temp = 25\n", - "min_temp = 15\n", - "temp_range = max_temp - min_temp" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We should consider \"edge cases\" where our temperature falls above or below our range. These are always good to check before we proceed. In this situation, we will illuminate all LEDs if the temperature is above the range, and 1 LED if it is below the range.\n", - "\n", - "Once we have ruled out edge cases, we can deal with the case where our temperature falls within our allotted range. Because there are 10 bars, we can only only display the temperature in tenths of our range. Knowing what our range is, we can calculate a number between 0 and 10 to represent where within the range we fall. Note that we multiply by 10 and round to the nearest whole number to make sure we pass an integer between 0 and 10 to the function up_to().\n", - "\n", - "Because our LED bar speaks in binary, We are going to use a function \"up_to\" which produces the binary value required to light up the bars \"up to\" a certain index on the led bar, given that index. This is covered more in depth in the [LED Bar notebook](../bootcamp_sessions/3_led_bar.ipynb)." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "def up_to(index):\n", - " return ~(2**(10 - index) - 1)" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "# if temperature is above our range of measurement\n", - "if temp_c > max_temp:\n", - " ledbar.write_binary(up_to(10))\n", - "# if temperature is below our range of measurement\n", - "elif temp_c < min_temp:\n", - " ledbar.write_binary(up_to(0))\n", - "# otherwise is falls within our range\n", - "else:\n", - " temp_index = int(round(((temp_c - min_temp)/temp_range)*10))\n", - " ledbar.write_binary(up_to(temp_index))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 3b01e081d27eb95b07a3a6e008a81e5e7b88b53d Mon Sep 17 00:00:00 2001 From: Dustin Ramsay Date: Wed, 29 Jul 2020 15:54:04 -0600 Subject: [PATCH 7/7] Delete temp_ledbar_example_TH02-checkpoint.ipynb --- .../temp_ledbar_example_TH02-checkpoint.ipynb | 268 ------------------ 1 file changed, 268 deletions(-) delete mode 100644 extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb diff --git a/extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb b/extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb deleted file mode 100644 index 32c40d1..0000000 --- a/extra/.ipynb_checkpoints/temp_ledbar_example_TH02-checkpoint.ipynb +++ /dev/null @@ -1,268 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Displaying Sensor Data on the LED Bar\n", - "\n", - "A key concept in computers is taking an input from a sensor, processing that data in a meaningful way, and outputting that to the user in a format that is intuitive and easy to read. This concept can be found in almost every computing system. \n", - "\n", - "We are going to create this type of system with our sensors and LED bar. The end product will be a sort of \"digital thermometer\".\n", - "\n", - "### This notebook will walk you through using the TH02 sensor\n", - "\n", - "If your sensor looks like this, it is a TH02 and you should follow this notebook. If not, you should use the ATH20 sensor notebook [here](temp_ledbar_example_ATH20.ipynb).\n", - "\n", - "![TH02](https://files.seeedstudio.com/wiki/Grove-TemptureAndHumidity_Sensor-High-Accuracy_AndMini-v1.0/img/main.jpg)\n", - "\n", - "As usual, apply the base overlay to the board:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "\n", - "require(['notebook/js/codecell'], function(codecell) {\n", - " codecell.CodeCell.options_default.highlight_modes[\n", - " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", - " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", - " Jupyter.notebook.get_cells().map(function(cell){\n", - " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", - " });\n", - "});\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from pynq.overlays.base import BaseOverlay\n", - "base = BaseOverlay(\"base.bit\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 1. Read Temperature Data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import Libraries" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.lib.arduino import Grove_TH02\n", - "from pynq.lib.arduino import ARDUINO_GROVE_I2C" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plugging in your TH02 Sensor\n", - "\n", - "This sensor uses the Arduino shield to communicate with your PYNQ Board. Attach the Arduino shield to the top of your PYNQ Board. Then, plug in the TH02 Sensor to one of the ports labeled I2C on the Arduino shield.\n", - "\n", - "![grove_adaptor](https://cdn10.bigcommerce.com/s-7gavg/products/531/images/4194/PYNQ_Shield_-_Oblique_-_600__81639.1473444236.1280.1280.png?c=2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Initialize the Temperature Sensor\n", - "\n", - "We create an variable called \"th02\" that represents the sensor. From this object we can call functions that retrieve data from the sensor." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "th02 = Grove_TH02(base.ARDUINO,ARDUINO_GROVE_I2C)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Read the Temperature and Humidity\n", - "Calling the function read() returns a tuple (two values separated by a comma). The first value is temperature and the second value is humidity." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The temperature is 28.21875 degrees celsius and the relative humidity is 40.0625 %\n" - ] - } - ], - "source": [ - "temp_c, humidity = th02.read()\n", - "print('The temperature is {} degrees celsius and the relative humidity is {} %'.format(temp_c, humidity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Display the Data to the LED Bar\n", - "\n", - "## Connecting the LED Bar\n", - "\n", - "Plug the LED bar into the port labeled G1 on your PMOD to Grove Adaptor. Then plug the PMOD to Grove adaptor into the port labeled PMODB on your PYNQ-Z2 Board" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Setup\n", - "\n", - "When the hardware is connected, run the following code to tell the PYNQ Board how you connected everything. If you plugged into a port besides G1, such as G2, then you will need to import `PMOD_GROVE_G2` instead." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "from pynq.lib.pmod import Grove_LEDbar\n", - "from pynq.lib.pmod import PMOD_GROVE_G1\n", - "\n", - "ledbar = Grove_LEDbar(base.PMODB, PMOD_GROVE_G1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Reset the LED Bar\n", - "\n", - "The default state of the LED could be all sorts of things. Let's turn it fully of so we have somewhere to work from." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "# Turn the LED bar off\n", - "ledbar.reset()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Decide on Your Temperature Scale\n", - "\n", - "We want to make a visual thermometer that displays the temperature across a range that we care about. Perhaps this is simply comfortable room temperature (somewhere between 60 and 80 degrees fahrenheit), or it's the temperature of industrial equipment that cannot get above 150 degrees fahrenheit. What we will do next is establish this range and \"map\" it to the 10 bars on the LED indicator, with the red being the highest end of the range and the green being the lowest. For this example, lets the temperature we might find in a house in Colorado, 60 to 80 degrees fahrenheit, or about 15 to 25 degrees celsius (remember, our sensors read celsius, so make sure to convert when necessary)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "max_temp = 25\n", - "min_temp = 15\n", - "temp_range = max_temp - min_temp" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We should consider \"edge cases\" where our temperature falls above or below our range. These are always good to check before we proceed. In this situation, we will illuminate all LEDs if the temperature is above the range, and 1 LED if it is below the range.\n", - "\n", - "Once we have ruled out edge cases, we can deal with the case where our temperature falls within our allotted range. Because there are 10 bars, we can only only display the temperature in tenths of our range. Knowing what our range is, we can calculate a number between 0 and 10 to represent where within the range we fall. Note that we multiply by 10 and round to the nearest whole number to make sure we pass an integer between 0 and 10 to the function up_to().\n", - "\n", - "Because our LED bar speaks in binary, We are going to use a function \"up_to\" which produces the binary value required to light up the bars \"up to\" a certain index on the led bar, given that index. This is covered more in depth in the [LED Bar notebook](../bootcamp_sessions/3_led_bar.ipynb)." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "def up_to(index):\n", - " return ~(2**(10 - index) - 1)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "# if temperature is above our range of measurement\n", - "if temp_c > max_temp:\n", - " ledbar.write_binary(up_to(10))\n", - "# if temperature is below our range of measurement\n", - "elif temp_c < min_temp:\n", - " ledbar.write_binary(up_to(0))\n", - "# otherwise is falls within our range\n", - "else:\n", - " temp_index = int(round(((temp_c - min_temp)/temp_range)*10))\n", - " ledbar.write_binary(up_to(temp_index))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -}