diff --git a/A.Setting up Your Tools and Workspace/A001 Open Signals/A001 Open Signals.ipynb b/A.Setting up Your Tools and Workspace/A001 Open Signals/A001 Open Signals.ipynb index 45b4f4d..ee4bbce 100644 --- a/A.Setting up Your Tools and Workspace/A001 Open Signals/A001 Open Signals.ipynb +++ b/A.Setting up Your Tools and Workspace/A001 Open Signals/A001 Open Signals.ipynb @@ -1,490 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
Meet your Biosignals with OpenSignals
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Meet your Biosignals with OpenSignals " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Keywords \n", - "\n", - "Open Signals, Biosignals, Physiological Signals Acquisition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributor(s):** Rafael Silva, Hugo Plácido da Silva, Ana Fred\n", - "\n", - "**Date of creation:** 16/05/2022\n", - "\n", - "**Last update:** 16/05/2022" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# I. Introduction\n", - "
\n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Background
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Biosignals have been extensively used in the healthcare and medical domains for more than 100 years, with the best known examples being perhaps Electrocardiography (ECG) and Electroencephalography (EEG). In this lesson we will perform a set of experiments using a real-world biomedical data acquisition system, understand the basic architecture of such systems, review typical setup procedures, and observe multiple signal sources in real-time." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
2. Objectives
\n", - " * Understand the basic blocks of a data acquisition system\n", - " * Get acquainted with biosignal acquisition procedures\n", - " * Handling recorded data on a computing environment" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
3. Materials
\n", - " * OpenSignals (r)evolution software\n", - " * 1x BITalino (r)evolution Board BT\n", - " * 1x 3.7V LiPo battery\n", - " * 1x 2-lead electrode cable\n", - " * 1x 3-lead electrode cable\n", - " * 5x Electrodes\n", - " * 1x Bluetooth adapter (optional)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# II. Experimental\n", - "
\n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###
1.1. Setting up your BITalino (r)evolution
\n", - " 1. Connect the 3.7V LiPo battery on to the JST socket.\n", - "\n", - "\n", - "\n", - " \n", - " 2. Turn on the device (Figure 1(b)); a white LED should start fading.\n", - "\n", - "\n", - "\n", - "\n", - "\n", - " \n", - " 3. Go to the Bluetooth device manager on your computer.\n", - " 4. Search for BITalino devices in range.\n", - " 5. Locate the device named BITalino-XX-XX, where XX-XX are the last four hexadecimal digits on the \n", - " sequence XX:XX:XX:XX:XX:XX labelled on the back of your board.\n", - " 6. Pair your device with the computer using the PIN code 1234.\n", - " \n", - "\n", - "\n", - "\n", - "###
1.2. Installing OpenSignals (r)evolution
\n", - "\n", - " 1. Access the SOFTWARE section on the BITalino website and choose the version that supports your operating system \n", - " (Windows/Mac OS), by clicking on its logo: http://www.bitalino.com/en/software\n", - "\n", - " 2. Open the software to confirm that it is working.\n", - "\n", - " 3. Hovering with the mouse pointer on each button shows a brief description of its function.\n", - "\n", - "###
1.3. Other useful tools
\n", - " \n", - "* Install the Anaconda Python distribution that best suits your platform (Python 2.7 is recommended):\n", - "\n", - " [https://www.anaconda.com/distribution/](https://www.anaconda.com/distribution/)\n", - " \n", - " Get a better understanding of Python environments and toolboxes:\n", - "\n", - " https://github.com/PIA-Group/ScientIST-notebooks/blob/master/C.Signal_Processing/C010%20Setup%20your%20Python%20workspace.ipynb\n", - "\n", - "* Install the BITalino Python API (recommended):\n", - "\n", - " https://github.com/BITalinoWorld/revolution-python-api\n", - "\n", - "* Install OpenSignals (r)evolution Software:\n", - "\n", - " http://bitalino.com/en/software\n", - "\n", - "* Prepare your device by connecting the battery (i.e. slide the battery connector onto the white socket on the BITalino block labelled as PWR)\n", - "\n", - "* Turn your device on by sliding the power button to the ON position; a white LED will start fading in / out, meaning that the device is in standby\n", - "\n", - " \n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " Get familiar with the architecture of BITalino:\n", - " datasheet \n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
2. Acquisition
\n", - "\n", - "\n", - "\n", - "Once your BITalino is turned on, pair the device with your computer via the Bluetooth device manager using the PIN 1234 (this is a one-time process). Your device will be named BITalino-XX-XX, with XX-XX being the last four hex digits of your devices' MAC address." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " **IMPORTANT:** The MAC address is the sequence XX:XX:XX:XX:XX:XX found on the label on the back of the devices' BT block and / or on the back of the cardboard packaging where the device is shipped.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following steps should guide you through to a first glimpse of your signals in real-time:\n", - "\n", - "* Launch **OpenSignals (r)evolution**\n", - "\n", - "* Enable your device for acquisition by pressing the icon presented below on the main screen and clicking the box showing the MAC address of your device (this is a one-time process) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"-\"\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " **IMPORTANT:** The ENABLE button needs to be blue.\n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "* You can proceed directly to record data, but you can also use this screen to configure the acquisition settings for your device (e.g. select the channels to be acquired, identify the type of sensor or change the sampling rate)\n", - "\n", - "* It is recommended that you review the sensor datasheets to obtain instructions regarding the typical electrode placement, sensor specifications and the transfer functions that can be used to convert the raw data into the correct physical units:\n", - "\n", - " * [Electromiography (EMG)](http://bitalino.com/datasheets/REVOLUTION_EMG_Sensor_Datasheet.pdf)\n", - " \n", - " * [Electrodermal Activity (EDA)](http://bitalino.com/datasheets/REVOLUTION_EDA_Sensor_Datasheet.pdf)\n", - " * [Electrocardiography (ECG)](http://bitalino.com/datasheets/REVOLUTION_ECG_Sensor_Datasheet.pdf)\n", - " * [Electroencephalography (EEG)](http://bitalino.com/datasheets/EEG_Sensor_Datasheet.pdf)\n", - " * [Accelerometry (ACC)](http://bitalino.com/datasheets/REVOLUTION_ACC_Sensor_Datasheet.pdf)\n", - " * [Optical Sensing (LUX)](http://bitalino.com/datasheets/REVOLUTION_LUX_Sensor_Datasheet.pdf)\n", - " * [Event Annotation (BTN)](http://bitalino.com/datasheets/REVOLUTION_BTN_Sensor_Datasheet.pdf)\n", - "* **Record a signal** by pressing the red circle on the main menu of the software\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\"Opensignals2\"\n", - " \n", - "### Testing your setup\n", - "1. Access the DEVICE MANAGER screen on the OpenSignals (r)evolution software \n", - "\n", - "\"-\"\n", - "\n", - "\n", - "\n", - "2. Click on your device and confirm that it is enabled for data acquisition (ENABLE button highlighted in blue)\n", - "\n", - "\"-\"\n", - "\n", - "\n", - "3. Press the RECORD icon to start a data acquisition session\n", - "\n", - "\"-\"\n", - "\n", - "\n", - "4. The white LED on your device should switch from fading to blinking (indicating that the device is streaming data), and the acquisition time should be running on screen\n", - "\n", - "\"-\"\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
3. Opening Recorded Data in Python
\n", - "\n", - "Locate a recording on your hard drive; for your convenience, we provide the [SampleACC.txt](https://github.com/PIA-Group/ScientIST-notebooks/blob/master/_Resources/SampleACC.txt) file with a snippet of Accelerometry (ACC) data.\n", - "\n", - "You can make a simple experiment using the Python script below.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pylab import *\n", - "\n", - "data = loadtxt(\"SampleACC.txt\")\n", - "\n", - "plot(data[:,5])\n", - "show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This code uses the function [loadtxt](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.loadtxt.html) (in this case made available through the PyLab module), to load the recorded data onto a variable in your program and display it in a graphic:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!git clone https://github.com/BITalinoWorld/python-lab-guides >/dev/null 2>&1\n", - "! pip install mpld3 >/dev/null 2>&1" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "! cd python-lab-guides >/dev/null 2>&1" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/html": [ - "\n", - "\n", - "\n", - "\n", - "
\n", - "" - ], - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "from pylab import *\n", - "%matplotlib inline\n", - "import mpld3\n", - "mpld3.enable_notebook()\n", - "\n", - "data = loadtxt(\"BITalino Hands-on/SampleACC.txt\")\n", - "\n", - "title('Accelerometry (ACC) data Sample')\n", - "plot(data[:,5],color=\"#00a0e4\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# III. Explore\n", - "
\n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Quiz
\n", - "\n", - "1. Draw a block diagram that shows the information flow and different stages between the body and the PC in a biosignal acquisition system.\n", - "\n", - "2. Show a screenshot with Accelerometer (ACC) data for one of the repetitions executed in II.2. What do you interpret from this data?\n", - "\n", - "3. As highlighted in the introductory segment of II.2., only one axis is connected by default. Which axis is it? Explain how you reached your conclusion.\n", - "\n", - "4. Show a screenshot of a relevant portion of Electromyography (EMG) data within the experiment proposed on II.3. Does this signal correspond to what you expected? Why?\n", - "\n", - "5. To the best of your knowledge, which noise sources can affect measurements made with bioelectrical sensors?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "\n", - " \"it\" \n", - "\"alternate\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
\n", - " Please provide us your feedback here. \n", - "
\n", - " Suggestions are welcome! \n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```Contributors: Prof. Hugo Silva; Joana Pinto```" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["
Meet your Biosignals with OpenSignals
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Meet your Biosignals with OpenSignals "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Keywords \n", "\n", "Open Signals, Biosignals, Physiological Signals Acquisition"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Contributor(s):** Rafael Silva, Hugo Pl\u00e1cido da Silva, Ana Fred\n", "\n", "**Date of creation:** 16/05/2022\n", "\n", "**Last update:** 16/05/2022"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# I. Introduction\n", "
\n", "
\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Background
\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Biosignals have been extensively used in the healthcare and medical domains for more than 100 years, with the best known examples being perhaps Electrocardiography (ECG) and Electroencephalography (EEG). In this lesson we will perform a set of experiments using a real-world biomedical data acquisition system, understand the basic architecture of such systems, review typical setup procedures, and observe multiple signal sources in real-time."]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
2. Objectives
\n", " * Understand the basic blocks of a data acquisition system\n", " * Get acquainted with biosignal acquisition procedures\n", " * Handling recorded data on a computing environment"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
3. Materials
\n", " * OpenSignals (r)evolution software\n", " * 1x BITalino (r)evolution Board BT\n", " * 1x 3.7V LiPo battery\n", " * 1x 2-lead electrode cable\n", " * 1x 3-lead electrode cable\n", " * 5x Electrodes\n", " * 1x Bluetooth adapter (optional)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# II. Experimental\n", "
\n", "
\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["###
1.1. Setting up your BITalino (r)evolution
\n", " 1. Connect the 3.7V LiPo battery on to the JST socket.\n", "\n", "\n", "\n", " \n", " 2. Turn on the device (Figure 1(b)); a white LED should start fading.\n", "\n", "\n", "\n", "\n", "\n", " \n", " 3. Go to the Bluetooth device manager on your computer.\n", " 4. Search for BITalino devices in range.\n", " 5. Locate the device named BITalino-XX-XX, where XX-XX are the last four hexadecimal digits on the \n", " sequence XX:XX:XX:XX:XX:XX labelled on the back of your board.\n", " 6. Pair your device with the computer using the PIN code 1234.\n", " \n", "\n", "\n", "\n", "###
1.2. Installing OpenSignals (r)evolution
\n", "\n", " 1. Access the SOFTWARE section on the BITalino website and choose the version that supports your operating system \n", " (Windows/Mac OS), by clicking on its logo: http://www.bitalino.com/en/software\n", "\n", " 2. Open the software to confirm that it is working.\n", "\n", " 3. Hovering with the mouse pointer on each button shows a brief description of its function.\n", "\n", "###
1.3. Other useful tools
\n", " \n", "* Install the Anaconda Python distribution that best suits your platform (Python 2.7 is recommended):\n", "\n", " [https://www.anaconda.com/distribution/](https://www.anaconda.com/distribution/)\n", " \n", " Get a better understanding of Python environments and toolboxes:\n", "\n", " https://github.com/PIA-Group/ScientIST-notebooks/blob/master/C.Signal_Processing/C010%20Setup%20your%20Python%20workspace.ipynb\n", "\n", "* Install the BITalino Python API (recommended):\n", "\n", " https://github.com/BITalinoWorld/revolution-python-api\n", "\n", "* Install OpenSignals (r)evolution Software:\n", "\n", " http://bitalino.com/en/software\n", "\n", "* Prepare your device by connecting the battery (i.e. slide the battery connector onto the white socket on the BITalino block labelled as PWR)\n", "\n", "* Turn your device on by sliding the power button to the ON position; a white LED will start fading in / out, meaning that the device is in standby\n", "\n", " \n", "\n", "\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " Get familiar with the architecture of BITalino:\n", " datasheet \n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
2. Acquisition
\n", "\n", "\n", "\n", "Once your BITalino is turned on, pair the device with your computer via the Bluetooth device manager using the PIN 1234 (this is a one-time process). Your device will be named BITalino-XX-XX, with XX-XX being the last four hex digits of your devices' MAC address."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " **IMPORTANT:** The MAC address is the sequence XX:XX:XX:XX:XX:XX found on the label on the back of the devices' BT block and / or on the back of the cardboard packaging where the device is shipped.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The following steps should guide you through to a first glimpse of your signals in real-time:\n", "\n", "* Launch **OpenSignals (r)evolution**\n", "\n", "* Enable your device for acquisition by pressing the icon presented below on the main screen and clicking the box showing the MAC address of your device (this is a one-time process) "]}, {"cell_type": "markdown", "metadata": {}, "source": ["\"-\"\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " **IMPORTANT:** The ENABLE button needs to be blue.\n", "
\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["* You can proceed directly to record data, but you can also use this screen to configure the acquisition settings for your device (e.g. select the channels to be acquired, identify the type of sensor or change the sampling rate)\n", "\n", "* It is recommended that you review the sensor datasheets to obtain instructions regarding the typical electrode placement, sensor specifications and the transfer functions that can be used to convert the raw data into the correct physical units:\n", "\n", " * [Electromiography (EMG)](http://bitalino.com/datasheets/REVOLUTION_EMG_Sensor_Datasheet.pdf)\n", " \n", " * [Electrodermal Activity (EDA)](http://bitalino.com/datasheets/REVOLUTION_EDA_Sensor_Datasheet.pdf)\n", " * [Electrocardiography (ECG)](http://bitalino.com/datasheets/REVOLUTION_ECG_Sensor_Datasheet.pdf)\n", " * [Electroencephalography (EEG)](http://bitalino.com/datasheets/EEG_Sensor_Datasheet.pdf)\n", " * [Accelerometry (ACC)](http://bitalino.com/datasheets/REVOLUTION_ACC_Sensor_Datasheet.pdf)\n", " * [Optical Sensing (LUX)](http://bitalino.com/datasheets/REVOLUTION_LUX_Sensor_Datasheet.pdf)\n", " * [Event Annotation (BTN)](http://bitalino.com/datasheets/REVOLUTION_BTN_Sensor_Datasheet.pdf)\n", "* **Record a signal** by pressing the red circle on the main menu of the software\n", "\n", "\n", "\n", "\n", "\n", "\"Opensignals2\"\n", " \n", "### Testing your setup\n", "1. Access the DEVICE MANAGER screen on the OpenSignals (r)evolution software \n", "\n", "\"-\"\n", "\n", "\n", "\n", "2. Click on your device and confirm that it is enabled for data acquisition (ENABLE button highlighted in blue)\n", "\n", "\"-\"\n", "\n", "\n", "3. Press the RECORD icon to start a data acquisition session\n", "\n", "\"-\"\n", "\n", "\n", "4. The white LED on your device should switch from fading to blinking (indicating that the device is streaming data), and the acquisition time should be running on screen\n", "\n", "\"-\"\n", "\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
3. Opening Recorded Data in Python
\n", "\n", "Locate a recording on your hard drive; for your convenience, we provide the [SampleACC.txt](https://github.com/PIA-Group/ScientIST-notebooks/blob/master/_Resources/SampleACC.txt) file with a snippet of Accelerometry (ACC) data.\n", "\n", "You can make a simple experiment using the Python script below.\n"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pylab import *\n", "\n", "data = loadtxt(\"SampleACC.txt\")\n", "\n", "plot(data[:,5])\n", "show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This code uses the function [loadtxt](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.loadtxt.html) (in this case made available through the PyLab module), to load the recorded data onto a variable in your program and display it in a graphic:\n"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["!git clone https://github.com/BITalinoWorld/python-lab-guides >/dev/null 2>&1\n", "! pip install mpld3 >/dev/null 2>&1"]}, {"cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": ["! cd python-lab-guides >/dev/null 2>&1"]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["[]"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}, {"data": {"image/png": "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\n", "text/html": ["\n", "\n", "\n", "\n", "
\n", ""], "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["from pylab import *\n", "%matplotlib inline\n", "import mpld3\n", "mpld3.enable_notebook()\n", "\n", "data = loadtxt(\"BITalino Hands-on/SampleACC.txt\")\n", "\n", "title('Accelerometry (ACC) data Sample')\n", "plot(data[:,5],color=\"#00a0e4\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# III. Explore\n", "
\n", "
\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Quiz
\n", "\n", "1. Draw a block diagram that shows the information flow and different stages between the body and the PC in a biosignal acquisition system.\n", "\n", "2. Show a screenshot with Accelerometer (ACC) data for one of the repetitions executed in II.2. What do you interpret from this data?\n", "\n", "3. As highlighted in the introductory segment of II.2., only one axis is connected by default. Which axis is it? Explain how you reached your conclusion.\n", "\n", "4. Show a screenshot of a relevant portion of Electromyography (EMG) data within the experiment proposed on II.3. Does this signal correspond to what you expected? Why?\n", "\n", "5. To the best of your knowledge, which noise sources can affect measurements made with bioelectrical sensors?"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", "\n", " \"it\" \n", "\"alternate\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", "
\n", " Please provide us your feedback here. \n", "
\n", " Suggestions are welcome! \n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["```Contributors: Prof. Hugo Silva; Joana Pinto```"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "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.9.12"}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file diff --git a/A.Setting up Your Tools and Workspace/A006 ScientISST - Arduino IDE tutorial/A006 ScientISST - Arduino IDE tutorial.ipynb b/A.Setting up Your Tools and Workspace/A006 ScientISST - Arduino IDE tutorial/A006 ScientISST - Arduino IDE tutorial.ipynb index 96fd4f3..0c24b46 100644 --- a/A.Setting up Your Tools and Workspace/A006 ScientISST - Arduino IDE tutorial/A006 ScientISST - Arduino IDE tutorial.ipynb +++ b/A.Setting up Your Tools and Workspace/A006 ScientISST - Arduino IDE tutorial/A006 ScientISST - Arduino IDE tutorial.ipynb @@ -1 +1 @@ -{"cells":[{"cell_type":"markdown","id":"7c7e72b3","metadata":{},"source":["![scientisst-notebooks_top-banner](https://raw.githubusercontent.com/scientisst/notebooks/59632d3d477981a3b1cc12157e12bbdcdb45def8/_Resources/top-banner.png)"]},{"cell_type":"markdown","id":"67f4d085","metadata":{},"source":["# ScientISST - Arduino IDE Tutorial "]},{"cell_type":"markdown","id":"67f4d085","metadata":{},"source":["### Keywords \n","\n","`ScientISST`, `ScientISST CORE`, `Arduino IDE`, `Firmware`"]},{"cell_type":"markdown","id":"67f4d085","metadata":{},"source":["### Notebook Info \n","\n","**Author(s):** Leonor Pereira; Ana Sofia Carmo; Francisco Melo; Afonso Raposo; Prof. Hugo Silva\n","\n","**Date of creation:** 01/22\n","\n","**Last update:** 11/22"]},{"cell_type":"markdown","id":"14f722c1","metadata":{},"source":["

\n"," \n","

\n","

ScientISST CORE.

"]},{"cell_type":"markdown","id":"01a9b3d3","metadata":{},"source":["### Description \n","\n","In this tutorial, we will dive into the world of embedded systems programming and show how you can write, compile, program and execute your own code on the ScientISST SENSE development board through Arduino's Integrated Development Environment (IDE), whether you’re using Windows, Mac OS X or Linux."]},{"cell_type":"markdown","id":"856dc6d4","metadata":{},"source":["### Objectives \n","\n","* Understand the ScientISST SENSE development board and computational paradigm via the Arduino IDE\n","* Setup the development tools in your computer\n","* Write, compile, program and execute your own code on the ScientISST SENSE development board"]},{"cell_type":"markdown","id":"2c9c23f9","metadata":{},"source":["### Materials \n","\n","* Arduino IDE\n","* 1x ScientISST SENSE development board\n","* 1x USB-C cable"]},{"cell_type":"markdown","id":"796b03fa","metadata":{},"source":["***"]},{"cell_type":"markdown","id":"b9e9f899","metadata":{},"source":["# 1. Background \n","\n","The ScientISST SENSE development board is an hardware platform, designed to empower students, researchers or anyone with an interest in developing biomedical engineering projects with the tools to easily create microcontroller-based devices and bring their health and well-being creations to life. \n","\n","By default the board is pre-programmed with a firmware optimized for real-time data acquisition and streaming, and can be used seamlessly with the available software and APIs. However, it is often important to experiment with custom firmware in a user-friendly way."]},{"cell_type":"markdown","id":"1d33e702","metadata":{},"source":["#
2. Prerequisites
"]},{"cell_type":"markdown","id":"5ac569af","metadata":{},"source":["##
2.1. Installing the Arduino IDE
\n","\n","Before starting this tutorial, you need to download and install the latest version of the Arduino IDE from: https://www.arduino.cc/en/software [[1]](#reference_1). If you don’t have the latest version installed, uninstall Arduino IDE and install it again. Otherwise, it may not work.\n","\n","After you have the latest Arduino IDE software installed in your computer, open the software to confirm that it is working. Hovering with the mouse pointer on each button shows a brief description of its function. The following figure summarizes these functionalities:"]},{"cell_type":"markdown","id":"5ffd44b5","metadata":{},"source":["\n","\n","\n","
\n","

Figure 1: Overview of the Arduino IDE Graphical User Interface (GUI).

"]},{"cell_type":"markdown","id":"aa4d8aa1","metadata":{},"source":["> 💡 **EXPLORE:** To get a better understanding on the Arduino IDE and its functionalities, a more comprehensive guide on this topic is available at: https://www.arduino.cc/en/Guide/Environment [[2]](#reference_2)."]},{"cell_type":"markdown","id":"3fe9329e","metadata":{},"source":["##
2.2. Installing the ESP32 Add-on in Arduino IDE
"]},{"cell_type":"markdown","id":"afc2a229","metadata":{},"source":["The ScientISST SENSE development board is built upon the ESP32-WROOM-32, a powerful, generic Wi-Fi+BT+BLE MCU module, which has at its core the ESP32-D0WDQ6 chip. This is why you first need to install the ESP32 add-on in the Arduino IDE in order to program the ScientISST SENSE development board from the Arduino IDE using its programming language (C/C++). To install this add-on, follow the next instructions:"]},{"cell_type":"markdown","id":"118af3b1","metadata":{},"source":["**2.1.** In the Arduino IDE, go to *File > Preferences*:
\n","\n","

\n"," \n","

\n","

Figure 2: Arduino IDE - How to open Preferences tab.

"]},{"cell_type":"markdown","id":"773bc891","metadata":{},"source":["**2.2\\.** Enter `https://dl.espressif.com/dl/package_esp32_index.json`\n","[[3]](#reference_3) into the “Additional Board Manager URLs” field (1) in the “Preferences” window as shown in the figure below. Then, click the “OK” button (2):
\n","\n","

\n"," \n","

\n","

Figure 3: Arduino IDE - How to add the ESP32 add-on.

\n","\n","> ⚡ **TIP:** If you already have the URL of another board in the “Additional Board Manager URLs” field, you can separate the URLs with a comma as displayed in the figure above."]},{"cell_type":"markdown","id":"2b979ae0","metadata":{},"source":["**2.3\\.** Open the Boards Manager. Go to *Tools > Board > Boards Manager*
\n","\n","\n","

\n"," \n","

\n","

Figure 4: Arduino IDE - How to open the Boards Manager tab.

"]},{"cell_type":"markdown","id":"bb34051f","metadata":{},"source":["**2.4\\.** Search for ESP32 and press the “Install” button for the “**esp32** by **Espressif Systems**”:
\n","\n","

\n"," \n","

\n","

Figure 5: Arduino IDE - How to install the ESP32 add-on.

"]},{"cell_type":"markdown","id":"a730f4f1","metadata":{},"source":["**2.5\\.** The add-on should be installed after a few seconds, as shown in the following figure:
\n","\n","

\n"," \n","

\n","

Figure 6: Arduino IDE - ESP32 add-on is installed.

"]},{"cell_type":"markdown","id":"a69b6c95","metadata":{},"source":["#
3. Setting up your ScientISST board to upload code from the Arduino IDE
"]},{"cell_type":"markdown","id":"b076b6c6","metadata":{},"source":["**3.1.** Connect the USB-C cable to your computer and to the corresponding socket on the ScientISST SENSE development board:
\n","\n","     **3.1.1** Connect the standard USB-A connector to your computer:
\n","\n","

\n"," \n","

\n","

Figure 7: Connect the USB-A end to your computer.

\n"," \n","     **3.1.2** Connect the other end to your ScientISST SENSE development board:
\n"," \n","

\n"," \n","

\n","

Figure 8: Connect the USB-C end to your ScientISST CORE development board.

"]},{"cell_type":"markdown","id":"1cf453e0","metadata":{},"source":["At this point, the built-in blue LED on the back of the ScientISST SENSE development board should be on, and the built-in white LED on the front should be blinking repeatedly, if the board still carries the default firmware."]},{"cell_type":"markdown","id":"fe52e670","metadata":{},"source":["**3.2\\.** In the Arduino IDE, go to `Tools > Board > ESP32 Arduino` and select your board model, i.e. ESP32 Dev Module:
\n","\n","

\n"," \n","

\n","

Figure 9: Arduino IDE - How to select the board.

"]},{"cell_type":"markdown","id":"4c5008eb","metadata":{},"source":["**3.3\\.** Go to `Tools > Port` and select the port that your ScientISST SENSE development board is using. On Windows it should have the prefix `COM`, followed by an integer number (as is the case in the figure below), and on Mac OS it should have the prefix `/dev/cu.usb` or `/dev/tty.usb`. Usually the port of your newly added device appears at the end of the list:\n","\n","

\n"," \n","

\n","

Figure 10: Arduino IDE - How to select the port.

\n","\n","> ⚡ **TIP:** If you don’t see the COM Port in your Arduino IDE, you need to install the CP210x USB to UART Bridge VCP Drivers from: https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers [[4]](#reference_4)."]},{"cell_type":"markdown","id":"9f557ee7","metadata":{},"source":["**3.4\\.** To upload a sketch with your code written on the Arduino IDE, you must first put your ScientISST SENSE development board on **BOOT mode**. To do so, you will need to use the RESET and MODE buttons on the ScientISST SENSE development board, shown in the following figure:\n","\n","

\n"," \n","

\n","

Figure 11: Button labels on the ScientISST CORE.

"]},{"cell_type":"markdown","id":"221f4ed4","metadata":{},"source":["Before uploading the sketch:\n","\n","1. Hold down the MODE button\n","2. Press the RESET button\n","3. Release the MODE button\n","\n","If the previous steps were done correctly, the white LED should have stopped blinking.\n","\n","At this point, the ScientISST SENSE development board is now on BOOT mode and is ready to have the sketch uploaded to it."]},{"cell_type":"markdown","id":"ceb8919a","metadata":{},"source":["**3.5\\.** Upload the sketch to your board by clicking the “Upload” button in the Arduino IDE:\n","\n","\n","

\n"," \n","

\n","

Figure 12: Arduino IDE - How to upload a sketch.

"]},{"cell_type":"markdown","id":"c484d0bb","metadata":{},"source":["Wait a few seconds while the code compiles and uploads to your board. If everything went as expected, the MESSAGES section of the Arduino IDE should show a notification indicating that the code has been uploaded, and list general information regarding the device and memory use:\n","\n","

\n"," \n","

\n","

Figure 13: Arduino IDE - After uploading correctly.

\n","\n","> ⚡ **TIP:** In case you obtain an error during the upload, read the output in the MESSAGES section carefully and you will likely be able to have a rough idea of what went wrong. The most common causes of problems are syntax errors in your code, a mismatching board version on the Arduino IDE, or a wrongly selected port, so please review your code and try to identify any typos or mismatching\n","characters.\n","\n","> ⚡ **`exec: \"python\": executable file not found in $PATH`:** If you get this error, resort to this discussion [https://stackoverflow.com/questions/60762378/exec-python-executable-file-not-found-in-path](https://stackoverflow.com/questions/60762378/exec-python-executable-file-not-found-in-path)."]},{"cell_type":"markdown","id":"adeaf43d","metadata":{},"source":["**3.6\\.** Finally, press the RESET button to put your ScientISST SENSE development board on Execution mode and have it run the uploaded code.\n","
\n","
"]},{"cell_type":"markdown","id":"e5d91d20","metadata":{},"source":["#
4. Testing your Setup
"]},{"cell_type":"markdown","id":"506e1d22","metadata":{},"source":["To test your setup, follow the steps from Section II.3.4 to II.3.6 (above) and upload the Blink sketch, one of the built-in examples of the Arduino IDE that can be loaded from `File > Examples > 01.Basics > Blink`:\n","\n","\n","

\n"," \n","

\n","

Figure 14: Arduino IDE - How to open a Blink sketch.

\n","\n","> ❗ **DON'T FORGET:** Don't forget to replace the ```LED_BUILTIN``` in the Blink sketch with the number of the pin connected to the white LED (GPIO 22).\n","\n","Upon successful completion of the process, the white LED on the front of the board should be on for one second, then off for one second, repeatedly."]},{"cell_type":"markdown","id":"23876435","metadata":{},"source":["#
5. Explore
\n"]},{"cell_type":"markdown","id":"3b8e7bbb","metadata":{},"source":["##
5.1. Final Notes
\n","\n","After following this tutorial, you should now be capable of writing, compiling, programing and executing your own code on the ScientISST SENSE development board through the Arduino IDE. We hope you find this hardware platform useful in the development of future projects and applications!\n","\n","As a final note, we leave here some words of **caution** to avoid damaging the board:\n","\n","> ⚠️ **WARNING - NEVER:** \n","> * Connect the voltage pins (e.g. the 3.3V pin) to another (external) voltage source, regardless of its type. \n","> * Connect the voltage pins to the GND. \n","> * Leave unconnected or “live” wires floating around your board, as they can inadvertently create short circuits between components\n","> * Bend, twist, cut, score, apply weight or otherwise perform any mechanical abuse to your board; it is fragile! \n","\n"," \n","> ⚠️ **WARNING - ALWAYS:** \n","> * Think and study the problem carefully to reach a convincing solution that can achieve the goals your are trying to fulfill, before taking action.\n","> * Have your board disconnected from the computer while assembling your circuits. "]},{"cell_type":"markdown","id":"89cdc85e","metadata":{},"source":["##
5.2. Further Reading
"]},{"cell_type":"markdown","id":"a77796a7","metadata":{},"source":[" 1\\. https://www.arduino.cc/en/software\n","\n"," 2\\. https://www.arduino.cc/en/Guide/Environment\n","\n"," 3\\. https://dl.espressif.com/dl/package_esp32_index.json\n","\n"," 4\\. https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers"]},{"cell_type":"markdown","id":"b43198d5","metadata":{},"source":["***"]},{"cell_type":"markdown","id":"7f78cd41","metadata":{},"source":["![scientisst-notebooks_bottom-banner](https://raw.githubusercontent.com/scientisst/notebooks/master/_Resources/bottom-banner.png)"]}],"metadata":{"kernelspec":{"display_name":"Python 3.10.0 64-bit","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.10.0"},"vscode":{"interpreter":{"hash":"7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad"}}},"nbformat":4,"nbformat_minor":5} +{"cells": [{"cell_type": "markdown", "id": "7c7e72b3", "metadata": {}, "source": ["![scientisst-notebooks_top-banner](https://raw.githubusercontent.com/scientisst/notebooks/59632d3d477981a3b1cc12157e12bbdcdb45def8/_Resources/top-banner.png)"]}, {"cell_type": "markdown", "id": "67f4d085", "metadata": {}, "source": ["# ScientISST - Arduino IDE Tutorial "]}, {"cell_type": "markdown", "id": "67f4d085", "metadata": {}, "source": ["### Keywords \n", "\n", "`ScientISST`, `ScientISST CORE`, `Arduino IDE`, `Firmware`"]}, {"cell_type": "markdown", "id": "67f4d085", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Author(s):** Leonor Pereira; Ana Sofia Carmo; Francisco Melo; Afonso Raposo; Prof. Hugo Silva\n", "\n", "**Date of creation:** 01/22\n", "\n", "**Last update:** 11/22"]}, {"cell_type": "markdown", "id": "14f722c1", "metadata": {}, "source": ["

\n", " \n", "

\n", "

ScientISST CORE.

"]}, {"cell_type": "markdown", "id": "01a9b3d3", "metadata": {}, "source": ["### Description \n", "\n", "In this tutorial, we will dive into the world of embedded systems programming and show how you can write, compile, program and execute your own code on the ScientISST SENSE development board through Arduino's Integrated Development Environment (IDE), whether you\u2019re using Windows, Mac OS X or Linux."]}, {"cell_type": "markdown", "id": "856dc6d4", "metadata": {}, "source": ["### Objectives \n", "\n", "* Understand the ScientISST SENSE development board and computational paradigm via the Arduino IDE\n", "* Setup the development tools in your computer\n", "* Write, compile, program and execute your own code on the ScientISST SENSE development board"]}, {"cell_type": "markdown", "id": "2c9c23f9", "metadata": {}, "source": ["### Materials \n", "\n", "* Arduino IDE\n", "* 1x ScientISST SENSE development board\n", "* 1x USB-C cable"]}, {"cell_type": "markdown", "id": "796b03fa", "metadata": {}, "source": ["***"]}, {"cell_type": "markdown", "id": "b9e9f899", "metadata": {}, "source": ["# 1. Background \n", "\n", "The ScientISST SENSE development board is an hardware platform, designed to empower students, researchers or anyone with an interest in developing biomedical engineering projects with the tools to easily create microcontroller-based devices and bring their health and well-being creations to life. \n", "\n", "By default the board is pre-programmed with a firmware optimized for real-time data acquisition and streaming, and can be used seamlessly with the available software and APIs. However, it is often important to experiment with custom firmware in a user-friendly way."]}, {"cell_type": "markdown", "id": "1d33e702", "metadata": {}, "source": ["#
2. Prerequisites
"]}, {"cell_type": "markdown", "id": "5ac569af", "metadata": {}, "source": ["##
2.1. Installing the Arduino IDE
\n", "\n", "Before starting this tutorial, you need to download and install the latest version of the Arduino IDE from: https://www.arduino.cc/en/software [[1]](#reference_1). If you don\u2019t have the latest version installed, uninstall Arduino IDE and install it again. Otherwise, it may not work.\n", "\n", "After you have the latest Arduino IDE software installed in your computer, open the software to confirm that it is working. Hovering with the mouse pointer on each button shows a brief description of its function. The following figure summarizes these functionalities:"]}, {"cell_type": "markdown", "id": "5ffd44b5", "metadata": {}, "source": ["\n", "\n", "\n", "
\n", "

Figure 1: Overview of the Arduino IDE Graphical User Interface (GUI).

"]}, {"cell_type": "markdown", "id": "aa4d8aa1", "metadata": {}, "source": ["> \ud83d\udca1 **EXPLORE:** To get a better understanding on the Arduino IDE and its functionalities, a more comprehensive guide on this topic is available at: https://www.arduino.cc/en/Guide/Environment [[2]](#reference_2)."]}, {"cell_type": "markdown", "id": "3fe9329e", "metadata": {}, "source": ["##
2.2. Installing the ESP32 Add-on in Arduino IDE
"]}, {"cell_type": "markdown", "id": "afc2a229", "metadata": {}, "source": ["The ScientISST SENSE development board is built upon the ESP32-WROOM-32, a powerful, generic Wi-Fi+BT+BLE MCU module, which has at its core the ESP32-D0WDQ6 chip. This is why you first need to install the ESP32 add-on in the Arduino IDE in order to program the ScientISST SENSE development board from the Arduino IDE using its programming language (C/C++). To install this add-on, follow the next instructions:"]}, {"cell_type": "markdown", "id": "118af3b1", "metadata": {}, "source": ["**2.1.** In the Arduino IDE, go to *File > Preferences*:
\n", "\n", "

\n", " \n", "

\n", "

Figure 2: Arduino IDE - How to open Preferences tab.

"]}, {"cell_type": "markdown", "id": "773bc891", "metadata": {}, "source": ["**2.2\\.** Enter `https://dl.espressif.com/dl/package_esp32_index.json`\n", "[[3]](#reference_3) into the \u201cAdditional Board Manager URLs\u201d field (1) in the \u201cPreferences\u201d window as shown in the figure below. Then, click the \u201cOK\u201d button (2):
\n", "\n", "

\n", " \n", "

\n", "

Figure 3: Arduino IDE - How to add the ESP32 add-on.

\n", "\n", "> \u26a1 **TIP:** If you already have the URL of another board in the \u201cAdditional Board Manager URLs\u201d field, you can separate the URLs with a comma as displayed in the figure above."]}, {"cell_type": "markdown", "id": "2b979ae0", "metadata": {}, "source": ["**2.3\\.** Open the Boards Manager. Go to *Tools > Board > Boards Manager*
\n", "\n", "\n", "

\n", " \n", "

\n", "

Figure 4: Arduino IDE - How to open the Boards Manager tab.

"]}, {"cell_type": "markdown", "id": "bb34051f", "metadata": {}, "source": ["**2.4\\.** Search for ESP32 and press the \u201cInstall\u201d button for the \u201c**esp32** by **Espressif Systems**\u201d:
\n", "\n", "

\n", " \n", "

\n", "

Figure 5: Arduino IDE - How to install the ESP32 add-on.

"]}, {"cell_type": "markdown", "id": "a730f4f1", "metadata": {}, "source": ["**2.5\\.** The add-on should be installed after a few seconds, as shown in the following figure:
\n", "\n", "

\n", " \n", "

\n", "

Figure 6: Arduino IDE - ESP32 add-on is installed.

"]}, {"cell_type": "markdown", "id": "a69b6c95", "metadata": {}, "source": ["#
3. Setting up your ScientISST board to upload code from the Arduino IDE
"]}, {"cell_type": "markdown", "id": "b076b6c6", "metadata": {}, "source": ["**3.1.** Connect the USB-C cable to your computer and to the corresponding socket on the ScientISST SENSE development board:
\n", "\n", "     **3.1.1** Connect the standard USB-A connector to your computer:
\n", "\n", "

\n", " \n", "

\n", "

Figure 7: Connect the USB-A end to your computer.

\n", " \n", "     **3.1.2** Connect the other end to your ScientISST SENSE development board:
\n", " \n", "

\n", " \n", "

\n", "

Figure 8: Connect the USB-C end to your ScientISST CORE development board.

"]}, {"cell_type": "markdown", "id": "1cf453e0", "metadata": {}, "source": ["At this point, the built-in blue LED on the back of the ScientISST SENSE development board should be on, and the built-in white LED on the front should be blinking repeatedly, if the board still carries the default firmware."]}, {"cell_type": "markdown", "id": "fe52e670", "metadata": {}, "source": ["**3.2\\.** In the Arduino IDE, go to `Tools > Board > ESP32 Arduino` and select your board model, i.e. ESP32 Dev Module:
\n", "\n", "

\n", " \n", "

\n", "

Figure 9: Arduino IDE - How to select the board.

"]}, {"cell_type": "markdown", "id": "4c5008eb", "metadata": {}, "source": ["**3.3\\.** Go to `Tools > Port` and select the port that your ScientISST SENSE development board is using. On Windows it should have the prefix `COM`, followed by an integer number (as is the case in the figure below), and on Mac OS it should have the prefix `/dev/cu.usb` or `/dev/tty.usb`. Usually the port of your newly added device appears at the end of the list:\n", "\n", "

\n", " \n", "

\n", "

Figure 10: Arduino IDE - How to select the port.

\n", "\n", "> \u26a1 **TIP:** If you don\u2019t see the COM Port in your Arduino IDE, you need to install the CP210x USB to UART Bridge VCP Drivers from: https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers [[4]](#reference_4)."]}, {"cell_type": "markdown", "id": "9f557ee7", "metadata": {}, "source": ["**3.4\\.** To upload a sketch with your code written on the Arduino IDE, you must first put your ScientISST SENSE development board on **BOOT mode**. To do so, you will need to use the RESET and MODE buttons on the ScientISST SENSE development board, shown in the following figure:\n", "\n", "

\n", " \n", "

\n", "

Figure 11: Button labels on the ScientISST CORE.

"]}, {"cell_type": "markdown", "id": "221f4ed4", "metadata": {}, "source": ["Before uploading the sketch:\n", "\n", "1. Hold down the MODE button\n", "2. Press the RESET button\n", "3. Release the MODE button\n", "\n", "If the previous steps were done correctly, the white LED should have stopped blinking.\n", "\n", "At this point, the ScientISST SENSE development board is now on BOOT mode and is ready to have the sketch uploaded to it."]}, {"cell_type": "markdown", "id": "ceb8919a", "metadata": {}, "source": ["**3.5\\.** Upload the sketch to your board by clicking the \u201cUpload\u201d button in the Arduino IDE:\n", "\n", "\n", "

\n", " \n", "

\n", "

Figure 12: Arduino IDE - How to upload a sketch.

"]}, {"cell_type": "markdown", "id": "c484d0bb", "metadata": {}, "source": ["Wait a few seconds while the code compiles and uploads to your board. If everything went as expected, the MESSAGES section of the Arduino IDE should show a notification indicating that the code has been uploaded, and list general information regarding the device and memory use:\n", "\n", "

\n", " \n", "

\n", "

Figure 13: Arduino IDE - After uploading correctly.

\n", "\n", "> \u26a1 **TIP:** In case you obtain an error during the upload, read the output in the MESSAGES section carefully and you will likely be able to have a rough idea of what went wrong. The most common causes of problems are syntax errors in your code, a mismatching board version on the Arduino IDE, or a wrongly selected port, so please review your code and try to identify any typos or mismatching\n", "characters.\n", "\n", "> \u26a1 **`exec: \"python\": executable file not found in $PATH`:** If you get this error, resort to this discussion [https://stackoverflow.com/questions/60762378/exec-python-executable-file-not-found-in-path](https://stackoverflow.com/questions/60762378/exec-python-executable-file-not-found-in-path)."]}, {"cell_type": "markdown", "id": "adeaf43d", "metadata": {}, "source": ["**3.6\\.** Finally, press the RESET button to put your ScientISST SENSE development board on Execution mode and have it run the uploaded code.\n", "
\n", "
"]}, {"cell_type": "markdown", "id": "e5d91d20", "metadata": {}, "source": ["#
4. Testing your Setup
"]}, {"cell_type": "markdown", "id": "506e1d22", "metadata": {}, "source": ["To test your setup, follow the steps from Section II.3.4 to II.3.6 (above) and upload the Blink sketch, one of the built-in examples of the Arduino IDE that can be loaded from `File > Examples > 01.Basics > Blink`:\n", "\n", "\n", "

\n", " \n", "

\n", "

Figure 14: Arduino IDE - How to open a Blink sketch.

\n", "\n", "> \u2757 **DON'T FORGET:** Don't forget to replace the ```LED_BUILTIN``` in the Blink sketch with the number of the pin connected to the white LED (GPIO 22).\n", "\n", "Upon successful completion of the process, the white LED on the front of the board should be on for one second, then off for one second, repeatedly."]}, {"cell_type": "markdown", "id": "23876435", "metadata": {}, "source": ["#
5. Explore
\n"]}, {"cell_type": "markdown", "id": "3b8e7bbb", "metadata": {}, "source": ["##
5.1. Final Notes
\n", "\n", "After following this tutorial, you should now be capable of writing, compiling, programing and executing your own code on the ScientISST SENSE development board through the Arduino IDE. We hope you find this hardware platform useful in the development of future projects and applications!\n", "\n", "As a final note, we leave here some words of **caution** to avoid damaging the board:\n", "\n", "> \u26a0\ufe0f **WARNING - NEVER:** \n", "> * Connect the voltage pins (e.g. the 3.3V pin) to another (external) voltage source, regardless of its type. \n", "> * Connect the voltage pins to the GND. \n", "> * Leave unconnected or \u201clive\u201d wires floating around your board, as they can inadvertently create short circuits between components\n", "> * Bend, twist, cut, score, apply weight or otherwise perform any mechanical abuse to your board; it is fragile! \n", "\n", " \n", "> \u26a0\ufe0f **WARNING - ALWAYS:** \n", "> * Think and study the problem carefully to reach a convincing solution that can achieve the goals your are trying to fulfill, before taking action.\n", "> * Have your board disconnected from the computer while assembling your circuits. "]}, {"cell_type": "markdown", "id": "89cdc85e", "metadata": {}, "source": ["##
5.2. Further Reading
"]}, {"cell_type": "markdown", "id": "a77796a7", "metadata": {}, "source": [" 1\\. https://www.arduino.cc/en/software\n", "\n", " 2\\. https://www.arduino.cc/en/Guide/Environment\n", "\n", " 3\\. https://dl.espressif.com/dl/package_esp32_index.json\n", "\n", " 4\\. https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers"]}, {"cell_type": "markdown", "id": "b43198d5", "metadata": {}, "source": ["***"]}, {"cell_type": "markdown", "id": "7f78cd41", "metadata": {}, "source": ["![scientisst-notebooks_bottom-banner](https://raw.githubusercontent.com/scientisst/notebooks/master/_Resources/bottom-banner.png)"]}], "metadata": {"kernelspec": {"display_name": "Python 3.10.0 64-bit", "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.10.0"}, "vscode": {"interpreter": {"hash": "7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad"}}}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/A.Setting up Your Tools and Workspace/A008 Setup your Python workspace/A008 Setup your Python workspace.ipynb b/A.Setting up Your Tools and Workspace/A008 Setup your Python workspace/A008 Setup your Python workspace.ipynb index c66f569..683d346 100644 --- a/A.Setting up Your Tools and Workspace/A008 Setup your Python workspace/A008 Setup your Python workspace.ipynb +++ b/A.Setting up Your Tools and Workspace/A008 Setup your Python workspace/A008 Setup your Python workspace.ipynb @@ -1,2377 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Introdução à Engenharia Biomédica (P4 - 2021/2022)\n", - "# Aula Prática #1 - Introdução ao Python\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Setup your Python workspace " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Keywords \n", - "\n", - "`Programming`, `Python`, `Anaconda`, `Data Visualization`, `Data Structures`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributor(s):** Rafael Silva, Hugo Plácido da Silva and Ana Fred\n", - "\n", - "**Date of creation:** 04/10/2020\n", - "\n", - "**Last update:** 12/05/2022" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " Notebooks are organized by cells or blocks that can contain text or code, which can be edited by double-clicking them (try filling in your data below). To execute a cell, you can click the Run button (above) or press CTRL+ENTER. To execute the current cell and move to the next, press SHIFT+ENTER. Familiarize yourself with the notebook operations in the toolbar above.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# I. Overview\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Introduction
\n", - "\n", - "Programming is the way we can communicate with computers, giving them instructions on what operations they should perform to achieve a specific goal. Nowadays, programming is an essential skill for scientists and engineers because it allows them to solve problems. Problem solving involves (i) formulating the problem, (ii) thinking of an approach to solve it, and (iii) reporting the results, which can all be done with programming. Programming can be used for many purposes, such as creating websites, configuring hardware, developing computer applications and games, managing databases, running simulations, etc.\n", - "\n", - "In this class, you will get a first approach to what programming is, using one of the most popular and simple programming languages: **Python**." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Objectives
\n", - "Here's what you should learn by the end of this class:\n", - "* Understand what Python is, and the benefits of working in a Python environment;\n", - "* Learn key programming concepts and tasks;\n", - "* Perform simple arithmetic operations and create functions;\n", - "* Learn how to install a Python package and use its functions;" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# II. What is Python? How does it work?\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. High-level programming
\n", - "\n", - "**Python** is a high-level programming language, just like C, C++ and Java. This means that it does not communicate directly with the computer - something that is only possible with low-level languages. Instead, the *source code* (i.e., the high-level program) is first processed by an *interpreter* or by a *compiler*. These are responsible to convert the source code into *machine code*, written in binary language (0's and 1's). Python scripts are executed by an interpreter, which translates the program one statement (or instruction) at a time, making it easier to correct mistakes. Compilers, on the other hand, read the entire program and translate it into machine code, which is the case for languages such as C, C++ and Java.\n", - "\n", - "We can use interpreters in two ways: the interactive mode and the script mode. In the interactive mode we type a simple operation and the interpreter outputs the result. In the script mode we save the code in a file (.py for Python), called a script, and the interpreter executes it.\n", - "\n", - "Python is distinguished by its simple and clean syntax. This is not only beneficial when it comes to readability, thus allowing the expense of program maintenance to be reduced, but also because it is an easy-to-learn programming language. In addition, it appears to be an increasingly attractive language for application and scripting development due to its open source nature. \n", - "\n", - "Comparatively to other languages, Python is particularly appealing for scientific computing. Alternatives include MATLAB, GNU Octave and R." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "To test the interactive mode, type `1+1` in the cell below, run it (`SHIFT+ENTER`) and see the result:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Python Interfaces
\n", - "\n", - "The interactive mode can be used to perform simple operations. However, for more complex tasks, the script mode is preferred. This can be done using *Integrated Development Environments* (IDEs), where we can create a script, such as:\n", - "* [Visual Studio Code](https://code.visualstudio.com/)\n", - "* [PyCharm](https://www.jetbrains.com/pycharm/)\n", - "* [Spyder](https://www.spyder-ide.org/)\n", - "\n", - "However, the large number of development environment options, and diversity of useful packages is often overwhelming, which has lead to the creation of pre-configured distributions targeted at simplifying the initial package management and deployment. For instance, this notebook was written using the [Anaconda Distribution](https://www.anaconda.com/products/distribution), which has Jupyter Notebook as one of its programs. \n", - "\n", - "The **Anaconda Navigator** is a graphical interface to facilitate the management of Python packages and environments and allow easy access to useful developer applications. It has proven to be very useful since it provides thousands of science and machine learning packages through a central cloud-based repository. Furthermore, it presents multiple data management environments capable of being run separately without interfering with each other.\n", - "\n", - "\"anaconda-nav\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " Since we will be using Anaconda Navigator in our classes, it is recommended to install it in your computer.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
3. What is a program?
\n", - "\n", - "A *program* can be defined as a set of specific instructions to perform some task. Examples of programs include: creating a document file with some text, plotting a function, solving an equation, multiplying two matrices, applying a filter to an image, managing a database, ... the possibilities are endless! The rules and the way we define the structure (i.e., the syntax) of these tasks may differ between programming languages, however there are basic elements that are common:\n", - "* **Input**: get data from some source (e.g., a text file, a keyboard)\n", - "* **Output**: the result of the program (e.g., a graph, a file containing results, a vector describing a feature)\n", - "* **Mathematical operations**: performing mathematical operations (e.g., addition, multiplication, logarithm calculation)\n", - "* **Looping**: repeating an action (e.g., reading a document line by line)\n", - "* **Conditionals**: check a condition (e.g., check if a value is an integer)\n", - "* **Variables and data structures**: store information (e.g., an array containing a signal)\n", - "\n", - "To illustrate, let's create a simple program that displays \"Hello, World!\". Note that we use the *print* function to instruct the intepreter to display our phrase on the screen which is enclosed in parentheses. In addition, we have to delimit the characters with quotation marks (single `'` or double `\"`)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print('Hello, World!')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# III. Python Basics\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Values and types
\n", - "\n", - "A *value* is the basic unit of data that a program works with, like a letter, a word or a number. Examples of values are `10`, `5.2` and `'Hello, World!'`. Values can be classified into different *types*, which will influence how programs interact with them. For example:\n", - "\n", - "* `'a'`, `'Hello, World!'` and `'100'` are *strings* (str), because they are made of alphanumeric characters enclosed by quotation marks;\n", - "\n", - "* `0` and `10` are *integers* (int);\n", - "\n", - "* `10.0` and `25.3` are *floats* (flt), because they are numbers with a decimal point (floating-point representation);\n", - "\n", - "* `True` and `False` are booleans (bool), and are used to evaluate logical operations.\n", - "\n", - "To check what is the value's type you can call `type( )`, with the value inside the parenthesis." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type('Biomedical Engineering')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type(123)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type('123')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type(3.14)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "type(True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also check what is the length of strings and other data types by using the function `len( )`. Integers, floats and booleans have no length." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "len('Biomedical Engineering')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "len(123)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Additionally, we can access each character or element by index using squared brackets `[ index ]`. Note that this is only possible for some data objets, called *subscriptable*, like strings, lists and dictionaries (we will cover them in section IV).\n", - "\n", - "In Python, indexing starts with `0`, and `-1` refers to the last element:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "'Hello'[0]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "'Hello'[4]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "'Hello'[-1]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " Try to check which value types have a defined length in Python, and which are subscriptable. You can add a code cell below by pressing the + symbol in the toolbar. \n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Operators
\n", - "\n", - "Operators are symbols that represent computations and can only be performed with values of the same type. The basic *arithmetic operators* in Python are:\n", - "\n", - "* Addition: `+`\n", - "\n", - "* Subtraction: `-`\n", - "\n", - "* Multiplication: `*`\n", - "\n", - "* Division: `/`\n", - "\n", - "* Exponentiation: `**`\n", - "\n", - "Let's see some examples:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "20+5" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "90/60" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "'Hello'+' World!'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that with string values, the '+' operation results in joining both strings, which is called *concatenation*. \n", - "\n", - "And what if we try an operation with two different value types?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1+'Hello'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get an error message. In this case it is a TypeError indicating that is not possible to add an integer and a string together." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are also *comparison operators* that return logical values (True or False):\n", - "\n", - "* Less than: `<` \n", - "* Less than or equal to: `<=`\n", - "* Greater than: `>` \n", - "* Greater than or equal to: `>=`\n", - "* Equal to: `==`\n", - "* Not equal to: `!=`\n", - "\n", - "Some examples:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1<10" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "'Python' == 'Python'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "'10' == 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another important set of operators are the *logical operators*:\n", - "\n", - "* `and`: True if both statements are true;\n", - "\n", - "* `or`: True if at least one statement is true;\n", - "\n", - "* `not`: True if the statement is false." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1==1 and 2<3" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1==10 or 2<3" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "not 1==2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " Try to perform basic computations with arithmetic, comparison and logical operators. You can add a code cell below by pressing the '+' symbol in the toolbar. \n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
3. Variables
\n", - "\n", - "One of the most useful features of a programming language is to work with variables. A variable is an object that refers to a value, allowing us to store information and make operations with. In Python, to create a variable, we don't need to declare it beforehand nor to define its type, it is created the moment we assign it to a value.\n", - "\n", - "A variable is identified by its name, which can contain letters (e.g., `var`), numbers (e.g., `var1`) and the underscore character (e.g., `var_1`). However, remember that it must begin with a letter, it can't have spaces, and it is case sensitive.\n", - "\n", - "Let's create two variables `x` and `y` and assign them values:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = 2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "y = 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that there is no output, since we are simply making a *variable assignment*. We can now make operations with these variables:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(y/x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Or even create a new variable using a combination of other variables and values:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "z = x + y/2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(z)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Variables can also be updated (i.e., change its value):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = 5" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using *casting*, it is possible to specifiy the value type of a variable:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a = int(2)\n", - "print(a)\n", - "print(type(a))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "b = str(2)\n", - "print(b)\n", - "print(type(b))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c = float(2)\n", - "print(c)\n", - "print(type(c))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Variables can be removed from memory using the keyword **del**:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "del c" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " Note that we can write multiple lines of code in each cell, where each line corresponds to a new expression or statement. In Python, we can simply press Enter to start a new line of code. The output of the statements will follow the same order.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Warning!
\n", - "
\n", - " Some names are exclusive of Python keywords, which cannot be used to name variables. Examples of such keywords include: class, True, False, None, and, or, not, if, else, with, while, for, return, from, import, is, continue, break . You can access the whole list by typing: import keyword; keyword.kwlist\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "1. Create a variable named `first`, assigning the value `'Hello'` to it. Then, create the variable `second` with value `'Python'`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Using the variables `first` and `second`, previously defined, create an operation that allows you to print the phrase \"Hello Python!\" (space and exclamation point included)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
4. Comments
\n", - "\n", - "When writing a program, and especially if it gets big and complex, it is useful to write notes or comments that allows anyone to read and understand what the different steps of the program do. In Python, comments start by the `#` symbol, and the interpreter ignores what comes right after." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# This is a comment\n", - "print('Hello, World!')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print('Hello, World!') # This is a comment" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Comments can also be used to clarify the meaning of variables, which can be very useful:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "d = 100 # distance in meters\n", - "t = 20 # time in seconds\n", - "\n", - "# Compute velocity\n", - "v = d/t # velocity in meters per second\n", - "print(v)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Warning!
\n", - "
\n", - " Comments should be short and straight to the point. They should not state obvious operations or be redundant. Also, when explaining the meaning of your variables, try to compromise between an explicit variable name and its length. Check this article.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here are some examples of comment practices that **should be avoided**:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print('Hello') # prints Hello" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "d = 100 # assign 100 to d" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# count variable\n", - "count = 0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Compute and print velocity\n", - "v = d/t # compute velocity, defined as the quotient between the displacement d and the elapsed time t\n", - "print(v) # prints the velocity in the console" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
5. Functions
\n", - "\n", - "\"function_calls\"\n", - "\n", - "

Reference: Runestone Academy

\n", - "\n", - "When writing a program, we can define *functions* to perform a whole sequence of operations, and return a result when called. This helps us to better manage and organize our program in its different steps. Note that functions can receive more than one input (called arguments). To create a function in Python, we need to follow this structure:\n", - "\n", - "\n", - "```python\n", - "def MY_FUNCTION(a, b, c):\n", - " # do something\n", - " \n", - " return # return something\n", - "```\n", - "\n", - "The different elements are:\n", - "* `def`: to declare we are creating a function\n", - "\n", - "* `MY_FUNCTION`: to give our function a name\n", - "\n", - "* `(a, b, c)`: to provide the list of desired inputs (also called *arguments*), which are separated by commas\n", - "\n", - "* `# do something`: to define what operations are made with the arguments\n", - "\n", - "* `return`: to declare the output of the function\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " Normally the programming environment will automatically stylize the text (color, bold, italic, ...) to make it easier to read. Also note that in Python we need to be very careful with the spaces at the beggining of a code line, which is called indentation. \n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's try creating a function called `mean` that receives two numbers `x` and `y`(the input) and returns their arithmetic mean (the output)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def mean(x, y):\n", - " \n", - " return (x+y)/2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can test this function by using two numbers of our choice by replacing `x` and `y`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(mean(10, 20))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "Try to create a function called ```temp_in_F``` that receives a temperature in Celsius and returns the temperature in Fahrenheit, according to the following formula:\n", - "\n", - "$$\n", - "T_F = \\frac{9}{5}\\times T_c + 32\n", - "$$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check if $150ºC$ corresponds to $302ºF$:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(temp_in_F(150))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# IV. Python Data Structures: Lists and Dictionaries\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python has 4 built-in data types to store collections of data: *lists*, *dictionaries*, *tuples* and *sets*. In this notebook we will cover the main features of lists and dictionaries." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Lists
\n", - "\n", - "Lists are data structures that can have multiple elements inside. They are created by placing its elements between squared brackets `[ ]` separated by commas. Lists are very versatile because they can contain any kind of object inside, like strings, floats, and other lists. \n", - "\n", - "Note that **list** is a Python built-in type, and should not be used as a variable name." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_a = [] # empty list\n", - "print(list_a)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_b = [1, 2, 3]\n", - "print(list_b)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Like strings, we can concatenate lists with the `+` operator, check their length with `len( )`, and access its items by index using squared brackets:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_c = [4, 5, 6]\n", - "list_d = list_b + list_c\n", - "print(list_d)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "len(list_d)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_d[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is also possible to access a section of the list by using the notation `[i:j]`, where we select the items from index $i$ (inclusive) to $j$ (exclusive). See some of the examples below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_d[0:4] # select the first 4 elements (indexes 0, 1, 2 and 3)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_d[0:1] # select the 1st element" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_d[1:1]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_d[0:len(list_d)] " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_d[1:] " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lists can contain other value types, and they can also be heterogenous:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "f = ['a', 'b', 'c']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "g = [1,2,'a'] # it contains int and str values" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "h = f + g\n", - "h" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "i = [1,[1, 2], 'hello'] # there is a list inside a list\n", - "i" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "i[1]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lists have several methods that we can work with. Some examples are:\n", - "\n", - "* `append()`\n", - "\n", - "* `insert()`\n", - "\n", - "* `remove()`\n", - "\n", - "* `pop()`\n", - "\n", - "* `sort()`\n", - "\n", - "* `copy()`\n", - "\n", - "To use them, we use the dot notation:\n", - "\n", - "```python\n", - "list_name.method_name(arguments)\n", - "```\n", - "\n", - "To check which methods are available when writing code, you can press **Tab** after typing dot `.`. Another option is to type: \n", - "\n", - "```python\n", - "dir(list)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_1 = [20, 10, 15, 5, 1]\n", - "list_1.sort()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " To find more about lists and associated methods consult Python's here. Alternatively, check Programiz's page on Python lists here.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Dictionaries
\n", - "\n", - "*Dictionaries* are another python datatype that can be very useful. Unlike lists, they are not defined by number indexes. Instead, dictionaries are indexed by keys (i.e., a label), with a value inside. They are written with curly brackets `{ }` and their elements follow the format `key: value`, separated by commas." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_a = {} # empty dictionary\n", - "dict_a" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b = {'key_1': 123, 'key_2': 'hello', 'key_3': [1,2,3]}\n", - "dict_b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We cannot access a dictionary's items by index. To access a key and view its contents, we can use squared brackets with the key string inside `[key]`, or call the method `.get( )`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b['key_1']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b.get('key_3')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b[0] # doesn't work" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To update a dictionary, we simply have to redefine its key:value pair and, if there is no matching key, the pair is added to the dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b['key_1'] = 'Python' # rewrite a value\n", - "dict_b" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict_b['key_4'] = [4, 5, 6] # add a new key with a value\n", - "dict_b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Some dictionary methods include:\n", - "\n", - "* `clear()`\n", - "\n", - "* `get(key)`\n", - "\n", - "* `pop(key)`\n", - "\n", - "* `update([other])`\n", - "\n", - "* `keys()`\n", - "\n", - "* `values()`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " To find more about dictionaries and its methods consult Python's documentation here and here. Alternatively, check Programiz's page on Python programming.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "\n", - "1. Create a dictionary called `my_dict` with the keys 'Name', 'Age', 'IST_ID' and 'Course' and add the corresponding values with your data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Without creating a new dictionary, delete the key 'Name' and add the keys 'First Name' and 'Last Name', associating the corresponding values.\n", - "*Hint: check the pop(key) method*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# V. Python Flow Control\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One of the most important tools to build complex programs is to control what the program does in specific scenarios. There are two main types of flow control: *conditional* and *loops*." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Conditional Statements
\n", - "\n", - "Conditional statements allows to define what part of the code to run based on whether a conditional statement is met or not. This is made using the **if**, **elif** and **else** statements. Let's start by the simplest form of conditional statement using an **if** statement:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```java\n", - "if expression:\n", - " statement\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "run = True # our variable\n", - "\n", - "if run == True: # if statement\n", - " print('Run!')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Because the condition `run==True` is met, the statements below it and **indented accordingly** are executed, and the console prints the sentence. If this were not the case, the interpreter would not execute any of the statements associated with the condition:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "run = False\n", - "\n", - "if run == True:\n", - " print('Run!')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The condition can be any expression that evaluates a boolean (check section III.2 - operators), and multiple statements can be made:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a = 0\n", - "b = 10\n", - "\n", - "if b > a:\n", - " c = True\n", - "\n", - "if b < a:\n", - " c = False" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "print(c) # since b>a, c equals True" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With the **else** keyword we can define what will happen if the condition is not met:\n", - "\n", - "```python\n", - "if expression:\n", - " # do something\n", - "else:\n", - " # do something else\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "run = False\n", - "\n", - "if run: # since run is a boolean, we can use it as the condition\n", - " print('Run!')\n", - "else:\n", - " print(\"Don't run!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we have multiple conditional statements to check sequentially, we can use the **elif** keyword:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "age = 20\n", - "\n", - "if age < 3:\n", - " print(\"Baby\")\n", - "elif age < 12:\n", - " print(\"Child\")\n", - "elif age < 19:\n", - " print(\"Teenager\")\n", - "elif age < 64:\n", - " print(\"Adult\")\n", - "else:\n", - " print(\"Senior\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The same could be done with multiple **if** statements and the **and** operator in the condition. However, in this case, the conditional statements are independent, which should be avoidable:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "age = 20\n", - "\n", - "if age < 3:\n", - " print(\"Baby\")\n", - "if age >= 3 and age < 12:\n", - " print(\"Child\")\n", - "if age >= 12 and age < 19:\n", - " print(\"Teenager\")\n", - "if age >= 19 and age < 64:\n", - " print(\"Adult\")\n", - "if age >= 64:\n", - " print(\"Senior\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "\n", - "1. Create an if-else statement that takes the variable `grade` and checks if it's smaller or greater than 9.5. It should print 'Pass' ($\\geq9.5$) or 'Fail' ($<9.5$). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grade = 8.3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Create a function that takes two integers and prints the highest value. Test it with your own examples." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Loops
\n", - "\n", - "To perform a sequence of repetitive operations by changing only a few parameters, python provides the *for* and *while* loops. For example, they can be used to perform the same processing steps for different files or variables.\n", - "\n", - "###
2.1. For Loop
\n", - "\n", - "The *for* loop is used to iterate over a sequence (for example, a list, a dictionary, a string) and to repeat its statements a precise number of times. Remember that indentation is key! The *for* loops follow the following structure:\n", - "\n", - "```python\n", - "for var in sequence:\n", - " # do something with var\n", - "```\n", - "\n", - "where `var` is a local variable that we especially assign for the loop. Common local variable names are `i, j, k`. \n", - "\n", - "Let's see some examples:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "list_files = ['file_1.txt', 'file_2.csv', 'file_3.txt', 'file_4.csv', 'file_5.png']\n", - "\n", - "for i in list_files:\n", - " print(i)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, the variable `i` takes one of the values of the sequence at a time, and it is printed to the console. Another useful method to use with the *for* loop is the *range* method, for when we wish the variable to take the index of the sequence values, and not the values themselves, or to simply work with a sequence of ordered integer values. For the previous example, we could work with the index of the items of the list:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i in range(len(list_files)):\n", - " print(i)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " To see how the range method works, try typing help(range). The help() method can be used to get information about the functions. An alternative is to search for it on the Internet.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A practical example would be to search for the '.txt' files only, and output their indexes on the list:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "txt_index = [] # empty list\n", - "\n", - "for i in range(len(list_files)): \n", - " \n", - " file_name = list_files[i] # corresponds to the value on the list\n", - " \n", - " if file_name[-4:]=='.txt': # verify if the last 4 characters of the string are .txt\n", - " txt_index.append(i) # adds the index to the empty list\n", - "\n", - "print(txt_index) # files with indexes 0 and 2 have the .txt file extension" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that the empty list `txt_index` is outside of the loop. Why?\n", - "\n", - "Then we could recover the filenames later:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i in txt_index:\n", - " print(list_files[i])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another useful strategy is to update a variable inside the *for* loop. For example, to sum the elements of a list, we can initialize a variable with the value 0 and update its value as the list is being read." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "numbers = [1, 2, 3, 4]\n", - "\n", - "sum_numbers = 0 # initialize sum variable\n", - "\n", - "for i in numbers:\n", - " \n", - " sum_numbers = sum_numbers + i # takes the previous saved variable and adds the new item\n", - " \n", - " print(f'sum = {sum_numbers}, i = {i}') # print the variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sum_numbers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "\n", - "1. Create a *for* loop that prints the square of the items of the list `numbers`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. On the previous example to search for the '.txt' files, we checked the file extension by the 4 last characters. How could this be a problem? Try to search for the '.csv' files usig the method .split() instead.\n", - "*Note: search for the split method documentation here or here, or type `help(str.split)`.*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###
2.2. While Loop
\n", - "\n", - "*While* loops are useful for when we want to repeat its statements as long as a condition is met (i.e., when we don't know the exact number of times to repeat). Their structure is as follows:\n", - "\n", - "```python\n", - "while condition:\n", - " # keep doing this until the condition is not true\n", - "```\n", - "\n", - "Let's see one example of a *while* loop that prints integer values that are smaller than 6 (starting from 0):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "i = 0 # count variable\n", - "\n", - "while i < 6:\n", - " print(i)\n", - " i = i + 1 # i gets updated each iteration by i+1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This loop prints the count variable `i` as long as it is smaller than 6. When it takes the value 6, the condition `i<6` is false and the *while* loop stops." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Warning!
\n", - "
\n", - "Be careful with while loops: if the condition is always True, the loop will not stop! To force the interpreter to stop running press the 'interrupt the kernel' button in Jupyter Notebook or CTRL+C in the console/IDE.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "\n", - "1. Create a *while* loop that prints each item of the `list_files` until the 4th file. \n", - "\n", - "*Don't forget to update the condition variable!*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Create a *while* loop that prints the number of elements of `list_files` that are before the `'file_4.csv'`.\n", - "\n", - "*Hint: use the != operator*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "
\n", - " Explore
\n", - "
\n", - " The continue, pass and break keywords can be used in loops to control its functioning. Check the python documentation here.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# VI. Python Libraries and Packages\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Although Python offers a wide variety of features and data structures (called Python Standard Library), most projects can benefit from sources of supplementary functions and methods. Libraries and packages can be made available to everyone, and are often useful for specific applications and projects, such as complex numerical computations, data analysis and plotting, scientific computing, machine learning, web development, and others.\n", - "\n", - "Two important concepts are package and module: a *module* is a .py file that contains the actual written functions and methods designed for a specific application, and a *package* is a collection of modules. This kind of structuring of a library can be particularly useful when applications become large and complex.\n", - "\n", - "\n", - "\n", - "\n", - "

Reference: Real Python

" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. How to install a package
\n", - "\n", - "Packages are a very practical tool for numerous purposes. In order to install them, two main options can be used.\t\n", - "\n", - "* **Python Package Index (PyPI)**\n", - "\n", - "PyPI is a repository of software for the Python programming language. It enables an easy access to packages shared by the Python Community. Installing a package only takes writing:\n", - "\n", - "```python\n", - "!pip install package_name\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "* **Anaconda Navigator**\n", - "\n", - "The Anaconda Navigator **Environments** tab has the list of every installed and uninstalled package plus it is possible to install them, as ilustrated:\n", - "\n", - "\n", - "\n", - "\"Install-packages\"\n", - "\n", - "\n", - "An alternative is to type in the console: \n", - "```python \n", - "conda install package_name\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. How to import and use a package
\n", - "\n", - "Even after installing a library, we still need to import the package or module into our Python environment. To do this, we use the keyword **import**:\n", - "\n", - "```python\n", - "import module_name\n", - "```\n", - "\n", - "Here we exemplify package import with the math *module*, which is always available in Python and gives access to several mathematical functions and numbers (e.g, the numbers $\\pi$ and $e$, the logarithm function)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "math" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import math" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To have access to the module's objects we can use the `dir( )` method:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(dir(math), end=' ')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now use it's functionalities using the dot notation (`module_name.object_name`):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(math.pi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, calling *pi* will not work:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(pi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To import an object from a module and avoid using the dot notation, we can use the keywords **from** and **import**:\n", - "```python\n", - "from module_name import object_name\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from math import pi\n", - "print(pi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are objects that are functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "value = 100\n", - "base = 10\n", - "value_log = math.log(value, base) # compute the logarithm\n", - "print(value_log)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To import all objects, we use `*`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from math import *\n", - "print(e)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is also possible to give a short-name to a package or module by using the keywords **import** and **as**:\n", - "\n", - "```python\n", - "import module_name as mod # to import the module with an alternative name\n", - "\n", - "mod.object # to call the object inside the module\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import math as m\n", - "m.pi" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Caution!
\n", - "
\n", - " When using different packages and modules, be careful about objects that may be imported with the same name. Because of such conflicts, it is advised to use dot notation to call the objects, along with a simplified module name. \n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Packages often contain multiple modules with different functionalities. In this case, the different modules can be accessed by using dot notation:\n", - "\n", - "```python\n", - "import package_name # imports all modules, need to use dot notation to call objects\n", - "\n", - "import package_name.module_name # imports one module, need to use dot notation to call objects\n", - "\n", - "import package_name.module_name as short_name # imports a module with another name\n", - "\n", - "from package_name.module_name import object_name # avoids dot notation to call an object\n", - "\n", - "from package_name.module_name import * # avoids dot notation, imports all objects\n", - "\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
3. Scientific Computing Libraries
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###
3.1. NumPy
\n", - "\n", - "*NumPy* is an easy-to-use, efficient tool for scientific computing.\n", - "For instance, it offers:\n", - "* a **N-dimensional array** object;\n", - "\n", - "* sophisticated **mathematical functions**;\n", - "\n", - "* **linear algebra** and **random number** capabilities.\n", - "\n", - "Let's visualize some of its operations." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "np.array([[1,2,3],[4,5,6]])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.random.randint(100) # Everytime you run this code, a different integer up to, but not including, 100 will appear." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a = np.arange(12).reshape(3,4) # Creates a 3x4 array with the numbers from 1 to 11\n", - "b = a > 4\n", - "a, b, a[b] " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = [56, 7, 3, 89, 30, 61]\n", - "np.sort(x) # rearranges the list in ascending order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = np.arange (6)\n", - "print(x)\n", - "\n", - "x.reshape(2,3) # reshapes the array, receiving as arguments (line, column)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " To learn more about NumPy funtionalities, visit NumPy.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###
3.2. Matplotlib
\n", - "\n", - "*Matplotlib* is a comprehensive library broadly used for producing **static, animated and interactive representations** in Python including plots, histograms, bar charts, etc.. It can be used in various environments, such as Python scripts, the Python and IPython shells and the Jupyter notebook.\n", - "\n", - "To properly utilize this library, here are some key steps to get started." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import matplotlib.patches as mpatches\n", - "import numpy as np\n", - "\n", - "t = np.arange(0.0, 2*np.pi, 0.01) # timeline we want to plot\n", - "\n", - "plt.grid(True) \n", - "\n", - "plt.title('Plot Example') \n", - "plt.xlabel('Time (s)')\n", - "plt.ylabel('Amplitude')\n", - "\n", - "plt.xlim([0, 2*np.pi])\n", - "plt.ylim([-1-0.1, 1+0.1])\n", - "\n", - "plt.plot(t, np.sin(t), label='Sine', color=\"#00bfc2\") \n", - "\n", - "plt.plot(t, np.cos(t), label='Cosine', color=\"#5756d6\") \n", - "plt.legend()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Age = ['0-25','25-50','+50']\n", - "Data =[10, 23, 16]\n", - "\n", - "plt.suptitle('Bar chart and plot example') \n", - "\n", - "plt.figure(figsize=(20, 4))\n", - "plt.subplot(131)\n", - "plt.bar(Age, Data,color=\"#00bfc2\")\n", - "plt.xlabel('Age group')\n", - "plt.ylabel('Number of individuals')\n", - "\n", - "\n", - "plt.subplot(132)\n", - "plt.plot(Age,Data,color=\"#5756d6\")\n", - "plt.xlabel('Age group')\n", - "plt.ylabel('Number of individuals')\n", - "plt.show" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " To learn more about Matplotlib funtionalities, visit Matplotlib.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###
3.3. Pandas
\n", - "\n", - "*Pandas* is a package designed to work with **tabular data**, namely data stored in spreadsheets and databases. It allows, for instance, the manipulation of rows and columns by selecting/modifying/eliminating specific data. \n", - "\n", - "Here's some examples of how it works." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd \n", - "\n", - "data = [['Tom', 20], ['Jack', 30], ['Meera', 25]]\n", - "\n", - "df = pd.DataFrame(data, columns = ['Name', 'Age'])\n", - "\n", - "print(df)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(df[df.Age > 20])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "
\n", - " Explore
\n", - "
\n", - " To learn more about Pandas funtionalities, visit Pandas.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# References\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "* A. Downey, [*Think Python*](https://www.greenteapress.com/thinkpython/thinkpython.pdf). *How to Think Like a Computer Scientist*, 2nd ed. Needham, Massachusetts: Green Tea Press, 2014.\n", - "* https://runestone.academy/\n", - "* https://www.scaler.com/\n", - "* https://www.math.tecnico.ulisboa.pt/~ccal/python/" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Where to learn Python?
\n", - "\n", - "* [Real Python](https://realpython.com/)\n", - "\n", - "* [Codecademy](https://www.codecademy.com)\n", - "\n", - "* [Programiz](https://www.programiz.com/)\n", - "\n", - "* [W3Schools](https://www.w3schools.com/)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
2. Further Reading
\n", - "\n", - "* A. Downey, [*Think Python*](https://www.greenteapress.com/thinkpython/thinkpython.pdf). *How to Think Like a Computer Scientist*, 2nd ed. Needham, Massachusetts: Green Tea Press, 2014." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - " \"Drawing\" \n", - "\n", - " \"Drawing\"\n", \n", - "" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["### Introdu\u00e7\u00e3o \u00e0 Engenharia Biom\u00e9dica (P4 - 2021/2022)\n", "# Aula Pr\u00e1tica #1 - Introdu\u00e7\u00e3o ao Python\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Setup your Python workspace "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Keywords \n", "\n", "`Programming`, `Python`, `Anaconda`, `Data Visualization`, `Data Structures`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Contributor(s):** Rafael Silva, Hugo Pl\u00e1cido da Silva and Ana Fred\n", "\n", "**Date of creation:** 04/10/2020\n", "\n", "**Last update:** 12/05/2022"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " Notebooks are organized by cells or blocks that can contain text or code, which can be edited by double-clicking them (try filling in your data below). To execute a cell, you can click the Run button (above) or press CTRL+ENTER. To execute the current cell and move to the next, press SHIFT+ENTER. Familiarize yourself with the notebook operations in the toolbar above.\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# I. Overview\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Introduction
\n", "\n", "Programming is the way we can communicate with computers, giving them instructions on what operations they should perform to achieve a specific goal. Nowadays, programming is an essential skill for scientists and engineers because it allows them to solve problems. Problem solving involves (i) formulating the problem, (ii) thinking of an approach to solve it, and (iii) reporting the results, which can all be done with programming. Programming can be used for many purposes, such as creating websites, configuring hardware, developing computer applications and games, managing databases, running simulations, etc.\n", "\n", "In this class, you will get a first approach to what programming is, using one of the most popular and simple programming languages: **Python**."]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Objectives
\n", "Here's what you should learn by the end of this class:\n", "* Understand what Python is, and the benefits of working in a Python environment;\n", "* Learn key programming concepts and tasks;\n", "* Perform simple arithmetic operations and create functions;\n", "* Learn how to install a Python package and use its functions;"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# II. What is Python? How does it work?\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. High-level programming
\n", "\n", "**Python** is a high-level programming language, just like C, C++ and Java. This means that it does not communicate directly with the computer - something that is only possible with low-level languages. Instead, the *source code* (i.e., the high-level program) is first processed by an *interpreter* or by a *compiler*. These are responsible to convert the source code into *machine code*, written in binary language (0's and 1's). Python scripts are executed by an interpreter, which translates the program one statement (or instruction) at a time, making it easier to correct mistakes. Compilers, on the other hand, read the entire program and translate it into machine code, which is the case for languages such as C, C++ and Java.\n", "\n", "We can use interpreters in two ways: the interactive mode and the script mode. In the interactive mode we type a simple operation and the interpreter outputs the result. In the script mode we save the code in a file (.py for Python), called a script, and the interpreter executes it.\n", "\n", "Python is distinguished by its simple and clean syntax. This is not only beneficial when it comes to readability, thus allowing the expense of program maintenance to be reduced, but also because it is an easy-to-learn programming language. In addition, it appears to be an increasingly attractive language for application and scripting development due to its open source nature. \n", "\n", "Comparatively to other languages, Python is particularly appealing for scientific computing. Alternatives include MATLAB, GNU Octave and R."]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "To test the interactive mode, type `1+1` in the cell below, run it (`SHIFT+ENTER`) and see the result:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Python Interfaces
\n", "\n", "The interactive mode can be used to perform simple operations. However, for more complex tasks, the script mode is preferred. This can be done using *Integrated Development Environments* (IDEs), where we can create a script, such as:\n", "* [Visual Studio Code](https://code.visualstudio.com/)\n", "* [PyCharm](https://www.jetbrains.com/pycharm/)\n", "* [Spyder](https://www.spyder-ide.org/)\n", "\n", "However, the large number of development environment options, and diversity of useful packages is often overwhelming, which has lead to the creation of pre-configured distributions targeted at simplifying the initial package management and deployment. For instance, this notebook was written using the [Anaconda Distribution](https://www.anaconda.com/products/distribution), which has Jupyter Notebook as one of its programs. \n", "\n", "The **Anaconda Navigator** is a graphical interface to facilitate the management of Python packages and environments and allow easy access to useful developer applications. It has proven to be very useful since it provides thousands of science and machine learning packages through a central cloud-based repository. Furthermore, it presents multiple data management environments capable of being run separately without interfering with each other.\n", "\n", "\"anaconda-nav\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " Since we will be using Anaconda Navigator in our classes, it is recommended to install it in your computer.\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
3. What is a program?
\n", "\n", "A *program* can be defined as a set of specific instructions to perform some task. Examples of programs include: creating a document file with some text, plotting a function, solving an equation, multiplying two matrices, applying a filter to an image, managing a database, ... the possibilities are endless! The rules and the way we define the structure (i.e., the syntax) of these tasks may differ between programming languages, however there are basic elements that are common:\n", "* **Input**: get data from some source (e.g., a text file, a keyboard)\n", "* **Output**: the result of the program (e.g., a graph, a file containing results, a vector describing a feature)\n", "* **Mathematical operations**: performing mathematical operations (e.g., addition, multiplication, logarithm calculation)\n", "* **Looping**: repeating an action (e.g., reading a document line by line)\n", "* **Conditionals**: check a condition (e.g., check if a value is an integer)\n", "* **Variables and data structures**: store information (e.g., an array containing a signal)\n", "\n", "To illustrate, let's create a simple program that displays \"Hello, World!\". Note that we use the *print* function to instruct the intepreter to display our phrase on the screen which is enclosed in parentheses. In addition, we have to delimit the characters with quotation marks (single `'` or double `\"`)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print('Hello, World!')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# III. Python Basics\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Values and types
\n", "\n", "A *value* is the basic unit of data that a program works with, like a letter, a word or a number. Examples of values are `10`, `5.2` and `'Hello, World!'`. Values can be classified into different *types*, which will influence how programs interact with them. For example:\n", "\n", "* `'a'`, `'Hello, World!'` and `'100'` are *strings* (str), because they are made of alphanumeric characters enclosed by quotation marks;\n", "\n", "* `0` and `10` are *integers* (int);\n", "\n", "* `10.0` and `25.3` are *floats* (flt), because they are numbers with a decimal point (floating-point representation);\n", "\n", "* `True` and `False` are booleans (bool), and are used to evaluate logical operations.\n", "\n", "To check what is the value's type you can call `type( )`, with the value inside the parenthesis."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["type('Biomedical Engineering')"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["type(123)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["type('123')"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["type(3.14)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["type(True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can also check what is the length of strings and other data types by using the function `len( )`. Integers, floats and booleans have no length."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["len('Biomedical Engineering')"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["len(123)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Additionally, we can access each character or element by index using squared brackets `[ index ]`. Note that this is only possible for some data objets, called *subscriptable*, like strings, lists and dictionaries (we will cover them in section IV).\n", "\n", "In Python, indexing starts with `0`, and `-1` refers to the last element:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["'Hello'[0]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["'Hello'[4]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["'Hello'[-1]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " Try to check which value types have a defined length in Python, and which are subscriptable. You can add a code cell below by pressing the + symbol in the toolbar. \n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Operators
\n", "\n", "Operators are symbols that represent computations and can only be performed with values of the same type. The basic *arithmetic operators* in Python are:\n", "\n", "* Addition: `+`\n", "\n", "* Subtraction: `-`\n", "\n", "* Multiplication: `*`\n", "\n", "* Division: `/`\n", "\n", "* Exponentiation: `**`\n", "\n", "Let's see some examples:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["20+5"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["90/60"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["'Hello'+' World!'"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that with string values, the '+' operation results in joining both strings, which is called *concatenation*. \n", "\n", "And what if we try an operation with two different value types?"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["1+'Hello'"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We get an error message. In this case it is a TypeError indicating that is not possible to add an integer and a string together."]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are also *comparison operators* that return logical values (True or False):\n", "\n", "* Less than: `<` \n", "* Less than or equal to: `<=`\n", "* Greater than: `>` \n", "* Greater than or equal to: `>=`\n", "* Equal to: `==`\n", "* Not equal to: `!=`\n", "\n", "Some examples:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["1<10"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["'Python' == 'Python'"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["'10' == 10"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Another important set of operators are the *logical operators*:\n", "\n", "* `and`: True if both statements are true;\n", "\n", "* `or`: True if at least one statement is true;\n", "\n", "* `not`: True if the statement is false."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["1==1 and 2<3"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["1==10 or 2<3"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["not 1==2"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " Try to perform basic computations with arithmetic, comparison and logical operators. You can add a code cell below by pressing the '+' symbol in the toolbar. \n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
3. Variables
\n", "\n", "One of the most useful features of a programming language is to work with variables. A variable is an object that refers to a value, allowing us to store information and make operations with. In Python, to create a variable, we don't need to declare it beforehand nor to define its type, it is created the moment we assign it to a value.\n", "\n", "A variable is identified by its name, which can contain letters (e.g., `var`), numbers (e.g., `var1`) and the underscore character (e.g., `var_1`). However, remember that it must begin with a letter, it can't have spaces, and it is case sensitive.\n", "\n", "Let's create two variables `x` and `y` and assign them values:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x = 2"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["y = 10"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that there is no output, since we are simply making a *variable assignment*. We can now make operations with these variables:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(y/x)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Or even create a new variable using a combination of other variables and values:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["z = x + y/2"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(z)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Variables can also be updated (i.e., change its value):"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(x)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x = 5"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(x)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Using *casting*, it is possible to specifiy the value type of a variable:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = int(2)\n", "print(a)\n", "print(type(a))"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["b = str(2)\n", "print(b)\n", "print(type(b))"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["c = float(2)\n", "print(c)\n", "print(type(c))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Variables can be removed from memory using the keyword **del**:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["c"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["del c"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["c"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " Note that we can write multiple lines of code in each cell, where each line corresponds to a new expression or statement. In Python, we can simply press Enter to start a new line of code. The output of the statements will follow the same order.\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Warning!
\n", "
\n", " Some names are exclusive of Python keywords, which cannot be used to name variables. Examples of such keywords include: class, True, False, None, and, or, not, if, else, with, while, for, return, from, import, is, continue, break . You can access the whole list by typing: import keyword; keyword.kwlist\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "1. Create a variable named `first`, assigning the value `'Hello'` to it. Then, create the variable `second` with value `'Python'`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["2. Using the variables `first` and `second`, previously defined, create an operation that allows you to print the phrase \"Hello Python!\" (space and exclamation point included)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["#
4. Comments
\n", "\n", "When writing a program, and especially if it gets big and complex, it is useful to write notes or comments that allows anyone to read and understand what the different steps of the program do. In Python, comments start by the `#` symbol, and the interpreter ignores what comes right after."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["# This is a comment\n", "print('Hello, World!')"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print('Hello, World!') # This is a comment"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Comments can also be used to clarify the meaning of variables, which can be very useful:\n"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["d = 100 # distance in meters\n", "t = 20 # time in seconds\n", "\n", "# Compute velocity\n", "v = d/t # velocity in meters per second\n", "print(v)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Warning!
\n", "
\n", " Comments should be short and straight to the point. They should not state obvious operations or be redundant. Also, when explaining the meaning of your variables, try to compromise between an explicit variable name and its length. Check this article.\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Here are some examples of comment practices that **should be avoided**:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print('Hello') # prints Hello"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["d = 100 # assign 100 to d"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["# count variable\n", "count = 0"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["# Compute and print velocity\n", "v = d/t # compute velocity, defined as the quotient between the displacement d and the elapsed time t\n", "print(v) # prints the velocity in the console"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
5. Functions
\n", "\n", "\"function_calls\"\n", "\n", "

Reference: Runestone Academy

\n", "\n", "When writing a program, we can define *functions* to perform a whole sequence of operations, and return a result when called. This helps us to better manage and organize our program in its different steps. Note that functions can receive more than one input (called arguments). To create a function in Python, we need to follow this structure:\n", "\n", "\n", "```python\n", "def MY_FUNCTION(a, b, c):\n", " # do something\n", " \n", " return # return something\n", "```\n", "\n", "The different elements are:\n", "* `def`: to declare we are creating a function\n", "\n", "* `MY_FUNCTION`: to give our function a name\n", "\n", "* `(a, b, c)`: to provide the list of desired inputs (also called *arguments*), which are separated by commas\n", "\n", "* `# do something`: to define what operations are made with the arguments\n", "\n", "* `return`: to declare the output of the function\n", "\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " Normally the programming environment will automatically stylize the text (color, bold, italic, ...) to make it easier to read. Also note that in Python we need to be very careful with the spaces at the beggining of a code line, which is called indentation. \n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now let's try creating a function called `mean` that receives two numbers `x` and `y`(the input) and returns their arithmetic mean (the output)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def mean(x, y):\n", " \n", " return (x+y)/2"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can test this function by using two numbers of our choice by replacing `x` and `y`:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(mean(10, 20))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "Try to create a function called ```temp_in_F``` that receives a temperature in Celsius and returns the temperature in Fahrenheit, according to the following formula:\n", "\n", "$$\n", "T_F = \\frac{9}{5}\\times T_c + 32\n", "$$"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["Check if $150\u00baC$ corresponds to $302\u00baF$:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(temp_in_F(150))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# IV. Python Data Structures: Lists and Dictionaries\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Python has 4 built-in data types to store collections of data: *lists*, *dictionaries*, *tuples* and *sets*. In this notebook we will cover the main features of lists and dictionaries."]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Lists
\n", "\n", "Lists are data structures that can have multiple elements inside. They are created by placing its elements between squared brackets `[ ]` separated by commas. Lists are very versatile because they can contain any kind of object inside, like strings, floats, and other lists. \n", "\n", "Note that **list** is a Python built-in type, and should not be used as a variable name."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_a = [] # empty list\n", "print(list_a)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_b = [1, 2, 3]\n", "print(list_b)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Like strings, we can concatenate lists with the `+` operator, check their length with `len( )`, and access its items by index using squared brackets:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_c = [4, 5, 6]\n", "list_d = list_b + list_c\n", "print(list_d)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["len(list_d)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_d[0]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is also possible to access a section of the list by using the notation `[i:j]`, where we select the items from index $i$ (inclusive) to $j$ (exclusive). See some of the examples below:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_d[0:4] # select the first 4 elements (indexes 0, 1, 2 and 3)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_d[0:1] # select the 1st element"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_d[1:1]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_d[0:len(list_d)] "]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_d[1:] "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Lists can contain other value types, and they can also be heterogenous:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["f = ['a', 'b', 'c']"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["g = [1,2,'a'] # it contains int and str values"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["h = f + g\n", "h"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["i = [1,[1, 2], 'hello'] # there is a list inside a list\n", "i"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["i[1]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Lists have several methods that we can work with. Some examples are:\n", "\n", "* `append()`\n", "\n", "* `insert()`\n", "\n", "* `remove()`\n", "\n", "* `pop()`\n", "\n", "* `sort()`\n", "\n", "* `copy()`\n", "\n", "To use them, we use the dot notation:\n", "\n", "```python\n", "list_name.method_name(arguments)\n", "```\n", "\n", "To check which methods are available when writing code, you can press **Tab** after typing dot `.`. Another option is to type: \n", "\n", "```python\n", "dir(list)\n", "```"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_1 = [20, 10, 15, 5, 1]\n", "list_1.sort()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_1"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " To find more about lists and associated methods consult Python's here. Alternatively, check Programiz's page on Python lists here.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Dictionaries
\n", "\n", "*Dictionaries* are another python datatype that can be very useful. Unlike lists, they are not defined by number indexes. Instead, dictionaries are indexed by keys (i.e., a label), with a value inside. They are written with curly brackets `{ }` and their elements follow the format `key: value`, separated by commas."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_a = {} # empty dictionary\n", "dict_a"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b = {'key_1': 123, 'key_2': 'hello', 'key_3': [1,2,3]}\n", "dict_b"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We cannot access a dictionary's items by index. To access a key and view its contents, we can use squared brackets with the key string inside `[key]`, or call the method `.get( )`:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b['key_1']"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b.get('key_3')"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b[0] # doesn't work"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To update a dictionary, we simply have to redefine its key:value pair and, if there is no matching key, the pair is added to the dictionary:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b['key_1'] = 'Python' # rewrite a value\n", "dict_b"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["dict_b['key_4'] = [4, 5, 6] # add a new key with a value\n", "dict_b"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Some dictionary methods include:\n", "\n", "* `clear()`\n", "\n", "* `get(key)`\n", "\n", "* `pop(key)`\n", "\n", "* `update([other])`\n", "\n", "* `keys()`\n", "\n", "* `values()`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " To find more about dictionaries and its methods consult Python's documentation here and here. Alternatively, check Programiz's page on Python programming.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "\n", "1. Create a dictionary called `my_dict` with the keys 'Name', 'Age', 'IST_ID' and 'Course' and add the corresponding values with your data."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["2. Without creating a new dictionary, delete the key 'Name' and add the keys 'First Name' and 'Last Name', associating the corresponding values.\n", "*Hint: check the pop(key) method*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["# V. Python Flow Control\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["One of the most important tools to build complex programs is to control what the program does in specific scenarios. There are two main types of flow control: *conditional* and *loops*."]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Conditional Statements
\n", "\n", "Conditional statements allows to define what part of the code to run based on whether a conditional statement is met or not. This is made using the **if**, **elif** and **else** statements. Let's start by the simplest form of conditional statement using an **if** statement:"]}, {"cell_type": "markdown", "metadata": {}, "source": ["```java\n", "if expression:\n", " statement\n", "```"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["run = True # our variable\n", "\n", "if run == True: # if statement\n", " print('Run!')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Because the condition `run==True` is met, the statements below it and **indented accordingly** are executed, and the console prints the sentence. If this were not the case, the interpreter would not execute any of the statements associated with the condition:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["run = False\n", "\n", "if run == True:\n", " print('Run!')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The condition can be any expression that evaluates a boolean (check section III.2 - operators), and multiple statements can be made:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = 0\n", "b = 10\n", "\n", "if b > a:\n", " c = True\n", "\n", "if b < a:\n", " c = False"]}, {"cell_type": "code", "execution_count": null, "metadata": {"scrolled": true}, "outputs": [], "source": ["print(c) # since b>a, c equals True"]}, {"cell_type": "markdown", "metadata": {}, "source": ["With the **else** keyword we can define what will happen if the condition is not met:\n", "\n", "```python\n", "if expression:\n", " # do something\n", "else:\n", " # do something else\n", "```"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["run = False\n", "\n", "if run: # since run is a boolean, we can use it as the condition\n", " print('Run!')\n", "else:\n", " print(\"Don't run!\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["If we have multiple conditional statements to check sequentially, we can use the **elif** keyword:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["age = 20\n", "\n", "if age < 3:\n", " print(\"Baby\")\n", "elif age < 12:\n", " print(\"Child\")\n", "elif age < 19:\n", " print(\"Teenager\")\n", "elif age < 64:\n", " print(\"Adult\")\n", "else:\n", " print(\"Senior\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The same could be done with multiple **if** statements and the **and** operator in the condition. However, in this case, the conditional statements are independent, which should be avoidable:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["age = 20\n", "\n", "if age < 3:\n", " print(\"Baby\")\n", "if age >= 3 and age < 12:\n", " print(\"Child\")\n", "if age >= 12 and age < 19:\n", " print(\"Teenager\")\n", "if age >= 19 and age < 64:\n", " print(\"Adult\")\n", "if age >= 64:\n", " print(\"Senior\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "\n", "1. Create an if-else statement that takes the variable `grade` and checks if it's smaller or greater than 9.5. It should print 'Pass' ($\\geq9.5$) or 'Fail' ($<9.5$). "]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["grade = 8.3"]}, {"cell_type": "markdown", "metadata": {}, "source": ["2. Create a function that takes two integers and prints the highest value. Test it with your own examples."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Loops
\n", "\n", "To perform a sequence of repetitive operations by changing only a few parameters, python provides the *for* and *while* loops. For example, they can be used to perform the same processing steps for different files or variables.\n", "\n", "###
2.1. For Loop
\n", "\n", "The *for* loop is used to iterate over a sequence (for example, a list, a dictionary, a string) and to repeat its statements a precise number of times. Remember that indentation is key! The *for* loops follow the following structure:\n", "\n", "```python\n", "for var in sequence:\n", " # do something with var\n", "```\n", "\n", "where `var` is a local variable that we especially assign for the loop. Common local variable names are `i, j, k`. \n", "\n", "Let's see some examples:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["list_files = ['file_1.txt', 'file_2.csv', 'file_3.txt', 'file_4.csv', 'file_5.png']\n", "\n", "for i in list_files:\n", " print(i)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this case, the variable `i` takes one of the values of the sequence at a time, and it is printed to the console. Another useful method to use with the *for* loop is the *range* method, for when we wish the variable to take the index of the sequence values, and not the values themselves, or to simply work with a sequence of ordered integer values. For the previous example, we could work with the index of the items of the list:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["for i in range(len(list_files)):\n", " print(i)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " To see how the range method works, try typing help(range). The help() method can be used to get information about the functions. An alternative is to search for it on the Internet.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["A practical example would be to search for the '.txt' files only, and output their indexes on the list:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["txt_index = [] # empty list\n", "\n", "for i in range(len(list_files)): \n", " \n", " file_name = list_files[i] # corresponds to the value on the list\n", " \n", " if file_name[-4:]=='.txt': # verify if the last 4 characters of the string are .txt\n", " txt_index.append(i) # adds the index to the empty list\n", "\n", "print(txt_index) # files with indexes 0 and 2 have the .txt file extension"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Notice that the empty list `txt_index` is outside of the loop. Why?\n", "\n", "Then we could recover the filenames later:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["for i in txt_index:\n", " print(list_files[i])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Another useful strategy is to update a variable inside the *for* loop. For example, to sum the elements of a list, we can initialize a variable with the value 0 and update its value as the list is being read."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["numbers = [1, 2, 3, 4]\n", "\n", "sum_numbers = 0 # initialize sum variable\n", "\n", "for i in numbers:\n", " \n", " sum_numbers = sum_numbers + i # takes the previous saved variable and adds the new item\n", " \n", " print(f'sum = {sum_numbers}, i = {i}') # print the variables"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["sum_numbers"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "\n", "1. Create a *for* loop that prints the square of the items of the list `numbers`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["2. On the previous example to search for the '.txt' files, we checked the file extension by the 4 last characters. How could this be a problem? Try to search for the '.csv' files usig the method .split() instead.\n", "*Note: search for the split method documentation here or here, or type `help(str.split)`.*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["###
2.2. While Loop
\n", "\n", "*While* loops are useful for when we want to repeat its statements as long as a condition is met (i.e., when we don't know the exact number of times to repeat). Their structure is as follows:\n", "\n", "```python\n", "while condition:\n", " # keep doing this until the condition is not true\n", "```\n", "\n", "Let's see one example of a *while* loop that prints integer values that are smaller than 6 (starting from 0):"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["i = 0 # count variable\n", "\n", "while i < 6:\n", " print(i)\n", " i = i + 1 # i gets updated each iteration by i+1"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This loop prints the count variable `i` as long as it is smaller than 6. When it takes the value 6, the condition `i<6` is false and the *while* loop stops."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Warning!
\n", "
\n", "Be careful with while loops: if the condition is always True, the loop will not stop! To force the interpreter to stop running press the 'interrupt the kernel' button in Jupyter Notebook or CTRL+C in the console/IDE.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "\n", "1. Create a *while* loop that prints each item of the `list_files` until the 4th file. \n", "\n", "*Don't forget to update the condition variable!*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["2. Create a *while* loop that prints the number of elements of `list_files` that are before the `'file_4.csv'`.\n", "\n", "*Hint: use the != operator*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["\n", "
\n", " Explore
\n", "
\n", " The continue, pass and break keywords can be used in loops to control its functioning. Check the python documentation here.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# VI. Python Libraries and Packages\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Although Python offers a wide variety of features and data structures (called Python Standard Library), most projects can benefit from sources of supplementary functions and methods. Libraries and packages can be made available to everyone, and are often useful for specific applications and projects, such as complex numerical computations, data analysis and plotting, scientific computing, machine learning, web development, and others.\n", "\n", "Two important concepts are package and module: a *module* is a .py file that contains the actual written functions and methods designed for a specific application, and a *package* is a collection of modules. This kind of structuring of a library can be particularly useful when applications become large and complex.\n", "\n", "\n", "\n", "\n", "

Reference: Real Python

"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. How to install a package
\n", "\n", "Packages are a very practical tool for numerous purposes. In order to install them, two main options can be used.\t\n", "\n", "* **Python Package Index (PyPI)**\n", "\n", "PyPI is a repository of software for the Python programming language. It enables an easy access to packages shared by the Python Community. Installing a package only takes writing:\n", "\n", "```python\n", "!pip install package_name\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["* **Anaconda Navigator**\n", "\n", "The Anaconda Navigator **Environments** tab has the list of every installed and uninstalled package plus it is possible to install them, as ilustrated:\n", "\n", "\n", "\n", "\"Install-packages\"\n", "\n", "\n", "An alternative is to type in the console: \n", "```python \n", "conda install package_name\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. How to import and use a package
\n", "\n", "Even after installing a library, we still need to import the package or module into our Python environment. To do this, we use the keyword **import**:\n", "\n", "```python\n", "import module_name\n", "```\n", "\n", "Here we exemplify package import with the math *module*, which is always available in Python and gives access to several mathematical functions and numbers (e.g, the numbers $\\pi$ and $e$, the logarithm function)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["math"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import math"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To have access to the module's objects we can use the `dir( )` method:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(dir(math), end=' ')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can now use it's functionalities using the dot notation (`module_name.object_name`):"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(math.pi)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this case, calling *pi* will not work:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(pi)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To import an object from a module and avoid using the dot notation, we can use the keywords **from** and **import**:\n", "```python\n", "from module_name import object_name\n", "```"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from math import pi\n", "print(pi)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are objects that are functions:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["value = 100\n", "base = 10\n", "value_log = math.log(value, base) # compute the logarithm\n", "print(value_log)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To import all objects, we use `*`:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from math import *\n", "print(e)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is also possible to give a short-name to a package or module by using the keywords **import** and **as**:\n", "\n", "```python\n", "import module_name as mod # to import the module with an alternative name\n", "\n", "mod.object # to call the object inside the module\n", "```"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import math as m\n", "m.pi"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Caution!
\n", "
\n", " When using different packages and modules, be careful about objects that may be imported with the same name. Because of such conflicts, it is advised to use dot notation to call the objects, along with a simplified module name. \n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Packages often contain multiple modules with different functionalities. In this case, the different modules can be accessed by using dot notation:\n", "\n", "```python\n", "import package_name # imports all modules, need to use dot notation to call objects\n", "\n", "import package_name.module_name # imports one module, need to use dot notation to call objects\n", "\n", "import package_name.module_name as short_name # imports a module with another name\n", "\n", "from package_name.module_name import object_name # avoids dot notation to call an object\n", "\n", "from package_name.module_name import * # avoids dot notation, imports all objects\n", "\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
3. Scientific Computing Libraries
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["###
3.1. NumPy
\n", "\n", "*NumPy* is an easy-to-use, efficient tool for scientific computing.\n", "For instance, it offers:\n", "* a **N-dimensional array** object;\n", "\n", "* sophisticated **mathematical functions**;\n", "\n", "* **linear algebra** and **random number** capabilities.\n", "\n", "Let's visualize some of its operations."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "np.array([[1,2,3],[4,5,6]])"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["np.random.randint(100) # Everytime you run this code, a different integer up to, but not including, 100 will appear."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = np.arange(12).reshape(3,4) # Creates a 3x4 array with the numbers from 1 to 11\n", "b = a > 4\n", "a, b, a[b] "]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x = [56, 7, 3, 89, 30, 61]\n", "np.sort(x) # rearranges the list in ascending order"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x = np.arange (6)\n", "print(x)\n", "\n", "x.reshape(2,3) # reshapes the array, receiving as arguments (line, column)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " To learn more about NumPy funtionalities, visit NumPy.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["###
3.2. Matplotlib
\n", "\n", "*Matplotlib* is a comprehensive library broadly used for producing **static, animated and interactive representations** in Python including plots, histograms, bar charts, etc.. It can be used in various environments, such as Python scripts, the Python and IPython shells and the Jupyter notebook.\n", "\n", "To properly utilize this library, here are some key steps to get started."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import matplotlib.pyplot as plt\n", "import matplotlib.patches as mpatches\n", "import numpy as np\n", "\n", "t = np.arange(0.0, 2*np.pi, 0.01) # timeline we want to plot\n", "\n", "plt.grid(True) \n", "\n", "plt.title('Plot Example') \n", "plt.xlabel('Time (s)')\n", "plt.ylabel('Amplitude')\n", "\n", "plt.xlim([0, 2*np.pi])\n", "plt.ylim([-1-0.1, 1+0.1])\n", "\n", "plt.plot(t, np.sin(t), label='Sine', color=\"#00bfc2\") \n", "\n", "plt.plot(t, np.cos(t), label='Cosine', color=\"#5756d6\") \n", "plt.legend()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["Age = ['0-25','25-50','+50']\n", "Data =[10, 23, 16]\n", "\n", "plt.suptitle('Bar chart and plot example') \n", "\n", "plt.figure(figsize=(20, 4))\n", "plt.subplot(131)\n", "plt.bar(Age, Data,color=\"#00bfc2\")\n", "plt.xlabel('Age group')\n", "plt.ylabel('Number of individuals')\n", "\n", "\n", "plt.subplot(132)\n", "plt.plot(Age,Data,color=\"#5756d6\")\n", "plt.xlabel('Age group')\n", "plt.ylabel('Number of individuals')\n", "plt.show"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " To learn more about Matplotlib funtionalities, visit Matplotlib.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["###
3.3. Pandas
\n", "\n", "*Pandas* is a package designed to work with **tabular data**, namely data stored in spreadsheets and databases. It allows, for instance, the manipulation of rows and columns by selecting/modifying/eliminating specific data. \n", "\n", "Here's some examples of how it works."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import pandas as pd \n", "\n", "data = [['Tom', 20], ['Jack', 30], ['Meera', 25]]\n", "\n", "df = pd.DataFrame(data, columns = ['Name', 'Age'])\n", "\n", "print(df)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(df[df.Age > 20])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\n", "
\n", " Explore
\n", "
\n", " To learn more about Pandas funtionalities, visit Pandas.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# References\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["* A. Downey, [*Think Python*](https://www.greenteapress.com/thinkpython/thinkpython.pdf). *How to Think Like a Computer Scientist*, 2nd ed. Needham, Massachusetts: Green Tea Press, 2014.\n", "* https://runestone.academy/\n", "* https://www.scaler.com/\n", "* https://www.math.tecnico.ulisboa.pt/~ccal/python/"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Where to learn Python?
\n", "\n", "* [Real Python](https://realpython.com/)\n", "\n", "* [Codecademy](https://www.codecademy.com)\n", "\n", "* [Programiz](https://www.programiz.com/)\n", "\n", "* [W3Schools](https://www.w3schools.com/)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
2. Further Reading
\n", "\n", "* A. Downey, [*Think Python*](https://www.greenteapress.com/thinkpython/thinkpython.pdf). *How to Think Like a Computer Scientist*, 2nd ed. Needham, Massachusetts: Green Tea Press, 2014."]}, {"cell_type": "markdown", "metadata": {}, "source": ["\n", " \"Drawing\" \n", "\n", " \"Drawing\"\n", \n", ""]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "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.9.12"}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file diff --git a/A.Setting up Your Tools and Workspace/A010 Python File Handling and Visualization/A010 Python File Handling and Visualization.ipynb b/A.Setting up Your Tools and Workspace/A010 Python File Handling and Visualization/A010 Python File Handling and Visualization.ipynb index 58449eb..e3ba7ef 100644 --- a/A.Setting up Your Tools and Workspace/A010 Python File Handling and Visualization/A010 Python File Handling and Visualization.ipynb +++ b/A.Setting up Your Tools and Workspace/A010 Python File Handling and Visualization/A010 Python File Handling and Visualization.ipynb @@ -1,878 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Introdução à Engenharia Biomédica (P4 - 2021/2022)\n", - "# Aula Prática #3 - Manuseamento de Ficheiros e Visualização em Python\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Python File Handling and Visualization " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Keywords \n", - "\n", - "`Python`, `File Handling`, `Data Visualization`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributor(s):** Rafael Silva, Hugo Plácido da Silva and Ana Fred\n", - "\n", - "**Date of creation:** 22/05/2022\n", - "\n", - "**Last update:** 22/05/2022" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# I. Overview\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Introduction
\n", - "\n", - "While it is possible to use a spreadsheet environment for loading and visualizing signals, its use can be limited when dealing with multiple recordings and especially when they are of long duration (i.e. large file size). It is also more difficult and time consuming to develop methods and algorithms to process and analyze these signals. Thus, robust and efficient computational environments based on programming languages such as Python are a useful tool to perform such tasks. In addition, specialized libraries for visualizing and analyzing data, solving equations, applying mathematical functions, signal processing and using Artificial Intelligence algorithms can be extremely useful for scientific projects.\n", - "\n", - "In this lesson, we will learn how to create a standard Python environment suitable for scientific computing, which includes file manipulation, plotting, and other features provided by Python libraries." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " In general, Python libraries are well documented and provide example applications, such as Matplotlib and NumPy. However, there are also educational websites like W3Schools and Programiz for learners, as well as online forums and communities that respond to public requests and questions. \n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Objectives
\n", - "\n", - "* Load formatted text files in Python ('.txt' and '.csv')\n", - "* Use basic functions for signal visualization and plot customization" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# II. File Handling\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To be safe, please run the following piece of code to save the current directory in a variable." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "cwd = os.getcwd()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Directory
\n", - "\n", - "An operating system organizes its files and folders in an hierarchical manner (i.e., the directory). To be able to handle files (open, create, update, delete) it is important to be aware of the main navigation commands in a Python environment. Unless we specify the whole or a relative path to a file, we will only have access to scripts and files that are in the same directory as we are. These commands are more useful in the interactive mode (i.e., the console), since in Python IDEs we can use the navigation buttons. \n", - "\n", - "* To show the present location (or path) of the directory, use the command `pwd`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pwd" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is the path to the folder where this notebook is located. Note that each level is separated by a double backslash `\\\\`. \n", - "\n", - "* To list all files and folders within the current directory we can use the `os.listdir()` function:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "os.listdir()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To navigate to other folders, we use the command `cd`.\n", - "\n", - "* To move to a folder within the current directory, we type the folder's name with double quotation marks ``\"\"``:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "cd \"_Resources\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "* To move up one directory level, we type `cd ..`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cd .." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also specify the whole path to the desired folder:\n", - "\n", - "```\n", - "cd \"\"\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To make sure we are using the correct directory, run the following piece of code:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "os.chdir(cwd)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Read files using Python built-in functions
\n", - "\n", - "For creating, reading and updating files, Python includes various functions, namely the function `open()`. This function receives two main parameters: \n", - "* **filename**: the name of the file in the current directory, or the whole path to it\n", - "\n", - "* **mode**: `\"r\"` to read, `\"a\"` to append and `\"w\"` to write a file\n", - "\n", - "Let's open the `ecg_op3.csv` file by creating a file object called `f`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "f = open(\"_Resources/ecg_op3.csv\", \"r\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since the file is now accessible to the Python environment, we can interact with it. \n", - "\n", - "Let's use the `readline()` method associated with the file object, which reads one line at a time:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "line = f.readline() # first line of the file\n", - "line" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that `\\n` is the character for a new line. When we no longer need information from the file, we need to close it:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "f.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To read the whole file, we can create a loop that reads each line and saves it on a list:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "f = open(\"_Resources/ecg_op3.csv\", \"r\")\n", - "ecg_data = [] # empty list to save the signal\n", - "\n", - "for i in f:\n", - " row = f.readline() # reads line\n", - " row = row.strip('\\n') # removes the \\n character\n", - " ecg_data.append(row) # adds line to the list\n", - " \n", - "f.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now access the values inside the `ecg_data` list:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "ecg_data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that each value of the list is a string, and not a numeric representation (e.g., integer, float). To change all values to integer we could have indicated in the previous *for* loop the data type of the rows:\n", - "```python\n", - "f = open(\"_Resources/ecg_op3.csv\", \"r\")\n", - "ecg_data = [] \n", - "\n", - "for i in f:\n", - " row = f.readline().rstrip('\\n') \n", - " ecg_data.append(int(row)) # <----- define row type with int()\n", - " \n", - "f.close()\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
3. Read files using Python libraries
\n", - "\n", - "Python libraries can make some tasks easier to perform and more intuitive. For example, the Numpy library has a single function to read text files, that performs the same steps described previously, called `loadtxt`. Let's see how it works:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "np.loadtxt?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first parameter **fname** corresponds to filename or filepath of our file. Let's use this function to read the `ecg_op3.csv` file:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ecg_data = np.loadtxt('_Resources/ecg_op3.csv')\n", - "ecg_data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "All it took was one line of code! Note that the function outputs a *numpy array* object, which is a Numpy data structure similar to lists and optimized for scientific computation.\n", - "\n", - "Depending on the format of our data we can specify more parameters in this function, namely:\n", - "* **dtype**: the data-type of the resulting array (optional)\n", - "* **comments**: the character that indicates a comment (optional)\n", - "* **delimiter**: the character used to separate values (optional)\n", - "* **skiprows**: number of rows to skip (optional)\n", - "* **usecols**: which columns to read (optional)\n", - "\n", - "Now let's try to load the `ecg_op2.csv`, knowing that this file uses the `#` character for comments and uses `\\t` (tab) as its value delimiter:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ecg_data = np.loadtxt('_Resources/ecg_op2.csv', comments='#', delimiter='\\t')\n", - "ecg_data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the first two rows of the file have been ignored. The output is a numpy array object, in which each row is another array containing the values of the columns separated by commas (i.e. a matrix) :" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ecg_data[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy arrays follow the same indexing and selecting notations as lists:\n", - "```\n", - "array[line, column]\n", - "```\n", - "Thus, to extract an entire column from an array and save it to a variable we use `:`:\n", - "```\n", - "col = array[:, column]\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "first_column = ecg_data[:,0] # all lines from the first column\n", - "first_column" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "\n", - "1. Using the capabilities of *NumPy*, load the `ecg_op2.csv` into the variable `ecg_data`. Take into account that:\n", - "\n", - "* The *NumPy* array should only contain values of type integer ('int')\n", - "\n", - "* The function must ignore lines that begin with '#'\n", - "\n", - "* The tab character is used as a value delimiter\n", - "\n", - "* You should only read the 'NSeq', 'AI1_raw' and 'AI1_mv' columns\n", - "\n", - "*Hint: check the first line of the .csv file for the indexes of the desired columns and add them in a list.*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Using the `ecg_data` variable, extract the 'AI1_mv' column into a numpy array called `ecg_mv`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3. Read the first line of the `ecg_op2.csv` file (i.e. metadata) and save it as a dictionary called `ecg_data_meta`. You should import the **ast** library and use the *literal_eval* function. Print the dictionary to check your output.\n", - "\n", - "*Hint: Use the example from II.2 and remove the `#` character from the line before using it in the function.*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# III. Signal Visualization using Matplotlib Pyplot\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Matplotlib* is a comprehensive library broadly used for producing **static, animated and interactive representations** in Python including plots, histograms, bar charts, etc. It can be used in various environments, such as Python scripts, the Python and IPython shells and the Jupyter notebook. \n", - "\n", - "Below you'll find the main components of a *Matplotlib* figure." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Matplotlib* is the main plotting library for Python, and most of its functions are accessible using the *Pyplot* submodule. The standard way to import the *Pyplot* module is by typing:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
1. Plot Basics
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After importing the *Pyplot* module, we can now use the functions `plot()` and `show()` to create and visualize plots. The parameters of the function `plot()` are diverse, and many configurations are possible. The simplest way is to provide two lists or arrays with the coordinates of the horizontal and vertical data points.\n", - "\n", - "```python\n", - "x = [x1, x2, x3] # list of x coordinates\n", - "y = [y1, y2, y3] # list of y coordinates\n", - "plt.plot(x, y)\n", - "plt.show()\n", - "```\n", - "\n", - "In the plot, the points (x1, y1), (x2, y2) and (x3,y3) will be sequentially connected with straigth lines.\n", - "\n", - "*Note: the `show()` function is optional in some Python environments.*" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's exemplify with the sine function:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = np.arange(0,2*np.pi,0.01) # arange(start, stop, step)\n", - "y = np.sin(x) # each value of x is mapped into its sine value\n", - "\n", - "plt.plot(x, y)\n", - "plt.show() # optional in jupyter notebook" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can specify other plot elements using functions such as:\n", - "\n", - "* `title(str)`: plot title\n", - "\n", - "* `xlabel(str)`: horizontal axis title\n", - "\n", - "* `ylabel(str)`: vertical axis title\n", - "\n", - "* `legend()`: plot legend\n", - "\n", - "* `grid(bool)`: plot grid\n", - "\n", - "* `xlim(list)`: horizontal axis limits\n", - "\n", - "* `ylim(list)`: vertical axis limits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.plot(x, y)\n", - "plt.title('Sine Function')\n", - "plt.xlabel('Samples')\n", - "plt.ylabel('Amplitude')\n", - "plt.grid(True)\n", - "plt.xlim([0,2*np.pi])\n", - "plt.ylim([-1,1])\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that each one of the previous functions can receive other parameters for further customization, such as color, width, style, size, transparency, among others:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "plt.plot(x, y, linestyle='--', linewidth=4, color='orange', label='Sine')\n", - "plt.title('Sine Function', fontsize=14)\n", - "plt.xlabel('Samples')\n", - "plt.ylabel('Amplitude')\n", - "plt.legend() # uses the label from the plt.plot\n", - "plt.show() " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also add other plots to the same figure:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = np.arange(0,2*np.pi,0.01)\n", - "y1 = np.sin(x) \n", - "y2 = np.cos(x)\n", - "\n", - "plt.plot(x, y1, label='Sine')\n", - "plt.plot(x, y2, label='Cossine')\n", - "plt.legend()\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Also, instead of connecting the data points with straight lines, we can use markers to highlight reference points:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x_max = np.pi/2\n", - "y_max = np.sin(x_max)\n", - "x_min = np.pi*3/2\n", - "y_min = np.sin(x_min)\n", - "\n", - "plt.plot(x, y, label='Sine')\n", - "plt.plot(x_max, y_max, marker='o', label='Max', color='orange')\n", - "plt.plot(x_min, y_min, marker='o', label='Min', color='green')\n", - "plt.legend()\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For future reference, here are some line and marker styles, along with base colors:\n", - "\n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Explore
\n", - "
\n", - " To learn more about Matplotlib funtionalities, visit Matplotlib.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### EXERCISE:\n", - "\n", - "1. Using Pyplot, plot the `ecg_mv` array, using the following instructions:\n", - " - Line: color purple, width 0.5\n", - " \n", - " - Title: 'ECG Signal - ADC'\n", - " \n", - " - Vertical Axis: 'Amplitude (mV)'\n", - " \n", - " - Horizontal Axis: 'Samples', from 0 to 5000" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Replicate the previous plot but with the horizontal axis now converted to real units:\n", - "\n", - " - Horizontal Axis: 'Time (s)', from 0 to 5 seconds\n", - " \n", - "One way to create a time sequence is using the numpy `arange()` function in this format:\n", - "\n", - "```python\n", - "import numpy as np\n", - "np.arange(start, stop, step)\n", - "```\n", - "\n", - "*Hint: you can use the `ecg_data_meta` dictionary to retrieve some important data*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3. Since the `ecg_mv` array results from converting the ADC values to the ADC operating voltage scale, it is not yet in real units. Change the plot title to 'ECG Signal - Real' and use the ECG sensor specifications to correctly plot the ECG signal in time and amplitude:\n", - "\n", - " - Gain = 1100\n", - " \n", - " - $V_{ref}$ = 3.3 V\n", - " \n", - " - Offset = $\\frac{Vref}{2}$\n", - " \n", - "\n", - "\n", - "Recall the transfer function of the ECG sensor:\n", - "\n", - "$$ \\textrm{Amplitude (V)} = \\frac{\\left(\\frac{\\textrm{ADC value}}{\\textrm{$2^n$}}-\\frac{1}{2}\\right) \\times \\textrm {Vref (V)}}{G_{E C G}}$$\n", - "\n", - "*Hint: The ECG signal should be within the -1.5 to 1.5 mV amplitude range.*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
2. Subplot
\n", - "\n", - "With Matplotlib it is also possible to draw multiple plots in one figure using the `subplot()` function. This function receives optional parameters to define the grid of subplots (rows and columns) and the desired location of the subplot:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "# plot 1:\n", - "x = np.arange(0,2*np.pi,0.01)\n", - "y1 = np.sin(x) \n", - "\n", - "plt.subplot(1, 2, 1) # the grid is 1x2, the subplot will be in the position 1\n", - "plt.plot(x, y1, label='Sine')\n", - "plt.legend()\n", - "\n", - "# plot 2:\n", - "x = np.arange(0,2*np.pi,0.01)\n", - "y2 = np.cos(x)\n", - "\n", - "plt.subplot(1, 2, 2) # the same grid, the subplot will be in the position 2\n", - "plt.plot(x, y2, label='Cossine', color='orange')\n", - "plt.legend()\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#
3. Scatter
\n", - "\n", - "Another useful feature of Matplotlib is the scatter plot, for when we prefer not to connect the data points. This is the case when the data is made of observations. The operation of the `scatter()` function is similar to that of the `plot()` function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# artificial data\n", - "height = np.random.normal(170, 10, 100)\n", - "weight = (height-100) * np.random.uniform(0.75, 1.25, 100)\n", - "\n", - "# scatter plot\n", - "plt.scatter(height, weight)\n", - "plt.xlabel('Height (cm)')\n", - "plt.ylabel('Weight (kg)')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - " \"Drawing\" \n", - "\n", - " \"Drawing\"\n", \n", - "" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["### Introdu\u00e7\u00e3o \u00e0 Engenharia Biom\u00e9dica (P4 - 2021/2022)\n", "# Aula Pr\u00e1tica #3 - Manuseamento de Ficheiros e Visualiza\u00e7\u00e3o em Python\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Python File Handling and Visualization "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Keywords \n", "\n", "`Python`, `File Handling`, `Data Visualization`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Contributor(s):** Rafael Silva, Hugo Pl\u00e1cido da Silva and Ana Fred\n", "\n", "**Date of creation:** 22/05/2022\n", "\n", "**Last update:** 22/05/2022"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# I. Overview\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Introduction
\n", "\n", "While it is possible to use a spreadsheet environment for loading and visualizing signals, its use can be limited when dealing with multiple recordings and especially when they are of long duration (i.e. large file size). It is also more difficult and time consuming to develop methods and algorithms to process and analyze these signals. Thus, robust and efficient computational environments based on programming languages such as Python are a useful tool to perform such tasks. In addition, specialized libraries for visualizing and analyzing data, solving equations, applying mathematical functions, signal processing and using Artificial Intelligence algorithms can be extremely useful for scientific projects.\n", "\n", "In this lesson, we will learn how to create a standard Python environment suitable for scientific computing, which includes file manipulation, plotting, and other features provided by Python libraries."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " In general, Python libraries are well documented and provide example applications, such as Matplotlib and NumPy. However, there are also educational websites like W3Schools and Programiz for learners, as well as online forums and communities that respond to public requests and questions. \n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Objectives
\n", "\n", "* Load formatted text files in Python ('.txt' and '.csv')\n", "* Use basic functions for signal visualization and plot customization"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# II. File Handling\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To be safe, please run the following piece of code to save the current directory in a variable."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import os\n", "cwd = os.getcwd()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Directory
\n", "\n", "An operating system organizes its files and folders in an hierarchical manner (i.e., the directory). To be able to handle files (open, create, update, delete) it is important to be aware of the main navigation commands in a Python environment. Unless we specify the whole or a relative path to a file, we will only have access to scripts and files that are in the same directory as we are. These commands are more useful in the interactive mode (i.e., the console), since in Python IDEs we can use the navigation buttons. \n", "\n", "* To show the present location (or path) of the directory, use the command `pwd`:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["pwd"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This is the path to the folder where this notebook is located. Note that each level is separated by a double backslash `\\\\`. \n", "\n", "* To list all files and folders within the current directory we can use the `os.listdir()` function:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["os.listdir()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To navigate to other folders, we use the command `cd`.\n", "\n", "* To move to a folder within the current directory, we type the folder's name with double quotation marks ``\"\"``:"]}, {"cell_type": "code", "execution_count": null, "metadata": {"scrolled": true}, "outputs": [], "source": ["cd \"_Resources\""]}, {"cell_type": "markdown", "metadata": {}, "source": ["* To move up one directory level, we type `cd ..`:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["cd .."]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can also specify the whole path to the desired folder:\n", "\n", "```\n", "cd \"\"\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To make sure we are using the correct directory, run the following piece of code:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["os.chdir(cwd)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Read files using Python built-in functions
\n", "\n", "For creating, reading and updating files, Python includes various functions, namely the function `open()`. This function receives two main parameters: \n", "* **filename**: the name of the file in the current directory, or the whole path to it\n", "\n", "* **mode**: `\"r\"` to read, `\"a\"` to append and `\"w\"` to write a file\n", "\n", "Let's open the `ecg_op3.csv` file by creating a file object called `f`:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["f = open(\"_Resources/ecg_op3.csv\", \"r\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Since the file is now accessible to the Python environment, we can interact with it. \n", "\n", "Let's use the `readline()` method associated with the file object, which reads one line at a time:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["line = f.readline() # first line of the file\n", "line"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that `\\n` is the character for a new line. When we no longer need information from the file, we need to close it:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["f.close()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["To read the whole file, we can create a loop that reads each line and saves it on a list:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["f = open(\"_Resources/ecg_op3.csv\", \"r\")\n", "ecg_data = [] # empty list to save the signal\n", "\n", "for i in f:\n", " row = f.readline() # reads line\n", " row = row.strip('\\n') # removes the \\n character\n", " ecg_data.append(row) # adds line to the list\n", " \n", "f.close()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can now access the values inside the `ecg_data` list:"]}, {"cell_type": "code", "execution_count": null, "metadata": {"scrolled": true}, "outputs": [], "source": ["ecg_data"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that each value of the list is a string, and not a numeric representation (e.g., integer, float). To change all values to integer we could have indicated in the previous *for* loop the data type of the rows:\n", "```python\n", "f = open(\"_Resources/ecg_op3.csv\", \"r\")\n", "ecg_data = [] \n", "\n", "for i in f:\n", " row = f.readline().rstrip('\\n') \n", " ecg_data.append(int(row)) # <----- define row type with int()\n", " \n", "f.close()\n", "```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
3. Read files using Python libraries
\n", "\n", "Python libraries can make some tasks easier to perform and more intuitive. For example, the Numpy library has a single function to read text files, that performs the same steps described previously, called `loadtxt`. Let's see how it works:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "np.loadtxt?"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The first parameter **fname** corresponds to filename or filepath of our file. Let's use this function to read the `ecg_op3.csv` file:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["ecg_data = np.loadtxt('_Resources/ecg_op3.csv')\n", "ecg_data"]}, {"cell_type": "markdown", "metadata": {}, "source": ["All it took was one line of code! Note that the function outputs a *numpy array* object, which is a Numpy data structure similar to lists and optimized for scientific computation.\n", "\n", "Depending on the format of our data we can specify more parameters in this function, namely:\n", "* **dtype**: the data-type of the resulting array (optional)\n", "* **comments**: the character that indicates a comment (optional)\n", "* **delimiter**: the character used to separate values (optional)\n", "* **skiprows**: number of rows to skip (optional)\n", "* **usecols**: which columns to read (optional)\n", "\n", "Now let's try to load the `ecg_op2.csv`, knowing that this file uses the `#` character for comments and uses `\\t` (tab) as its value delimiter:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["ecg_data = np.loadtxt('_Resources/ecg_op2.csv', comments='#', delimiter='\\t')\n", "ecg_data"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that the first two rows of the file have been ignored. The output is a numpy array object, in which each row is another array containing the values of the columns separated by commas (i.e. a matrix) :"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["ecg_data[0]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Numpy arrays follow the same indexing and selecting notations as lists:\n", "```\n", "array[line, column]\n", "```\n", "Thus, to extract an entire column from an array and save it to a variable we use `:`:\n", "```\n", "col = array[:, column]\n", "```"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["first_column = ecg_data[:,0] # all lines from the first column\n", "first_column"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "\n", "1. Using the capabilities of *NumPy*, load the `ecg_op2.csv` into the variable `ecg_data`. Take into account that:\n", "\n", "* The *NumPy* array should only contain values of type integer ('int')\n", "\n", "* The function must ignore lines that begin with '#'\n", "\n", "* The tab character is used as a value delimiter\n", "\n", "* You should only read the 'NSeq', 'AI1_raw' and 'AI1_mv' columns\n", "\n", "*Hint: check the first line of the .csv file for the indexes of the desired columns and add them in a list.*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["2. Using the `ecg_data` variable, extract the 'AI1_mv' column into a numpy array called `ecg_mv`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["3. Read the first line of the `ecg_op2.csv` file (i.e. metadata) and save it as a dictionary called `ecg_data_meta`. You should import the **ast** library and use the *literal_eval* function. Print the dictionary to check your output.\n", "\n", "*Hint: Use the example from II.2 and remove the `#` character from the line before using it in the function.*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["# III. Signal Visualization using Matplotlib Pyplot\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["*Matplotlib* is a comprehensive library broadly used for producing **static, animated and interactive representations** in Python including plots, histograms, bar charts, etc. It can be used in various environments, such as Python scripts, the Python and IPython shells and the Jupyter notebook. \n", "\n", "Below you'll find the main components of a *Matplotlib* figure."]}, {"cell_type": "markdown", "metadata": {}, "source": [""]}, {"cell_type": "markdown", "metadata": {}, "source": ["*Matplotlib* is the main plotting library for Python, and most of its functions are accessible using the *Pyplot* submodule. The standard way to import the *Pyplot* module is by typing:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import matplotlib.pyplot as plt"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
1. Plot Basics
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["After importing the *Pyplot* module, we can now use the functions `plot()` and `show()` to create and visualize plots. The parameters of the function `plot()` are diverse, and many configurations are possible. The simplest way is to provide two lists or arrays with the coordinates of the horizontal and vertical data points.\n", "\n", "```python\n", "x = [x1, x2, x3] # list of x coordinates\n", "y = [y1, y2, y3] # list of y coordinates\n", "plt.plot(x, y)\n", "plt.show()\n", "```\n", "\n", "In the plot, the points (x1, y1), (x2, y2) and (x3,y3) will be sequentially connected with straigth lines.\n", "\n", "*Note: the `show()` function is optional in some Python environments.*"]}, {"cell_type": "markdown", "metadata": {}, "source": [""]}, {"cell_type": "markdown", "metadata": {}, "source": ["Let's exemplify with the sine function:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x = np.arange(0,2*np.pi,0.01) # arange(start, stop, step)\n", "y = np.sin(x) # each value of x is mapped into its sine value\n", "\n", "plt.plot(x, y)\n", "plt.show() # optional in jupyter notebook"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can specify other plot elements using functions such as:\n", "\n", "* `title(str)`: plot title\n", "\n", "* `xlabel(str)`: horizontal axis title\n", "\n", "* `ylabel(str)`: vertical axis title\n", "\n", "* `legend()`: plot legend\n", "\n", "* `grid(bool)`: plot grid\n", "\n", "* `xlim(list)`: horizontal axis limits\n", "\n", "* `ylim(list)`: vertical axis limits"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["plt.plot(x, y)\n", "plt.title('Sine Function')\n", "plt.xlabel('Samples')\n", "plt.ylabel('Amplitude')\n", "plt.grid(True)\n", "plt.xlim([0,2*np.pi])\n", "plt.ylim([-1,1])\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that each one of the previous functions can receive other parameters for further customization, such as color, width, style, size, transparency, among others:"]}, {"cell_type": "code", "execution_count": null, "metadata": {"scrolled": true}, "outputs": [], "source": ["plt.plot(x, y, linestyle='--', linewidth=4, color='orange', label='Sine')\n", "plt.title('Sine Function', fontsize=14)\n", "plt.xlabel('Samples')\n", "plt.ylabel('Amplitude')\n", "plt.legend() # uses the label from the plt.plot\n", "plt.show() "]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can also add other plots to the same figure:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x = np.arange(0,2*np.pi,0.01)\n", "y1 = np.sin(x) \n", "y2 = np.cos(x)\n", "\n", "plt.plot(x, y1, label='Sine')\n", "plt.plot(x, y2, label='Cossine')\n", "plt.legend()\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Also, instead of connecting the data points with straight lines, we can use markers to highlight reference points:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["x_max = np.pi/2\n", "y_max = np.sin(x_max)\n", "x_min = np.pi*3/2\n", "y_min = np.sin(x_min)\n", "\n", "plt.plot(x, y, label='Sine')\n", "plt.plot(x_max, y_max, marker='o', label='Max', color='orange')\n", "plt.plot(x_min, y_min, marker='o', label='Min', color='green')\n", "plt.legend()\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For future reference, here are some line and marker styles, along with base colors:\n", "\n", ""]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Explore
\n", "
\n", " To learn more about Matplotlib funtionalities, visit Matplotlib.\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### EXERCISE:\n", "\n", "1. Using Pyplot, plot the `ecg_mv` array, using the following instructions:\n", " - Line: color purple, width 0.5\n", " \n", " - Title: 'ECG Signal - ADC'\n", " \n", " - Vertical Axis: 'Amplitude (mV)'\n", " \n", " - Horizontal Axis: 'Samples', from 0 to 5000"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["2. Replicate the previous plot but with the horizontal axis now converted to real units:\n", "\n", " - Horizontal Axis: 'Time (s)', from 0 to 5 seconds\n", " \n", "One way to create a time sequence is using the numpy `arange()` function in this format:\n", "\n", "```python\n", "import numpy as np\n", "np.arange(start, stop, step)\n", "```\n", "\n", "*Hint: you can use the `ecg_data_meta` dictionary to retrieve some important data*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["3. Since the `ecg_mv` array results from converting the ADC values to the ADC operating voltage scale, it is not yet in real units. Change the plot title to 'ECG Signal - Real' and use the ECG sensor specifications to correctly plot the ECG signal in time and amplitude:\n", "\n", " - Gain = 1100\n", " \n", " - $V_{ref}$ = 3.3 V\n", " \n", " - Offset = $\\frac{Vref}{2}$\n", " \n", "\n", "\n", "Recall the transfer function of the ECG sensor:\n", "\n", "$$ \\textrm{Amplitude (V)} = \\frac{\\left(\\frac{\\textrm{ADC value}}{\\textrm{$2^n$}}-\\frac{1}{2}\\right) \\times \\textrm {Vref (V)}}{G_{E C G}}$$\n", "\n", "*Hint: The ECG signal should be within the -1.5 to 1.5 mV amplitude range.*"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["#
2. Subplot
\n", "\n", "With Matplotlib it is also possible to draw multiple plots in one figure using the `subplot()` function. This function receives optional parameters to define the grid of subplots (rows and columns) and the desired location of the subplot:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "# plot 1:\n", "x = np.arange(0,2*np.pi,0.01)\n", "y1 = np.sin(x) \n", "\n", "plt.subplot(1, 2, 1) # the grid is 1x2, the subplot will be in the position 1\n", "plt.plot(x, y1, label='Sine')\n", "plt.legend()\n", "\n", "# plot 2:\n", "x = np.arange(0,2*np.pi,0.01)\n", "y2 = np.cos(x)\n", "\n", "plt.subplot(1, 2, 2) # the same grid, the subplot will be in the position 2\n", "plt.plot(x, y2, label='Cossine', color='orange')\n", "plt.legend()\n", "\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#
3. Scatter
\n", "\n", "Another useful feature of Matplotlib is the scatter plot, for when we prefer not to connect the data points. This is the case when the data is made of observations. The operation of the `scatter()` function is similar to that of the `plot()` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["# artificial data\n", "height = np.random.normal(170, 10, 100)\n", "weight = (height-100) * np.random.uniform(0.75, 1.25, 100)\n", "\n", "# scatter plot\n", "plt.scatter(height, weight)\n", "plt.xlabel('Height (cm)')\n", "plt.ylabel('Weight (kg)')\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\n", " \"Drawing\" \n", "\n", " \"Drawing\"\n", \n", ""]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "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.9.12"}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file diff --git a/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/A011 How to flash a ScientISST board with the official firmware.ipynb b/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/A011 How to flash a ScientISST board with the official firmware.ipynb new file mode 100644 index 0000000..ad2d2b4 --- /dev/null +++ b/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/A011 How to flash a ScientISST board with the official firmware.ipynb @@ -0,0 +1,522 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "1e2a027b", + "metadata": {}, + "source": [ + "![scientisst-notebooks_top-banner](https://raw.githubusercontent.com/scientisst/notebooks/59632d3d477981a3b1cc12157e12bbdcdb45def8/_Resources/top-banner.png)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3cf183a2", + "metadata": {}, + "source": [ + "# How to flash a ScientISST " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "36a4cefd", + "metadata": {}, + "source": [ + "### Keywords \n", + "`ScientISST`, `firmware`, `configuration`" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "e09b7dc0", + "metadata": {}, + "source": [ + "### Notebook Info \n", + "\n", + "**Contributor(s):** Rui Maciel, Frederico Almeida Santos\n", + "\n", + "**Date of creation:** 05/03/2023\n", + "\n", + "**Last update:** 05/03/2023" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "043fa9be", + "metadata": {}, + "source": [ + "### Description \n", + "This notebook will guide you through the process of flashing a ScientISST board. The guide includes steps for Windows, Linux, Mac OS and Windows Subsystem for Linux." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "14a7e588", + "metadata": {}, + "source": [ + "### Materials \n", + "\n", + "* 1 ScientISST Board\n", + "* 1 USB-C cable\n", + "* 1 computer with internet connection, a USB port, python 3 installed and with one of the following operating systems:\n", + " * Windows 10/11\n", + " * Linux\n", + " * Mac OS\n", + " * Windows Subsystem for Linux (WSL2 - Ubuntu or Debian)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "01d58803", + "metadata": {}, + "source": [ + "***" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "# 1. Background " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "The ScientISST SENSE development board is an hardware platform, designed to empower students, researchers or anyone with an interest in developing biomedical engineering projects with the tools to easily create microcontroller-based devices and bring their health and well-being creations to life.\n", + "\n", + "By default the board is pre-programmed with a firmware optimized for real-time data acquisition and streaming, and can be used seamlessly with the available software and APIs. However, it is often important to experiment with custom firmware." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "69307772", + "metadata": {}, + "source": [ + "# 2. Prerequisites " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "521fbb4a", + "metadata": {}, + "source": [ + "## 2.1. Windows \n", + "\n", + "Download and install the ESP-IDF version 4.4.4 from the link bellow:\n", + "\n", + "[https://dl.espressif.com/dl/esp-idf/?idf=4.4.4](https://dl.espressif.com/dl/esp-idf/?idf=4.4)\n", + "\n", + "📋 **NOTE:** It is important to install this specific version 4.4.4 since this is the version currently used by the firmware. Do not install the latest version of ESP-IDF, it is not backwards compatible with version 4.4.x.\n", + "\n", + "## 2.2. Mac OS \n", + "\n", + "### Step 0 - Before You Start\n", + "\n", + "If an error like this is shown during any step:\n", + "\n", + "```bash\n", + "xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun\n", + "```\n", + "\n", + "Then you will need to install the XCode command line tools to continue. You can install thee by running:\n", + "\n", + "```bash\n", + "xcode-select --install\n", + "```\n", + "\n", + "Furthermore, if you use Apple M1 platform and see an error like this:\n", + "\n", + "```bash\n", + "WARNING: directory for tool xtensa-esp32-elf version esp-2021r2-patch3-8.4.0 is present, but tool was not found\n", + "ERROR: tool xtensa-esp32-elf has no installed versions. Please run 'install.sh' to install it.\n", + "```\n", + "\n", + "or:\n", + "\n", + "```bash\n", + "zsh: bad CPU type in executable: ~/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcc\n", + "```\n", + "\n", + "Then you will need to install Apple Rosetta 2 by running:\n", + "\n", + "```bash\n", + "/usr/sbin/softwareupdate --install-rosetta --agree-to-license\n", + "```\n", + "\n", + "### Step 1 - Install CMake & Ninja build\n", + "\n", + "- If you have [HomeBrew](https://brew.sh/), you can run on the terminal:\n", + "\n", + "```bash\n", + "brew install cmake ninja dfu-util\n", + "```\n", + "\n", + "- If you have [MacPorts](https://www.macports.org/install.php), you can run:\n", + "\n", + "```bash\n", + "sudo port install cmake ninja dfu-util\n", + "```\n", + "\n", + "If you don’t have [HomeBrew](https://brew.sh/) or [MacPorts](https://www.macports.org/install.php), we suggest installing [HomeBrew](https://brew.sh/).\n", + "\n", + "### Step 2 - Install ccache (Optional but recommended)\n", + "\n", + "- If you have [HomeBrew](https://brew.sh/), you can run on the terminal:\n", + "\n", + "```bash\n", + "brew install ccache\n", + "```\n", + "\n", + "- If you have [MacPorts](https://www.macports.org/install.php), you can run:\n", + "\n", + "```bash\n", + "sudo port install ccache\n", + "```\n", + "\n", + "If you don’t have [HomeBrew](https://brew.sh/) or [MacPorts](https://www.macports.org/install.php), we suggest installing [HomeBrew](https://brew.sh/).\n", + "\n", + "### Step 3 - Installing Python 3\n", + "\n", + "Check your current python version by running:\n", + "\n", + "```bash\n", + "python --version\n", + "```\n", + "\n", + "if the output is Python 3, then you’re good to go and can proceed to the next step. Otherwise, also check if Python 3 isn’t already installed on your computer by running:\n", + "\n", + "```bash\n", + "python3 --version\n", + "```\n", + "\n", + "If the above command returns an error, it means Python 3 is not installed.\n", + "\n", + "Below is an overview of the steps to install Python 3.\n", + "\n", + "- If you have [HomeBrew](https://brew.sh/), you can run on the terminal:\n", + "\n", + "```bash\n", + "brew install python3\n", + "```\n", + "\n", + "- If you have [MacPorts](https://www.macports.org/install.php), you can run:\n", + "\n", + "```bash\n", + "sudo port install python38\n", + "```\n", + "\n", + "## 2.3. Linux \n", + "\n", + "To compile the firmware you will need to get the following packages. The command to run depends on which distribution of Linux you are using:\n", + "\n", + "- Ubuntu and Debian:\n", + "\n", + "```bash\n", + "sudo apt-get install git wget flex bison gperf python3 python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0\n", + "```\n", + "\n", + "- CentOS 7 & 8:\n", + "\n", + "```bash\n", + "sudo yum -y update && sudo yum install git wget flex bison gperf python3 cmake ninja-build ccache dfu-util libusbx\n", + "```\n", + "\n", + "- Arch\n", + "\n", + "```bash\n", + "sudo pacman -S --needed gcc git make flex bison gperf python cmake ninja ccache dfu-util libusb\n", + "```\n", + "\n", + "## 2.4. Linux (WSL2 - Ubuntu and Debian) \n", + "\n", + "To compile the firmware you will need to get the following packages. The command to run depends on which distribution of Linux you are using:\n", + "\n", + "- Ubuntu and Debian:\n", + "\n", + "```bash\n", + "sudo apt-get install git wget flex bison gperf python3 python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0\n", + "```\n", + "\n", + "```bash\n", + "sudo apt install linux-tools-virtual hwdata\n", + "```\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "923b217f", + "metadata": {}, + "source": [ + "# 3. Download the firmware repository " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "```bash\n", + "git clone --recursive git@github.com:scientisst/scientisst-sense-firmware.git\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "# 4. Install Xtensa’s toolchain " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "**(MacOS / Linux)**\n", + "\n", + "```shell\n", + ". ./get_idf.sh --install\n", + "```\n", + "\n", + "**(Windows)**\n", + "\n", + "```bash\n", + "get_idf.bat --install\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "# 5. Load Xtensa’s tools " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "This step needs to be repeated every time you restart your terminal.\n", + "\n", + "**(MacOS / Linux)**\n", + "\n", + "```shell\n", + ". ./get_idf.sh\n", + "```\n", + "\n", + "**(Windows)**\n", + "\n", + "```bash\n", + "get_idf.bat\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "648690ed", + "metadata": {}, + "source": [ + "# 6. Configure the firmware " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "00d4cc0a", + "metadata": {}, + "source": [ + "Two files should be modified according to the board used and desired configuration.\n", + "\n", + "**config.h**\n", + "\n", + "![config.h](_Resources/config.png)\n", + "\n", + "Make sure you edit the following lines according to your needs:\n", + "\n", + "-line nº7: NO_EXT_ADC(to disable external adc or ADC_MCP(to enable external adc);\n", + "\n", + "-line nº11: HW_VERSION_LEGACY (Core and Cardio ) or HW_VERSION_NANO (Nano);\n", + "\n", + "-line nº13: 0 (do not include SD card code) or 1 (include SD card code);\n", + "\n", + "-line nº14: 0 (if mount fails stop execution) or 1 (if mount fails format SD card);\n", + "\n", + "-line nº18: 0(no timestamp) or 1(include timestamp in frame).\n", + "\n", + "⚠️ **WARNING:** Formating the SD card will erase all data inside it.\n", + "\n", + "⚠️ **WARNING:** Keep in mind that timestamp, ext adc and SD card functionalities are mutually exclusive and cannot be active at the same time.\n", + "\n", + "**scientisst.c**\n", + "\n", + "![scientisst.h](_Resources/scientisst.png)\n", + "\n", + "This settings can be edited after flashing the scientisst board on the WebSense website. Edit the op_settings structure with your desired configuration. On the screenshot are the 2 most common uses: bluetooth (do not change anything), and wifi(erase line 137 and copy the code inside the comment into the remaining {})" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "# 7. Flash the Firmware " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "Make sure you connect the ScientISST board to the computer using USB and place it in FLASH mode. Consult your board model for instructions on how to place the board in FLASH mode.\n", + "\n", + "```bash\n", + "idf.py flash\n", + "```\n", + "\n", + "FOR WSL (after every restart and before flashing):\n", + "\n", + "First you have to give access of the USB port to the WSL installation. [https://github.com/dorssel/usbipd-win/wiki/WSL-support](https://github.com/dorssel/usbipd-win/wiki/WSL-support)\n", + "\n", + "- In WSL shell:\n", + "\n", + "```bash\n", + "sudo update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 20\n", + "```\n", + "\n", + "- Then in Windows PowerShell:\n", + "\n", + "```powershell\n", + "usbipd wsl list\n", + "```\n", + "\n", + "- Then type with the busid of the board\n", + "\n", + "```powershell\n", + "usbipd wsl attach --busid \n", + "```\n", + "\n", + "- Finally, in the WSL terminal\n", + "\n", + "```bash\n", + "sudo chmod a+rw /dev/ttyUSB0\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "# 8.Troubleshooting " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "## 8.1. Cannot open /dev/ttyUSB0: Permission denied " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "If you see this message, it means your user cannot access the serial ports without elevated permissions. To fix this use, add yourself to the correct user groups to gain access to the serial ports.\n", + "\n", + "**(For MacOS / Linux only)**\n", + "\n", + "```bash\n", + "sudo usermod -a -G tty $USER\n", + "sudo usermod -a -G dialout $USER\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "b4c52f8a", + "metadata": {}, + "source": [ + "***" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "13f4c736", + "metadata": {}, + "source": [ + "![scientisst-notebooks_bottom-banner](https://raw.githubusercontent.com/scientisst/notebooks/master/_Resources/bottom-banner.png)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.0" + }, + "vscode": { + "interpreter": { + "hash": "7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/_Resources/config.png b/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/_Resources/config.png new file mode 100644 index 0000000..2c945d8 Binary files /dev/null and b/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/_Resources/config.png differ diff --git a/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/_Resources/scientisst.png b/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/_Resources/scientisst.png new file mode 100644 index 0000000..50298ab Binary files /dev/null and b/A.Setting up Your Tools and Workspace/A011 How to flash a ScientISST board with the official firmware/_Resources/scientisst.png differ diff --git a/A.Setting up Your Tools and Workspace/README.md b/A.Setting up Your Tools and Workspace/README.md index 0988e79..676815d 100644 --- a/A.Setting up Your Tools and Workspace/README.md +++ b/A.Setting up Your Tools and Workspace/README.md @@ -8,8 +8,9 @@ A001 Open Signals | Open Signals, Biosignals, Physiological Signals Acquisition| A002 Arduino Essentials | Arduino, Embedded Systems , Signals Acquisition| Update authors| dd/mm/aa| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A002%20Arduino%20Essentials/A002%20Arduino%20Essentials.ipynb) A003 Arduino - Getting started | Arduino, Embedded systems| Update authors| dd/mm/aa| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A003%20Arduino%20-%20Getting%20started/A003%20Arduino%20-%20Getting%20started.ipynb) A005 Seeeduino XIAO Essentials | Seeeduino XIAO, Embedded Systems , Signals Acquisition| Update authors| dd/mm/aa| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A005%20Seeeduino%20XIAO%20Essentials/A005%20Seeeduino%20XIAO%20Essentials.ipynb) -A006 ScientISST - Arduino IDE tutorial | Sense, Arduino, IDE| Update authors| dd/mm/aa| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A006%20ScientISST%20-%20Arduino%20IDE%20tutorial/A006%20ScientISST%20-%20Arduino%20IDE%20tutorial.ipynb) +A006 ScientISST - Arduino IDE tutorial | `ScientISST`, `ScientISST CORE`, `Arduino IDE`, `Firmware`| Leonor Pereira; Ana Sofia Carmo; Francisco Melo; Afonso Raposo; Prof. Hugo Silva| 11/22| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A006%20ScientISST%20-%20Arduino%20IDE%20tutorial/A006%20ScientISST%20-%20Arduino%20IDE%20tutorial.ipynb) A007 File Exploration | Hierarchical Data Format (HDF), Data Loading, Metadata| Update authors| dd/mm/aa| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A007%20File%20Exploration/A007%20File%20Exploration.ipynb) A008 Setup your Python workspace | `Programming`, `Python`, `Anaconda`, `Data Visualization`, `Data Structures`| Rafael Silva, Hugo Plácido da Silva and Ana Fred| 12/05/2022| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A008%20Setup%20your%20Python%20workspace/A008%20Setup%20your%20Python%20workspace.ipynb) A009 Essentials of Post-processing | Low-Pass Filter, Python, Plotting| Update authors| dd/mm/aa| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A009%20Essentials%20of%20Post-processing/A009%20Essentials%20of%20Post-processing.ipynb) A010 Python File Handling and Visualization | `Python`, `File Handling`, `Data Visualization`| Rafael Silva, Hugo Plácido da Silva and Ana Fred| 22/05/2022| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A010%20Python%20File%20Handling%20and%20Visualization/A010%20Python%20File%20Handling%20and%20Visualization.ipynb) +A011 How to flash a ScientISST board with the official firmware | `ScientISST`, `firmware`, `configuration`| Rui Maciel, Frederico Almeida Santos| 05/03/2023| [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/scientisst/notebooks/blob/master/A.Setting%20up%20Your%20Tools%20and%20Workspace/A011%20How%20to%20flash%20a%20ScientISST%20board%20with%20the%20official%20firmware/A011%20How%20to%20flash%20a%20ScientISST%20board%20with%20the%20official%20firmware.ipynb) diff --git a/B.Instrumentation/B001 Basic active circuits with an OpAmp/B001 Basic active circuits with an OpAmp.ipynb b/B.Instrumentation/B001 Basic active circuits with an OpAmp/B001 Basic active circuits with an OpAmp.ipynb index 5757956..8befab5 100755 --- a/B.Instrumentation/B001 Basic active circuits with an OpAmp/B001 Basic active circuits with an OpAmp.ipynb +++ b/B.Instrumentation/B001 Basic active circuits with an OpAmp/B001 Basic active circuits with an OpAmp.ipynb @@ -1,298 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " #
Active Circuits with an Operational Amplifier
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Basic active circuits with an OpAmp " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Keywords \n", - "```Operational Amplifiers```, ```Circuit Analysis```, ```Arduino```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributor(s):** Afonso Raposo, Joana Pinto, Prof. João Sanches; Prof. Hugo Silva\n", - "\n", - "**Date of creation:** dd/mm/aa\n", - "\n", - "**Last update:** 2021" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# I. Introduction\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Background
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This session aims at introducing the student to the operational amplifier (OpAmp) and its basic configurations: Voltage follower, inverter and non-inverter." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " If you have difficulties with the hardware setup, use Tinkercad.
Files with pre-recorded data are also provided for some experiments.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
2. Objectives
\n", - "* Experiment different OpAmp configurations\n", - "* Use Arduino-type systems as a basic function generator and signal visualizer \n", - "* Explore experimental characterization of active electronic circuits\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
3. Materials (optional)
\n", - "* Arduino IDE\n", - "* 1x Breadboard\n", - "* 5x Jumper wires\n", - "* 4x 1kOhm resistors\n", - "* 4x 10kOhm resistors\n", - "* 1x 100nF capacitor\n", - "* 1x OPA344PA OpAmp\n", - "* 1x Arduino (or analogous device)\n", - "* 1x USB cable" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# II. Experimental\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Consider the following active circuits represented in Figure 1 and Figure 2.\n", - "\n", - "
\n", - " Note
\n", - "
\n", - " The datasheet for the OPA344 OpAmp can be found at:
https://www.ti.com/lit/ds/sbos107a/sbos107a.pdf\n", - "
\n", - "
\n", - "\n", - "\n", - "\n", - "
Figure 1 - Non-inverter OpAmp configuration
\n", - "\n", - "\n", - "\n", - "
Figure 2 - Inverter OpAmp configuration
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# III. Explore\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Quizz
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "1) Derive its transfer function for both configurations with and without the capacitor." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2) Simulate the circuits for several input signals (sinusoidal, square, triangular and noise) and frequencies." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3) Compute the input and output impedances (use the Thévenin’s theorem)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "4) Assemble the non-inverter configuration on a breadboard without the capacitor ($V- = 0V$ and $V+ = V_{cc}$ on the OPA344). Use your Arduino to record $v_o$ and to input a square wave with amplitude $[0; V_{cc}/4]$ as $v_i$ (test one or more frequencies of your choice). Discuss your findings." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import pylab as pl\n", - "import matplotlib.pyplot as plt\n", - "\n", - "fname = './data/L5.4.csv'\n", - "\n", - "dados = pl.loadtxt(fname, delimiter = ',')\n", - "\n", - "n = 250\n", - "\n", - "t = dados[:n, 0]-dados[0,0]\n", - "vi = dados[:n, 1]\n", - "vo = dados[:n, 2]\n", - "\n", - "plt.xlabel('Time (us)', color = \"#00a0e4\")\n", - "plt.ylabel('ADC', color = \"#00a0e4\")\n", - "\n", - "plt.plot(t, vi, color = \"#00a0e4\")\n", - "plt.plot(t, vo, color = \"#5756d6\")\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "5) Repeat Exercise 4 with $R_f = 0\\Omega$ and discuss your findings." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fname = './data/L5.5.csv'\n", - "\n", - "dados = pl.loadtxt(fname, delimiter = ',')\n", - "\n", - "n = 250\n", - "\n", - "t = dados[:n, 0]-dados[0,0]\n", - "vi = dados[:n, 1]\n", - "vo = dados[:n, 2]\n", - "\n", - "plt.xlabel('Time (us)', color = \"#00a0e4\")\n", - "plt.ylabel('ADC', color = \"#00a0e4\")\n", - "\n", - "plt.plot(t, vi, color = \"#00a0e4\")\n", - "plt.plot(t, vo, color = \"#5756d6\")\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
\n", - " Please provide us your feedback here. \n", - "
\n", - " Suggestions are welcome! \n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```Contributors: Prof. João Sanches; Prof. Hugo Plácido da Silva; Joana Pinto```" - ] - } - ], - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": [" #
Active Circuits with an Operational Amplifier
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Basic active circuits with an OpAmp "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Keywords \n", "```Operational Amplifiers```, ```Circuit Analysis```, ```Arduino```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Contributor(s):** Afonso Raposo, Joana Pinto, Prof. Jo\u00e3o Sanches; Prof. Hugo Silva\n", "\n", "**Date of creation:** dd/mm/aa\n", "\n", "**Last update:** 2021"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# I. Introduction\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Background
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This session aims at introducing the student to the operational amplifier (OpAmp) and its basic configurations: Voltage follower, inverter and non-inverter."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " If you have difficulties with the hardware setup, use Tinkercad.
Files with pre-recorded data are also provided for some experiments.\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
2. Objectives
\n", "* Experiment different OpAmp configurations\n", "* Use Arduino-type systems as a basic function generator and signal visualizer \n", "* Explore experimental characterization of active electronic circuits\n", "\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
3. Materials (optional)
\n", "* Arduino IDE\n", "* 1x Breadboard\n", "* 5x Jumper wires\n", "* 4x 1kOhm resistors\n", "* 4x 10kOhm resistors\n", "* 1x 100nF capacitor\n", "* 1x OPA344PA OpAmp\n", "* 1x Arduino (or analogous device)\n", "* 1x USB cable"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# II. Experimental\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Consider the following active circuits represented in Figure 1 and Figure 2.\n", "\n", "
\n", " Note
\n", "
\n", " The datasheet for the OPA344 OpAmp can be found at:
https://www.ti.com/lit/ds/sbos107a/sbos107a.pdf\n", "
\n", "
\n", "\n", "\n", "\n", "
Figure 1 - Non-inverter OpAmp configuration
\n", "\n", "\n", "\n", "
Figure 2 - Inverter OpAmp configuration
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# III. Explore\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Quizz
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["1) Derive its transfer function for both configurations with and without the capacitor."]}, {"cell_type": "markdown", "metadata": {}, "source": ["2) Simulate the circuits for several input signals (sinusoidal, square, triangular and noise) and frequencies."]}, {"cell_type": "markdown", "metadata": {}, "source": ["3) Compute the input and output impedances (use the The\u0301venin\u2019s theorem)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["4) Assemble the non-inverter configuration on a breadboard without the capacitor ($V- = 0V$ and $V+ = V_{cc}$ on the OPA344). Use your Arduino to record $v_o$ and to input a square wave with amplitude $[0; V_{cc}/4]$ as $v_i$ (test one or more frequencies of your choice). Discuss your findings."]}, {"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAY0AAAEKCAYAAADuEgmxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAIABJREFUeJztvXt8HNd15/k91d1oPPkGQQogxYcoWZRtSTaj+JFk4siKFNsTKcmuht6MB5tRRtkZOWN7M59ESnZnnJlo45nM7iT7ydgZJY6DnTiWmYcjfWYc27KcrOVkI5qyZUuiXpQoioD4AN8ACDTQXWf/qFvdDZB4kOq+p8G6388Hn6quru57L6q6zr3nd8+5oqoEAoFAILAUIusKBAKBQGD5EIxGIBAIBJZMMBqBQCAQWDLBaAQCgUBgyQSjEQgEAoElE4xGIBAIBJZMMBqBQCAQWDLBaAQCgUBgyQSjEQgEAoElk2/ml4vIJ4CfBxR4Bvg5oBP4IrAFeA24W1VPu/MfAO4BKsC/VNWvLvT969at0y1btjSp9oFAIHBl8tRTT51Q1d7L+aw0K42IiPQD3wJ2quqkiOwBvgzsBE6p6qdE5H5gtar+iojsBL4A3AJcBXwduFZVK/OVsWvXLt23b19T6h8IBAJXKiLylKruupzPNts9lQc6RCRPMsJ4A7gTGHLvDwF3uf07gYdVtaSqB4EDJAYkEAgEAi1C04yGqo4A/xF4HTgCnFXVrwF9qnrEnXYU6HP7/cDhuq8YdscCgUAg0CI0zWiIyGqS0cNWEndTl4j84/pzNPGNXZJ/TETuFZF9IrJvdHS0YfUNBAKBwOI00z31fuCgqo6q6gzwF8B7gGMishHAbY+780eATXWfH3DHZqGqD6nqLlXd1dt7WTpOIBAIBC6TZhqN14F3iUiniAhwK/A88Cgw6M4ZBB5x+48Cu0WkKCJbgR3A3ibWLxAIBAKXSNOm3KrqkyLyZ8B3gDLwXeAhoBvYIyL3AIeAu935z7kZVvvd+fctNHMqEAgEAv5p2pRbH4Qpt4FAIHDpvJkpt00N7mt1KrHy4rkyAly7Ik8ukup7xyYrPH+2TEdOuHZFnlfHy/QWIzZ15ThZinl1rMJbVubpKQgHxiqMnK/QkRPetjpPZ94+0L6+bevaI144W6bi+gcDnTm29+RIvIYJqsrrExUOjldoi+CGVQVWti3cjpNTFV4Zq3Ddyvyi5zabmVh5/kyZzrzQlRdeOlcmEnjLyjyjUzF7T0xzvqz8oy0drG3Pzfs96f/hfFm5flWheiy9xgCFCH5gbRttOZn3e3wwVVH+8vVJVOGnru6gPSfV/0NHXujOC8PnK1zTk9y/YzPK+vaI6+bc6/WUKsqzZ2YYm0lulu68sK494pHXp+htj/jgQLvptVZVXhmrMOyuRU7g+pV51rlrOhMre09MU46T3/TGztq1rm9bbzHiLSvzRAJPn5rh7IzS35njmp4cYzPKC2fLbOvJVb/XmrPTMa+OldnSnefQRJnrVxYoGt1/mTQa3z4xzS3//cKZV5154ac2t3NuWvnKG1PMxJf+3cUI9n5wPW9fU2hATS+Nr78xxe5vnuYf9LXxzWPTnChdRgMWIFf3ED4+VfvuSODLt67l9v72hpa3FIYnKvzsE6fYe2KaqSU4M+978mx1/+Y1Bda3Rzx2pER8kQH3NT05Rs7HTFYufHNDR8Tnf3gNP7ax+Gaqf1kcm6zwlr88xpnpuno9cXrJn+/OC9t78rx0rsxkRenvjOjOR7x0rrzoVMaf39HJ779n9eVV/E1Qqig7vnSMwxPzX+T17RECHJta2n2fGsTXxuf/zq3dOf7Xnd189PruS61yQ3jvl0d5Y7LC6FTMRLl2dXasyPF771ptcv9l0mhc1ZHjX9/YA8D2njyqyqvjFYYnKvzZoUn6OiLuu66LDw60M15WXjxbZltPnuNTFY5PxfTkhW11P7pNnTm29+R55swMH9t7lkMTZROjsf9smZOlmL94fYqf2tzOXZs7UFVOlGLeuirpmajCgbFytadWT197xHUr80xV4JnTMxc8LKcqynNnZviBtW1s6sqxoiD0tkf8z397hgNjZW731dA6njo5zTePTTO4vZMfv6rIRFk5X1Z2rspTUXjuzAy97TluWVdgugKPHp5kRqEcK/99uMTzZ8t87Pouegq13nNfe8RMDF97Y4oPDiSjqIHOHNf05BGBk6WYf/T/nuKrb0yZ/GhHzlc4M63s3tLBPTs6AfjW8WkUqqPm82VloqwMdOU4cK7M9p48a4sRh89X+PaJaV4+V+ZHN3SyohDxyliZibLy01e3054Tdq4ssK49+X+cmIp5faLMhwba+Ymvn2R8xsadPTYTc3iiwh39RX56c0f1WpQqyjOnZzg3oxyeqDBRVu7e0sHKNmH/mTKnpmsGJCewc2Vh1v/htfEKv/q2Hq7pyfPKWJnDzmNw7Yrk9e88P84XDk6aGY3vnpqhryPiw1s7eN+GIocnKqwtRnzq2TE++/JEMBq+6O/K8es3rbjoe5997+X3ola2JcNFK5koLffU7o2sLs7vQnjfEm60Dw4sbdRwwnXvrdqcjhA+sbObGy9iqO+YM/qpN+YPvmPh7/7YzvkfFG2R2F1nt/3ZbR28/6qkfel2KfyT7Z2XVW5bTmjs2HXppG3+hwPt/LNru2a9N98I97arFv7Ouf+Hi/0uHnujxHjZTvdVEpfqp965ctbxn93WydRFRsA+yKTRaBapm9jqh5U+QOdxVzeFyOkiZm12W9/eXREu6tLyQVpuvSblAwFiI0tZbbPncpPrbGc0Yr14mzvyQkfeRtOwV2yvIMRdXrOHieuP+byV0rKs2qwGhhKSH47Vo6TaOfBcbiQt0GbPhtKyzZC02/e9vRjBaDSQ9OJa3WQWD9Bqm40NpXejYdgDTUv13eZkpOG3zBSrNkfYtRlwOlVrWY1gNBqIda/bwlVTc8kZPUCt3BZY9rr9jyjB9bqtXXKey7V0Q0IYaVzx1EYatg9Qn0P4tCTrh4nNSMNvmSl2Iw1LIdxoRImYuqeUYDSuaKq9buORhoV7Kgjh/qgJ4X7LDSMNv6jRiHIxgtFoIObuKYMflrX4bzG6AtseaE0I9y8KW7khzUaU2HkOrNq8GMFoNJD0wWUnhPsfwluL/xajq7S87LmnWqHNBobSuM0tZjOC0Wgk5iONOfXwgblLzmgInwjh2YpZaIUpt1lyT1lNM16MYDQaiHWv22LKbU0Itxb//ZZr2wO1EYVbY6Tht1xLN6RVmxcjGI0GUut1G/VA3dZnpHBmhXAM22wmhNulTjEbUbbASKPFbEYwGo3E3D01T8qBZmLdZjMh3PQB6urgudxECLfBVgi3ITbQKJdCMBoNpBXcU95dFsbif7aF8OzknrIVwm3b3GI2o3lGQ0SuE5Gn6/7OicjHRWSNiDwmIi+77eq6zzwgIgdE5EURsci0/aawnn4aoyY3mOUD1EwgJXuicBDC/ZK5Kbeq+qKq3qSqNwHvBM4DXwLuBx5X1R3A4+41IrIT2A3cANwBfFpEWmPZrCWSxZEGuAeocQBUyD3VfLIphBv+ntM6ZHT21K3AK6p6CLgTGHLHh4C73P6dwMOqWlLVg8AB4BZP9WsI5tNPsTEapkFfbpstIdyJwiEivOm0wkijtUyGP6OxG/iC2+9T1SNu/yjQ5/b7gcN1nxl2x5YNNVHYbv6+RUZM0x6o4ZRb6weofyHcLveUlShsG/mfUSFcRNqAnwT+dO57mvgWLumaiMi9IrJPRPaNjl64zrclWXVPmfq6q3XwP3vK3lVjIYR7LbKKmXuqBSY8tJjN8NJZ+QngO6p6zL0+JiIbAdz2uDs+Amyq+9yAOzYLVX1IVXep6q7e3t4mVvvSsZ5+aieE2z1AgxDuj6RzkK0oeMuV+zInhNfxYWquKYBHgUG3Pwg8Und8t4gURWQrsAPY66F+DcM+91QWhfBkm8UeaDaFcN+JKYMQPpemrhEuIl3AbcAv1B3+FLBHRO4BDgF3A6jqcyKyB9gPlIH7VLXSzPo1miCE+8diidu0POuMryYjjayNKIMQfgFNNRqqOgGsnXPsJMlsqoud/yDwYDPr1ExaQwj3TxDC/WImCptGhGdRCHd1aDGrESLCG0hrCOH+77DWEML9ltsK7infl1poBfHfb7ktcZ1tip+XYDQaiL0QbnODtUZEuO+ZRC3QA/VcbiYjwrF0Q2Z0ym2WaI2Rhv9yBbvkfVnugYbcU83H0g0ZRhoZIL2hLafc2gnhNmSzB1qrg08yOdJogVF0GGlcwZi7p0yFcKMeqKEonEkhPGMPUNvU6K4OLTblNhiNBmLunsKmV5JZIdxvkVXshPBWcMn5LbcVIv9by2QEo9FQWmPKrcHsKex7oCYR4da9bs/lRmKfhymLiSmDe+oKxnykYSWEG440ar3ukHuq2WRzpBGE8LkEo9FAzDUNMyHcNveUmY5jUC5YC+HZEv9D7qkLCUajgZgvfZrRiHAzHcfaPZVJITw7uaeCEJ4RrOfv2wnhdrmnspZvK8tCuMXoKmttXoxgNBqM5fRTq5GGtRBuNboyn3LruVzbOA0bUViwXHgq2Qb31BWO5Q/LKveUtRBuNtLImCic1dxTQQifTTAaDca01032HqB2S9za90BDRHjzsewQhSm3GcH6JrNx1Rj2QDMthPvPw2Q/k8i/EA61zAM+sQpcXYxgNBqM9fz97EWEByHcF1kVwsGm3Wo0ulqMphoNEVklIn8mIi+IyPMi8m4RWSMij4nIy267uu78B0TkgIi8KCK3N7NuzcLyh2UrhGdL/A9CuF+sROFq7JXfYpMyMzrl9neAr6jqW4AbgeeB+4HHVXUH8Lh7jYjsBHYDNwB3AJ8WkVyT69dwLKefZjUiPGs6jp0Qnr02pw9siw5C5oRwEVkJ/AjwWQBVnVbVM8CdwJA7bQi4y+3fCTysqiVVPQgcAG5pVv2ahb0QbpB7ylwI949g3+v276rJYO6p1D3luVzIphC+FRgFPici3xWRPxCRLqBPVY+4c44CfW6/Hzhc9/lhd2xZYSuEZzUi3MJQ2qZOSevgE+t4HLBJjQ42I40sCuF54B3AZ1T1ZmAC54pK0WRKwiVdDhG5V0T2ici+0dHRhlW2Udi6LexyT9kJ4YbuKf/FAoZCuOHsKXsh3H+7syiEDwPDqvqke/1nJEbkmIhsBHDb4+79EWBT3ecH3LFZqOpDqrpLVXf19vY2rfKXi+X002xGhFtNM26BKbeey20NIdx/Zl8IQng9TbvvVPUocFhErnOHbgX2A48Cg+7YIPCI238U2C0iRRHZCuwA9jarfs3CNCIcSyHcrgea1Sm3QQhvPtXlDoIQXiXf5O//ReDzItIGvAr8HImh2iMi9wCHgLsBVPU5EdlDYljKwH2qWmly/RqO9fRTkwcoGRXCjafcZisi3EgIdyXajjQMCl+AphoNVX0a2HWRt26d5/wHgQebWadmYy+E2+SeymJAY/ZE4VYQ//2WaznSSEeyrWY0QkR4g7HsdWcyItzIUEZil3uqJoR79u+3QGxKEMLtCUajwVj+sKxEYeseqImOg60QbnKdDbWrbAvhBoUvQDAaDcZy+qmtEG6D3TRjWyHcYkJNEML90qpCeDAaDcY695SdEB5yT/kiVjX54Vq7IcFCCHfley4XMjjlNqtYD+FNHqBBCPeKpUvO0vUK2co9lcWI8ExiL4Tb5J7KWuoU64hwmzbbr9xnJ4R7LpjaGh4tZjOC0Wg0tkK4VUS4tRBuMM0YMRXCs9g5SOvgk5p7yn/LgxCeEWwjwm1E4cymRvdfLGArhIPNKnY1IdxzksYghF9AMBoNxjr3VPYiwrOZe8pKCAebDkIQwluHYDQajPUQ3k4Iz2DuKbMZY0Yjymr5/svOZkT47Dq0CsFoNBjL6afZjQj3j5BNIRyMRGGs8m0ZtjlEhGeDLOaesk5YaGYoM9hmsHVPZWqN8JB7KhtYrx2dTSE8e7mnLIVwm5FGgp17KuSeSglGo8FYB0CZCKQZXHjKXgi3mXILNsGrNSE85J6yJhiNBmOde8qkB2o6uspe7inLiPC0fN9YicKtIYS3ltUIRqPBZNK/TwZTp2BrKK2i4JPy/WPlqglC+IUEo9FgLJc+NU2pkTVDmUUhHLsHqFXuKVshPCFT7ikReU1EnhGRp0Vknzu2RkQeE5GX3XZ13fkPiMgBEXlRRG5vZt2aRRZzT9kL4f7LNY8INyg3vbUshXCr3FMmEeEZzj31PlW9SVXTZV/vBx5X1R3A4+41IrIT2A3cANwBfFpEch7q11Csc09lUwgPuad8kO0ptyH3VIrFM+ZOYMjtDwF31R1/WFVLqnoQOADcYlC/N4V17qnsCeHZG2nYC+EGD9C0DhnKPVVts/+iF6TZRkOBr4vIUyJyrzvWp6pH3P5RoM/t9wOH6z477I4tK6x73XZCuA2WuacsI/+zKIRbttmig6DVkUZrmY18k7//h1R1RETWA4+JyAv1b6qqisgl3YPO+NwLsHnz5sbVtEHYR4T7xzYPUxaFcKNpxtXy/ZdtP7ryX3YmhXBVHXHb48CXSNxNx0RkI4DbHnenjwCb6j4+4I7N/c6HVHWXqu7q7e1tZvUviyzmngpCuF/shHDb3FOW+bZshPBk22I2o3lGQ0S6RKQn3Qd+HHgWeBQYdKcNAo+4/UeB3SJSFJGtwA5gb7Pq1yzshfDs5Z7KZER4BnNPmY40/BdtNs14MZrpnuoDvuR6J3ngT1T1KyLybWCPiNwDHALuBlDV50RkD7AfKAP3qWqlifVrCta5p7IphGcr91Ss2cs9FWNsKC3Ff+8lL0zTjIaqvgrceJHjJ4Fb5/nMg8CDzaqTDyKEcsbWWYiwS52SzYjw7OWeUqsMzi0hhBsUvgAhIrzBZFEIt3XJ2eWeAqMeqOEsubR835i7p0LuqSrBaDQY+4hw/+VGhqlTLNuclu8bK1HYOiI8COGtQTAaDcZy6dMghPsjLdMk6MtMCHcPUP9F2y9x67/oEBGeFWwjwrMqhPsvt5r91H/RQQj3iG1EeHZzT2UK6163Ve4pWx3HIvdUrXzf2Avh/rGPCLcR/+vr0CoEo9FgbIXw7OWeCjEL/qgJ4Vbif7Y6B5mMCM8ilrmnzFw12CZpNBldVUVhgx4o2UyNbppvy1QIby2rEYxGgzHvdRuUa517ytK/byOEG08z9l+0/ZRb/0WHkUZWsFz6NAjh/rAM+oqxmjFml3sqNlsL3m7KbVwdabQWwWg0GPOlT42m3GYuoNFtrdwWWRtp2Avh/tEWzT0VjEaDMY8Iz9hIw24VO9sptyZtrivfN1ZTbmtCuF3uqWA0rnBshfDs5Z5Kpp/6pyaE+y/bXgjPXu6pEBFeIxiNBmM+0jAo19YlZzTN2G2zmHsqCOF+sFridjGC0WgwWcw9ZZk6JZtCePZyT2VVCG8tc5EQjEaDsZ5+GoRwP2RTCLfLPZVNIbz19AxYwGjI0MhvydDIL1zk+C/I0Minmlut5Yu5eyqTQrj/cu2FcP/lZlsI91+21ehqMRYaafwY8NBFjv8+8KGlFiAiORH5roj8N/d6jYg8JiIvu+3qunMfEJEDIvKiiNy+1DJaiSy6p+yFcDuB1E4IN0ipYS6E+8d+4anWYyGjUdTB/gv+UzrYf6mxRR8Dnq97fT/wuKruAB53rxGRncBu4AbgDuDTIpK7hHJaAquRRirIZk8Iz2JEeFaF8OzlnlpuI41JGRrZMfegOza5lC8XkQHgg8Af1B2+Exhy+0PAXXXHH1bVkqoeBA4AtyylnFbCasptWqSVEG6ae8pUCLeYv59FITyDqdGNphkvxkJrhP9r4K9kaOQ3gKfcsV3AA8DHl/j9vw38MtBTd6xPVY+4/aNAn9vvB/6+7rxhd2xZYdXrri7Y4r/oWg9U1fv0wCCE+yObEeF22tWyE8J1sP+vSEYB7wP+yP29D/gZHez/8mJfLCIfAo6r6lPznaOJT+WS7kERuVdE9onIvtHR0Uv5qBeSXrfN3P2kfEtft/eizVOjZ2kRplQ7ypIoHITwC1lopIEO9j8LDF7md78X+EkR+QDQDqwQkT8GjonIRlU9IiIbgePu/BFgU93nB9yx2XVSfQgn0O/atcvKKzIvVkK4pXvK0tdtJ4TbPUCtouBNU6ObC+H+WY5CODI0MihDI0/J0MiE+9snQyP/ZClfrKoPqOqAqm4hEbi/oar/GHiUmiEaBB5x+48Cu0WkKCJbgR3A3stokylW/n3LjJiWD9DsCuF2uacyGRFulHuqFUcaC8VpDJJoF/8KuIpEX/hl4GMyNPKRN1Hmp4DbRORl4P3uNar6HLAH2A98BbhPVStvohwT7IRwu4yYYuiqMc89ZVC2WWp0wym3SZuzlXuqVSPCF3JP/XPgp3Sw/7W6Y9+QoZGfAR4G/utSC1HVvwH+xu2fBG6d57wHgQeX+r2tiFWgW2sI4f7LzmLuqawK4VnTrtRoRLkYCz1jVswxGAC4YyuaVaHljlVKjZoQ7r9s0x5oBh8mZlNu0/IzJArbLjy1zNxTLByLsaQ4jSxilXuqKoQb5Z6qr4NPzN1TmZpyayj+ByG8ZVjIPXW9DI18/yLHBdjWpPose8yFcMted6aEcNvsp1mbJRdyT7UOCxqNixwTkmmxDzSnOsufLE65rQ7h/Rdtn3vKe8l2orC1G9J0pJGhNi/GvEZDB/sPpfsyNHIz8D8B/yNwEPjz5ldteWInhLvZU/6Ltp9hkrEpt9aisJ0Qnq3OgVUC0sWY12jI0Mi1wIfd3wngi4DoYP/7PNVtWWKV8TW7QnjIPeWLLCbvM21zi86eWsg99QLwBPAhHew/ACBDI5/wUqtljFXuqZoQ7p9MCuFumy0hPNlmSwh32pVB2ctRCP9pkkjuv5ahka+QxGa0YhtaiizmnsqkEG7oqrETwu0eoHbLvbrygxBeZaGEhX+pg/27gbcAf00SHb5ehkY+I0MjP+6rgsuNbArhCdkSwm1zT9lGhPsvO4vZjJedEJ6ig/0TwJ8AfyJDI6tJxPBfAb7W5LotSzIZEZ4O4bM00nDbkHvKD6qQM7i5LbWrZSeEXwwd7D9NkmH2YsvABrAUwpNSbYVw/2Vb/bDsp9z6xzr3VOZW7mvRkYZFx/SKJgjh/lDLacZua7Vedtb8+1mNCG/F2VPBaDSYbEeE+215K0wzthpVZi8i3EoID7mn5hKMRoOpX/rUJzUh3HAI77lc09GVsUvOxj1l+AA1FsKtAnZb0GYEo9ForPz7tkJ4svXtqTFd4jbknvKKtUvOLAapBa1GMBoNxuqHZSuE2/RA05FNNoXwjOWewjoiPOSeSglGo8FY+UCzKYTPLt8nISLcL4kQbhe4mqXR1WI07fcmIu0isldEviciz4nIr7vja0TkMRF52W1X133mARE5ICIvisjtzapbM7ESSLMphNtPMzaJ/rcShd02pEb3g9U048VoZietBPyYqt4I3ATcISLvAu4HHlfVHcDj7jUispMkbckNwB3Ap0Uk18T6NQWrHmgWI8IzK4RbicKmEeFGSRozKP4vRtN+b5ow7l4W3J8CdwJD7vgQcJfbvxN4WFVLqnoQOADc0qz6NQurHmhNCDccwpsJ4X7LhVaICPdfrmXuKUtRODKaRq/LLfdUIxCRnIg8DRwHHlPVJ4E+VT3iTjkK9Ln9fuBw3ceH3bG533mviOwTkX2jo6NNrP3lYTXSaIWYBTMh3DL3lPeSWyEi3H/ZVoYSkv91EMJrNNVoqGpFVW8CBoBbROStc95XLtGIq+pDqrpLVXf19vY2sLaNwcptYSuE2/RAq0J4xnzd5gsSGUXBWz1A7UYaGRPC61HVMySZcu8AjonIRgC3Pe5OGyFZSjZlwB1bVojRA9RSFLYylK3QZitR2CSlhtvaCeE2T1CrzNWWo6uFaObsqV4RWeX2O4DbSBZ2ehQYdKcNAo+4/UeB3SJSFJGtwA5gb7Pq1yyyONKoCeFGUfBeS3VlGve6TUZXGUyNDraZqy2mGS/GJWW5vUQ2AkNuBlQE7FHV/yYi/x+wR0TuAQ4BdwOo6nMisgfYD5SB+1S10sT6NQXrKbemUbNZ0nHc1kYIz96UW0tROBKbzNWt6p5qmtFQ1e8DN1/k+Eng1nk+8yDwYLPq5AOr7KdpaTYpNRJ8i8I1Idw/9hHh/rGefmorhPsvN+Seygh2/n1Xvt9ikzKNRho1ITxbuaesI8KtoqNthXADNyStOdIIRqPBVN0Wnsu1FYWNck+1QhS8/6LNck9ZriFimSY8COGzCUajwWQx91QmI8LdNku5p+yFcJsnqK0Q3no0UwhvWSYmKjzzzAQHX51iamr+R93p02VOnprh6qvb2b69ne7uHCdGZxgbr7C+t8AbR6aZmdZZ506tyVNY6V84ixVWn63w1d87QumWFUxMVOjpybFuXYGxsQojwyVUYcPGNkpTMadOlQGIIugfKLJ9ewdHjkzz0ovnF3W5rO8rgMLx4zOUSjHPH5pi9VV572uIxKoUZpQDXzvN5741Vj3e1Z1jYKBIHCvDwyV6unMcOTrNmdNlbn3/avbvP8+BlydZt67Atu3tHDs6PavNK1bmWLEiz8FXpzj0+hRr1xRYvTpf/d58DoYnK+Rn1LvbQlUhVk5+8xyf++551q8vgMDYWIWBgSJtheTeO3p0mldemeLkyRmu3tzOtu3trOhJsvIcer3EU/vGqFRg48Y2tm9vp9gecepUmQ19BY4dn2FqMmbFyhz9VxU5c7bMk38/Rkd3xLqcxWrZSbsr3xnncy+VAOjsili3rsDRozP0rS+wYkXStrHxCsOH3b2+oY3SdEyppKxdm+fQoRIHD07R051j+/Z2+vuLTM8oh1+fYnpaWbMmT3tHxJEj02jdY6F3bAbdZtBmIFIYH6/w7LMTvPD87N/m1q3t/Oj7VnmvVyaNxpEj0/z2fxohl4OOjvnTW3V3R6xZU+DJvz/HNx4/Uz0eRRDHUCgIxWJUPberO8fI3nHWvbPDZKTRe6rMyEslPv/SVLWOKcWiEEXC5GRysKsrQkSYmUl+VCnt7RH5/Pz9mzhWzp9PvqOzMzn33LkK6zrERAjvPVXmtafQFTV7AAAeIklEQVQmOdYRkcsl9T5/vlJt+9xrtW/fOLlc8oPbt2+MJ544S0fdZ1WT9qkm/6Orr27n9den2L8/nvW9ANftKJpc55VjMSf/boK/KUr12s293pAY93VrCzz55Dm+8Y0zs967fmcnnZ0Rhw5NsXfv2KzvyOWS+yD9PwAMDBQ5cGCSa9blTHrdUSlm5m/H+ZuiUChE1WtxsXbPvddFktFZe3vEli1Fjh2b5rvfHa+2rVAQ2tqEiYnk/Pr7YXKywraVOeIf9NbUKrHCqr88zc9/7gRw4W9zejoORsMXW7a08+D/sYXNm4sUCos7N1SV48dnmJqKWbkyT1dXxMmTZXp7C9WbC+DQa1P8yq8cJFKbpU/FFflbv7WVDRvbmJiIOXu2TEdHRG9vAYBTp8q0tQk9Pflq244dm+GVVybp7srxtrd3ES3i+zhzJhmlrFqVZ2Kiwj3/9CVE1UQIj9wD49/+uy1s2lQEoFSKOXZsGhFhw4YCExMxbW1CHMP3vzfODW/tYuXKPFNTiSFYvTo/a9bZ+fMVxscr9PYWZh1Pv1cV/rdfe41C2ajNrtCPf2KArVvbgcTAHT06Q+ye6GvW5Gdd49HRmepDtKcnx5o1hep3jo2VmZ5WVq3KMzo6w9q1+eqDeXR0hra2iA0bCvzSL73KqxWbkQZu8v1HPtLH+29bTakUc/p0mfXrC5w4UWtbe3uUjL5IRv+JQYiq56b3dtq2fE7o29BGPi+Mj1colWLWrKndD7/5m6/zxKEps2nGuXMV3vrWTj74obXceOPiv00fZNJo5PPC9u0dSz5fROjra5t1bMOGtgvOy7leQBTbxGmkD9C+DW0UChGrVkWsWjX7Eq9dW5j1Onmwtl20PfNR/52p0YxiGyE8bXOubsBYLEZs3txefb1qVa1j8J73rqzut7dHtLdf2Gno7MzR2XnhCLT+e3N5QWKbacZpm/M5mXUtUqM5FxFh/fr5r29qXGD2fd3ZmePqq2v/h3xeiGZs/PvpDyr9jRWLUbWu87Wt3jDOvb/ntg2guztHd/fsY/mcu85GuaeIYce1Hdx8c7f38ucjCOENpPoAVTVxW6QjjYXcS40mLUvURghPe931Iz4fRDmxuc6a+LmTOvgtO5eT5DpbRMFX3HX2/MSKIpvrDIkrWEgMVysRjEYDSXu7ojZTbiM3md3nEDZyd1CkFhHhWjWUvo1GLmd0nQGpG2n4JO8MpcVAQ+aMNHyRyyf/b5PBVXUUHYzGFYulq0ZJbu7IoCcmAhKr99xTs1w1vh8mOXHX2f+Mseroynubca4ar8UCdg/QfHV05bVYANIkSsFoXMHU3FM2QnikidvEN4mrxiYivOqq8W0s0163QZurvW7Pbc6l19lvsUDSKUnr4JOkc2AzusKozYsRjEYDqfn3/d9ktkbDTggX99T2P9Kw0XHqR1e+Rxr5vLgOkddiAdDqA9RvuTnLkUba5habrhSMRgOp+vfN3FPqvccNzkVlJYQbuS1q7imvxc4eaRj1uk1mT5ldZwzF/7QOYaRxxVI/k8hGCLe5waIcJq6a2PgBaiWEW80Yy+XchAcDZ41YGQ03tdrEPWV0nRcjGI0GMlvT8Ft22us20zRMYhaUyMxtgUmve3Zsio2hzNRII5JkkkcQwqsEo9FAUteQxU2W9rot3VO+c0+lrhqJ/K8jUh1peG9z/TRjr0VXXXKWvW7f04xzeZsRJVA1lHnP13kxmrnc6yYR+WsR2S8iz4nIx9zxNSLymIi87Lar6z7zgIgcEJEXReT2ZtWtWYgIEmEywyR26SUseiW5vE1AY+Kq8RuXkpJLRWHP5ZpPMzYKdCMN7vMsCttOM7aZWr0YzeyXloFfUtWdwLuA+0RkJ3A/8Liq7gAed69x7+0GbgDuAD7tlopdVlRdNQYr94mVeyqySamR5p6yuEvyhkJ4qmn4NpY1UdhrsUCdpuG5zflckpA9rlhGwWfEaKjqEVX9jtsfA54H+oE7gSF32hBwl9u/E3hYVUuqehA4ANzSrPo1i8gqUthNufXtsoBar9tKCLcYaVTjNDyXG2OTLgbcdTZzT9Xq4JO0E+bbDQl2UfCL4cUDLiJbSNYLfxLoU9Uj7q2jQJ/b7wcO131s2B1bVohRrhrFPUCtRhpWrhpV7zmYIPEzW/S650vS6INadLSB2TCMCAerkUaytegILkTTjYaIdAN/DnxcVc/Vv6eJ+b6kqyEi94rIPhHZNzo62sCaNobISCyMNZlJZKJpuJlE/qOjNZkxZqFppNc5Q3EakWF0tJjNknMjDYt1fbM45VZECiQG4/Oq+hfu8DER2eje3wgcd8dHgE11Hx9wx2ahqg+p6i5V3dXb29u8yl8mUWTXAxUr91QuFYX9Njp11ViMrvL5dHTlu802iSnBdsqtXZxGso0rXot1hbo6ZMVoSDIH8rPA86r6f9W99Sgw6PYHgUfqju8WkaKIbAV2AHubVb9mkeZhshDCLdOIWDxMUlHYwj2Vi2ziNFSTB6gYTK22csnNnmbsP04DaqK0V1o0TqOZE9jeC3wEeEZEnnbHfhX4FLBHRO4BDgF3A6jqcyKyB9hPMvPqPlW1sO9viiiXDKVNhPBYTXLvW7lqYk0z+9pMubWLCDd0yZl1iIzcU3l791SrxWk0zWio6reA+e7sW+f5zIPAg82qkw+sFm2xHGlU5+97Lrf6ALVwT+Vskvels+QsphnnqqKw33Kto+DBRggng3EamSSyyknkhvBWmoYYTLlNRWGT2VNG008T95SajTQANPbbPUhnBoL/acbVXr7J0n3JptXcU8FoNBjLNOFRbHOD5dI2ey43zT1l02ZBDKPgxSjyH4xGGoYzxgA828mEYDSygVWqhaQ3ZvkANfB1a+qe8losUO+e8t3mdJqx12KBmijs+wEaa23Kre92pxqhjRCewSm3WcTOPZVGhFsJ4Uap0Y1Sp+SN1o5OpxnbjDRs/PtKkvYfi8SUqTvMYKRhlZhyMYLRaDBRhGnuKRtNw3AVOyNDmc8JOYWK5yFlmpjSZJqxoRCeZDO2yHbg6mDinnKzp4IQfmVjtY5yOtKwuMFyuchwjXBjUdgoTsOizakorJ4NpeISU5rEpqQjDf9WIw1otLjWCxGMRoOJcjaLtiSzp9QkI2Y+byWEW46ukv9zxXevG8sgThv/fm10ZeeSM4kYM0qBvxjBaDSYWgCU33LT3pjFIvRJwkKL6Gi1i01J/ftlz9NPLacZG80kSrUri5GGae4po3xbixGMRoOxTo1uERGer6ZG998DFUPxHwweoG6asYV/v9brtkmRY9JmwzgNq9QpixGMRoNJU2qYCOFGRqO6upnncpNV7NRM/Af/M4nSzoHFSKMqCnsXwtU8Ct5mpJFsgqZxhZPMJPKfe6oSq91Monwykyj2LZAaTzMG/yONtNdtNWMM8N7rTmYG2mgatTZ7LzrJt9VirikIRqPhJLmn/I9mU0HWIk9N1ddtEB1tlhrdKCdRGuhmlaQRbDSNxD3lt1yoT1hok0bEwiW3GMFoNJg0J5H3B2gl+SVbZMS0mkmUrhFuMtKoBrr5LdcyCr7mqrHRrizjNCwiwq3E/8VowSotb6wiwtMHtokQnva6y54fJrhpxkbraQDEnrvd6TRjm2zGydZECDeL/DeMCI8VwkjjyicXYZN7yjB6NH2Y2ERHZ2ukEVtOM67GafgtNxlpqKkQbpVGxKLNixGMRoPJ5cQkJ1GlnGytptyCQU4itQ/u8z2rJk1MaZGwsJq8z3sMkpouPJVUwso9FUYaVzy5vE3207SXbyKE5200jYoqOevZU75dci2g45hEhJsF97kd79pVshZ8pjQNEflDETkuIs/WHVsjIo+JyMtuu7ruvQdE5ICIvCgitzerXs0mn0tcJt5dNa2gafh+mKRtNnTJeR9pGAY0VkVhIzekqUsuQ+L/YjTTjv0RcMecY/cDj6vqDuBx9xoR2QnsBm5wn/m0SCt68xbHatGWdPZUwSCNiFV6iUq6SI2h28J3bEptjXCvxQI142zikrOK03BtFot4nDhjmoaqfhM4NefwncCQ2x8C7qo7/rCqllT1IHAAuKVZdWsm+er0U88PE8MHqFWbK85qmMammLhq1KTNlr1uK0OZLt8RRho1fF+GPlU94vaPAn1uvx84XHfesDt2ASJyr4jsE5F9o6OjzavpZWKW/dQ9vAommkay9e3rrjg9wSQ2xazXnawFbyoK+/bvYxfEKSJoZDXSsFk3ZTHMZBZNsttd8lNGVR9S1V2ququ3t7cJNXtz1IyG37vMNCI8FcJ998YM11CuxmkY5Z6yyGacM1pPI06XuDV6gEqE9ym3YaRR45iIbARw2+Pu+Aiwqe68AXds2ZH2ur1HClfTKFsG9/ktN3WHmSRpNAr6qk0ztnRP+S23Ns3Y6AEaifcpt+k040xpGvPwKDDo9geBR+qO7xaRoohsBXYAez3XrSHkrDSNdKRhGafhuQdaMWxzzkjTqMRKhNHKfUaG0jKzL5A8JS3a3KJxGk0b5IrIF4AfBdaJyDDwb4BPAXtE5B7gEHA3gKo+JyJ7gP1AGbhP1WStrDeNVcxCbNnrNlo7ujrSMBWF/ZZbNpxmXDVUFkK4URoRIBlpmK0FnyGjoaofnuetW+c5/0HgwWbVxxfp7CX/MQtpcJ/XYpMyrZYBrRpKr8UCdjOJUkNpMZPIakEiSyEcACMhPCQszAhmI40sxixU7HQcq0WYLKcZiwgq/kdX1V63katGIjF0ybXeSCMYjQZTFcJ998aqIw0LITzZek/eZ+iqsfLvW+YYA0z8+4qa5RgDkpGG0UqcYaSRAdKefsV3TiJDUTgyGmlU821lyT0V27mnADQSMFvi1lLT8FtkMs24NTWNYDQaTKHqnvKd8dXuAVrNfupdCE+2hbz/29gqTXg5HWkYtBmAyH/C19pSxn7LTZGcW9vCI5ZR8IvRglVa3litHW3q3zdKjZ5mmM1SwsLYcHQFOFHY9+jKFW040jARwoOmkQ2s1pawdE+Z5SRKF56ydE95F8Jd+QaGEoBIDEZXdh0icLqC59FVNU4jGI0rn4JR0Bem/n1XBaPRlYUoHEXJTCLfvppKdS14o4eJSZuTrVWvWyLxPrqqRsEHo3HlU0sjksGRhlFmX6sHqIqBjuM0DTP3VM6/q6acTjM2elqJQZxGNaCxBZ/QLVil5Y1VnIbtGuG2Oo5Fm4FEFDYK7svSlNuqe8rQJSfeHQcaNI2skE659f0wSQVZm5TZrg5GIw2LdPDgpp8aCeFmeZjEIKVGdRTttdgqNrOnkqWMw0gjAxTMIsLtRxreZxIZ97otoqNrwX12U269jzSqqVNs2iwR3kcaZWMdZyGC0WgwtSUxjSLCLeI08jaaRlqe1UgjeYAazRizarNBr7timFcNUiHcb5nVHGPBaFz51JYB9VuuxknPV8T/TRZFglILMPSFtdtCIzGYcmsbpyHi3yWXBjRa5FWDZNqrb6MxUzZ2Qy5AMBoNpmAUp4EzGlZYzCRKe922Iw2/RVZaYXTlOyLcMEkjpO4pv40uGwbrLkYwGg2mUI1Z8J/xVQ2vphrMJKolLLTy7xsI4YZTqyHtddvEaVgEcYJrs3dD6YxGCy7CFIxGgykUbNxTyUjD7gbTSPwvA2rs30+EcKs1RLI3urLy70dREjPhk9QlF9xTS0BE7hCRF0XkgIjcb12fSyXnZrX4n3JrPNKwcE+lM0ys2m0R9GUc0GiRh8m6zRKJmXuqFYVwo/kIF0dEcsB/Bm4DhoFvi8ijqrrftmZLJ+31TpeVkYmLP0VXtgndhQhV5e9Hp9nQkWNrT56TUxWeOD7NdSvyXLcyz0wM3zs1w4lSzK0bi0xWlImZ2TdvJLChI7I3GhFMzcQMT1QQkujdvvaIqQqcKsWMliq8cT7mtquKFCKhVFFOTMV05IU1xVrFy7FybDKmLQfritG8wv5kWZmacSk1DIO+4liZmInpKkScmY4vuD5z6S4IK9uS9o7PxJydTs4/OxPz0rkyP9JXpCMnnCrFrGgTegoRo1MV9p6YoTMnTEzbtjnJw5Tc2+k1FhFeHSvzd8enac8Jd/QXkzZNK0cmK7w+UeGGVXm68xF9HUnbj00m7RB3/5ZjmI6VrrxwohQzXffTOTWZvLBzySWdg++fmuGVsTL9nTluXFOgmBNmYuWxN0pc1RnxtlUFRODoZExeoLc94nxZyUdCIUraXN+XXF0UOnLC2Iyywt0T0xVldCrm+Hmn4wSjsSi3AAdU9VUAEXkYuJNk7fBlQdrrfXK4xNv/YJjitDLeGdEzEXO+I2KyKFTywrUr8vSdqfAtlDiCGypw5lyZE105FNgwFTMpMCVCz0RMW144VRR6T5ZpKyunVuYY60q+d0sxonN0hh5D/2cUCUdPl9nx+TeoRMJMQVgbwZlYKU4qnZMxJ1bnuKEzRzfC62+UyE8qlRwU1xfIr4hoP13h9FjMWA56JmJWFYRtA0XGi8KRyQpdFdhSgVe6Ip4dK3PDkWmuxSagMWk0TJ2tcP3vvM6Wze3sOztTfSh0TCk9EzEqcK47YrpN6JxUitMxXesLkBdGJip0TcTkKjDZLnSfjyl1R0wWhIpCV1m5mYgD58rV7+09VWYHUDD65eZygpSUH/zdw5zrjtgwrXR053hZteq1KuZgLCegsHI8Tv4PkNyvFWifjmFS6T4fc647YmptHp2JKZxXOorCcHtEua59609WeA/QXrC5zl1tEadj+OBDI5ztiZgpCKsmY3Z05BgvRhw/Ok0Uw4q1ecpdEUdOl1kxHtOdg2PFiJlOoRgJpcmYleMxUQwTncJUR0RHe8RJhR9e38b0dMyh16YonFc6p2JuAtqM2rwQrWY0+oHDda+HgR80qstlEUWC5OEtB6d5y8Hpi58koDlBysrP5CVxZV3KkF+46AyW1X2Fy6lyQ9jeVyB/sMTAsXEACl0RMxMx0ibojIJCvl0oTyUV3zLr05PQJjB9kUbtPU8H0Ft3aEcOrlUghnyb3Y9q2/o2hp89z3u+PQnfnuQnl/zJSQDeucSz113k2MYem5/uu69u54mXpvih70zOOn79nPOidoFyLX39xYjyEJcvPH7TPOdfv9bm/v6xbR388d+O8d7vTl70/WvnvJ6v/vORX5ljIh6nbTxmy5x/1w9vab/Eb2s+4ntu/UKIyP8A3KGqP+9efwT4QVX9aN059wL3AmzevPmdhw4dMqnrQjzz/QmOHJ1m1cocPT15jo9Os6GvjZMnZxifiDl9eoaxcxXe9vYu9j93nmJ7xDXb2+npyTPyRglV2LixjVIpplRSBgbaiGMYHi5x9eYi6/vaeO3gFEePTXPVVUU6OyKOHptm9eo827Z1mLR5YqLCCy+c5+TJMpPnK4yMTNO7vsDYWIXu7hxXbWzj2Wcn2LixjY7OHGvX5tnQ18b5yZiDr07y2mslNm8usnFjG2NjFQY2FYkiGD5cYnwisahtbcKaNXme2jdOsT1i3do8V/UXeetbu0zaPD0dMzo6w9hYheHh0qzcW91dEQObisQxHD5cYnIyZuXKHCvcNU7PXbs2T7EYcepUmb6+AsePzzDpXDcdHRGbNhWrkysAzpwuMz2j3Hxzt8+mVqlUlKNHpzl/PuaNN0qs721jbKzMmbOVWeeMDJcotEVcc007mzYVUfd/6OnJsW5dgfaOiDVr8hw7NsOrr05RLEr1fjh8uFTNN5XS2RnxnvesMBlVxnHS5tJUzOuHS5RKytq1edqLESdPztA/UKStLeLIGyXOnK3Q3h6xebO7f4enGR9P/jdtBWHT5tnnjlfvHWXjVW1s397Bhg1tiEBbW0Rvb3MMpYg8paq7LuuzLWY03g18UlVvd68fAFDV37zY+bt27dJ9+/Z5rGEgEAgsf96M0Wi12VPfBnaIyFYRaQN2A48a1ykQCAQCjpbSNFS1LCIfBb4K5IA/VNXnjKsVCAQCAUdLGQ0AVf0y8GXregQCgUDgQlrNPRUIBAKBFiYYjUAgEAgsmWA0AoFAILBkgtEIBAKBwJIJRiMQCAQCS6algvsuFREZBd5MSPg64ESDqrNcCG3OBqHN2eBy23y1qvYuftqFLGuj8WYRkX2XGxW5XAltzgahzdnAos3BPRUIBAKBJROMRiAQCASWTNaNxkPWFTAgtDkbhDZnA+9tzrSmEQgEAoFLI+sjjUAgEAhcApk0GiJyh4i8KCIHROR+6/osBRF5TUSeEZGnRWSfO7ZGRB4TkZfddnXd+Q+49r0oIrfXHX+n+54DIvJ/i1uEW0SKIvJFd/xJEdlS95lBV8bLIjLY5Hb+oYgcF5Fn646ZttOl6n/SfeaLLm1/s9v8SREZcdf7aRH5wJXSZhHZJCJ/LSL7ReQ5EfmYO36lX+f52r28rrWqZuqPJOX6K8A2oA34HrDTul5LqPdrwLo5x/4DcL/bvx/4925/p2tXEdjq2ptz7+0F3kWyaOxfAT/hjv8L4Pfc/m7gi25/DfCq2652+6ub2M4fAd4BPNsq7QT2ALvd/u8B/9xDmz8J/KuLnLvs2wxsBN7h9nuAl1y7rvTrPF+7l9W1Nn8Y+v4D3g18te71A8AD1vVaQr1f40Kj8SKwse6GfPFibSJZn+Td7pwX6o5/GPgv9ee4/TxJwJDUn+Pe+y/Ah5vc1i3MfoCatdO9dwLIX+z+aWKb53uQXDFtriv3EeC2LFznedq9rK51Ft1T/cDhutfD7liro8DXReQpSdZJB+hT1SNu/yjQ5/bna2O/2597fNZnVLUMnAXWLvBdPrFs51rgjDt37nc1m18Uke8791Xqqrmi2uzcJzcDT5Kh6zyn3bCMrnUWjcZy5YdU9SbgJ4D7RORH6t/UpJtwxU+Fy0o7gc+QuFBvAo4A/6dtdRqPiHQDfw58XFXP1b93JV/ni7R7WV3rLBqNEWBT3esBd6ylUdURtz0OfAm4BTgmIhsB3Pa4O32+No64/bnHZ31GRPLASuDkAt/lE8t2ngRWuXPnflfTUNVjqlpR1Rj4fZLrPav+c+qzrNosIgWSB+fnVfUv3OEr/jpfrN3L7lo302fXin8kfr5XSYSlVAi/wbpei9S5C+ip2/874A7gt5gtHP4Ht38DswW0V5lfQPuAO34fswW0PW5/DXCQRDxb7fbXNLm9W5jt3zdtJ/CnzBYK/4WHNm+s2/8E8PCV0mZXv/8H+O05x6/o67xAu5fVtTZ/IFr8AR8gmbnwCvBr1vVZQn23uZvne8BzaZ1J/JGPAy8DX6fuYQ78mmvfi7iZFe74LuBZ997vUgvwbHc3zwF3Q26r+8w/dccPAD/X5LZ+gWSIPkPiX73Hup3u/7/XHf9ToOihzf8VeAb4PvDonAfLsm4z8EMkrqfvA0+7vw9k4DrP1+5lda1DRHggEAgElkwWNY1AIBAIXCbBaAQCgUBgyQSjEQgEAoElE4xGIBAIBJZMMBqBQCAQWDLBaAQCgUBgyeQXPyUQuDKRoZE0LgBgA1ABRt3r8zrY/54mlHkz8FEd7L/nMj77MPC/62D/y42uVyCwVILRCGQWHew/SZLvBxka+SQwroP9/7HJxf4q8BuX+dnPAL8M/LPGVScQuDSC0QgELoIMjYzrYH+3DI38KPDrwBngbSRrDzwDfAzoAO7Swf5XZGiklyQFw2b3FR/Xwf6/nfOdPcDbdbD/e+71J6kzVDI08izwIZLRzh6SPEA54N/pYP8XgSeAP5KhkbwO9pcJBAwImkYgsDg3Av8LcD3wEeBaHey/BfgD4BfdOb8D/Ccd7P8B4Gfce3NJUz8sxh3AGzrYf6MO9r8V+AqADvbHJKkebnwTbQkE3hTBaAQCi/NtHew/ooP9JZJcP19zx58hSTQI8H7gd2Vo5GmS/EErZGike873bKSmmSzEM8BtMjTy72Vo5Id1sP9s3XvHgasusx2BwJsmuKcCgcUp1e3Hda9jar+hCHiXDvZPLfA9kyQJ5VLKzO64tQPoYP9LMjTyDpJkdr8hQyOP62D/v607Z/KyWhEINIAw0ggEGsPXqLmqkKGRmy5yzvPANXWvXyNZGxxnJLa6/atIZm/9MUm68HfUfeZalubiCgSaQjAagUBj+JfALhka+b4Mjewn0UBmoYP9LwArnSAOyWI8a2Ro5DngoyTp+iER3Pc6V9e/wc22kqGRPmBSB/uPNrcpgcD8hNTogYBHZGjkE8CYDvZfTChfymfP6WD/Zxtfs0BgaYSRRiDgl88wWyO5FM4AQw2sSyBwyYSRRiAQCASWTBhpBAKBQGDJBKMRCAQCgSUTjEYgEAgElkwwGoFAIBBYMsFoBAKBQGDJ/P+nD0yP3RmKEAAAAABJRU5ErkJggg==", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["import pylab as pl\n", "import matplotlib.pyplot as plt\n", "\n", "fname = './data/L5.4.csv'\n", "\n", "dados = pl.loadtxt(fname, delimiter = ',')\n", "\n", "n = 250\n", "\n", "t = dados[:n, 0]-dados[0,0]\n", "vi = dados[:n, 1]\n", "vo = dados[:n, 2]\n", "\n", "plt.xlabel('Time (us)', color = \"#00a0e4\")\n", "plt.ylabel('ADC', color = \"#00a0e4\")\n", "\n", "plt.plot(t, vi, color = \"#00a0e4\")\n", "plt.plot(t, vo, color = \"#5756d6\")\n", "\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["5) Repeat Exercise 4 with $R_f = 0\\Omega$ and discuss your findings."]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [{"data": {"image/png": "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", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["fname = './data/L5.5.csv'\n", "\n", "dados = pl.loadtxt(fname, delimiter = ',')\n", "\n", "n = 250\n", "\n", "t = dados[:n, 0]-dados[0,0]\n", "vi = dados[:n, 1]\n", "vo = dados[:n, 2]\n", "\n", "plt.xlabel('Time (us)', color = \"#00a0e4\")\n", "plt.ylabel('ADC', color = \"#00a0e4\")\n", "\n", "plt.plot(t, vi, color = \"#00a0e4\")\n", "plt.plot(t, vo, color = \"#5756d6\")\n", "\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", "
\n", " Please provide us your feedback here. \n", "
\n", " Suggestions are welcome! \n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["```Contributors: Prof. Jo\u00e3o Sanches; Prof. Hugo Pl\u00e1cido da Silva; Joana Pinto```"]}], "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.8.8"}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file diff --git a/B.Instrumentation/B003 Introduction to the Laboratory Equipment/B003 Introduction to the Laboratory Equipment.ipynb b/B.Instrumentation/B003 Introduction to the Laboratory Equipment/B003 Introduction to the Laboratory Equipment.ipynb index 4944d86..3575416 100755 --- a/B.Instrumentation/B003 Introduction to the Laboratory Equipment/B003 Introduction to the Laboratory Equipment.ipynb +++ b/B.Instrumentation/B003 Introduction to the Laboratory Equipment/B003 Introduction to the Laboratory Equipment.ipynb @@ -1,449 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "2162fad8", - "metadata": {}, - "source": [ - "![scientisst-notebooks_top-banner](https://raw.githubusercontent.com/scientisst/notebooks/59632d3d477981a3b1cc12157e12bbdcdb45def8/_Resources/top-banner.png)" - ] - }, - { - "cell_type": "markdown", - "id": "5b6a1998", - "metadata": {}, - "source": [ - "# B003 Introduction to the Laboratory Equipment " - ] - }, - { - "cell_type": "markdown", - "id": "c5be1c9e", - "metadata": {}, - "source": [ - "### Keywords \n", - "`Electronics`, `Equipment`, `Instrumentation`, `Arduino`, `Arduino IDE`, `Seeeduino Nano`" - ] - }, - { - "cell_type": "markdown", - "id": "1eb41d14", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributor(s):** Ana Sofia Carmo, Afonso Raposo, Prof. Hugo Silva\n", - "\n", - "**Date of creation:** 2021\n", - "\n", - "**Last update:** 09/2022" - ] - }, - { - "cell_type": "markdown", - "id": "93f954d7", - "metadata": {}, - "source": [ - "### Description \n", - "\n", - "In this lab, you will become familiar with the main tools (or _instruments_) available in an instrumentation laboratory and how to properly setup your workspace for the upcoming sessions and projects. This guide includes a rundown of **laboratory equipment**, as well as the configuration of the **Arduino-based development tools** on your computer." - ] - }, - { - "cell_type": "markdown", - "id": "5bb201d0", - "metadata": {}, - "source": [ - "### Materials \n", - "\n", - "**_Workbench equipment_**\n", - "* DC power supply with probes\n", - "* Multimeter\n", - "* Function generator\n", - "* Oscilloscope\n", - "\n", - "**_Complementary equipment_**\n", - "* 1 pair of power supply probes\n", - "* 1 pair of multimeter probe\n", - "* 1 pair of oscilloscope probes\n", - "* BNC to alligator clips breakout cable\n", - "* 1x Seeeduino Nano\n", - "* 1x Breadboard\n", - "* 1x 220Ω resistor" - ] - }, - { - "cell_type": "markdown", - "id": "ec46c012", - "metadata": {}, - "source": [ - "***\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "c641fd15", - "metadata": {}, - "source": [ - "# 1. DC Power Supply & Multimeter " - ] - }, - { - "cell_type": "markdown", - "id": "34873fdd", - "metadata": {}, - "source": [ - "## 1.1. An Introduction to the Tools " - ] - }, - { - "cell_type": "markdown", - "id": "0d6124d5", - "metadata": {}, - "source": [ - "### DC Power Supply \n", - "\n", - "A DC power supply is a type of power supply that gives direct current (DC) voltage to power a device. Because DC power supplies are commonly used on an engineer's or technician's bench workbench to power experimental circuits, they are also often called a \"workbench power supply\".\n", - "\n", - "A typical DC power supply is shown in the figure below, along with the connection probes:\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "

Figure 1: Example of a DC power supply (left) and connection probes (right).

\n", - "\n", - "The power supply has knobs that allow the selection of the desired voltage and the current it outputs. Remember that if the current is 0, the output will have 0 volts. Some power supplies even have an `OUTPUT` button that allows toggling the output voltage between `ON` and `OFF`.\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 2: Example of DC power supply (with an OUTPUT button).

\n", - "\n", - "\n", - "> ⚠️ **WARNING:** To protect your circuit, you should always adjust the limit current (i.e. the highest value it can reach)! To do so, proceed as such: \n", - "> 1. Without the probes connected to the circuit, adjust the `VOLTAGE` to a value between 0.5V and 5V.\n", - "> 2. Turn the `OUTPUT` to `OFF` and temporarilly short-circuit the power supply terminals (+) and (-) using the connection probes.\n", - "> 3. Turn the `OUTPUT` to `ON` and adjust the `CURRENT` control to the desired limit value.\n", - "> 4. Remove the short circuit and set the `VOLTAGE` to the desired value.\n", - "> 5. Turn the `OUTPUT` to `OFF` again before connecting the power supply to your circuit.\n", - "> 6. Turn the `OUTPUT` to `ON` and check if the `VOLTAGE` value is as expected. If it is not, the current limit may have been set to too low - in this case readjust it slightly.\n", - "\n", - "You can easily power your circuit with a power supply, for example by connecting and then wrapping a wire around each alligator clips and connecting the other end to the circuit, as such:\n", - "\n", - "

\n", - "\n", - " \n", - "

\n", - "

Figure 3: Powering a circuit using wires connected and wrapped around the alligator clips.

\n", - "\n", - "> ⚠️ **WARNING:** The power supply is capable of damaging your circuit. Always be extra careful when using this device. Always verify the selected voltage before connecting to your circuit. Voltages too high can damage your circuit components and even be dangerous to you." - ] - }, - { - "cell_type": "markdown", - "id": "0a5f86dc", - "metadata": {}, - "source": [ - "### Multimeter \n", - "\n", - "A Multimeter is known as a multitester or VOM (Volt-Ohm Milliammeter). It is an all-in-one electronic measuring instrument that combines several measurement functions, including **AC/DC voltage, current and resistance**. Thus, it is crucial for analysis and/or troubleshooting of your circuit or electronic designs!\n", - "\n", - "A typical multimeter nowadays looks like the left image below. As you can see, it has a selection knob that allows you to select what to measure, according to the symbols on the right. \n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "

Figure 4: Example of multimeter (left) and symbol legend (right, src: https://www.techtonions.com/how-to-use-a-multimeter/).

\n", - "\n", - "A very useful feature of multimeters is the ability to test for **continuity**. This can be used to check if there is a short circuit in your circuit or to verify if something is not connected properly. Just turn the knob to the continuity test position and press the blue button. Now if you touch the probes together the multimeter will *beep*.\n", - "\n", - "Note the ports on the bottom. There will always be at least 3 ports:\n", - "\n", - "> **COM**: stands for common, and it will always be connected to Ground or ‘-‘ in any DC circuit. As a convention, always connect the Black probe to the this port. \n", - "> **mA μA / VΩ**: used for measuring voltage (V), current in milliampere range (mA), resistance (Ω), and more. \n", - "> **10A**: used to measure current only in the Ampere range (>200mA). \n", - "\n", - "> ⚡ **TIP:** Additionally, some multimeters have numbers on the knob. This allows you to choose the range/magnitude of your measure. For example, if you want to measure the voltage of a 1.5V battery, you'd choose the the 2V range on the DC voltage (if you chose the 20V range, you'd still get a reading, but it would be less accurate). " - ] - }, - { - "cell_type": "markdown", - "id": "64038589", - "metadata": {}, - "source": [ - "## 1.2. Testing the Tools: Powering a Circuit \n", - "\n", - "1. Following the indications on the [DC Power Supply section](#section:power_supply), set the `VOLTAGE` to 5V.\n", - "\n", - "2. Assemble your simple circuit, as shown in [Figure 3](#powering_circuit), and turn the `OUTPUT` to `ON`. \n", - "\n", - "3. Turn on your multimeter and set it to read DC voltage; by placing the multimeter probes in parallel with the resistor, check the voltage value.\n", - "\n", - "4. Now, set the multimeter to read current; by placing the multimeter probes in series with the resistor, check the current value." - ] - }, - { - "cell_type": "markdown", - "id": "7ab8633b", - "metadata": {}, - "source": [ - "# 2. Function Generator & Oscilloscope " - ] - }, - { - "cell_type": "markdown", - "id": "6c2efc7d", - "metadata": {}, - "source": [ - "## 2.1. An Introduction to the Tools " - ] - }, - { - "cell_type": "markdown", - "id": "ff86c13b", - "metadata": {}, - "source": [ - "### Function Generator
\n", - "\n", - "A function generator is usually a piece of electronic equipment or software used to generate different types of periodic signals with known characteristics (amplitude, waveform and frequency). Some of the most common waveforms produced by the function generator are the sine wave, square wave, triangular wave, and sawtooth shapes.\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 5: Types of waves often produced by the function generator.

\n", - "\n", - "Function generators are used in the development, test, and repair of electronic equipment. For example, they may be used as a signal source to test amplifiers or to introduce an error signal into a control loop. A typical function generator looks like this:\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "

Figure 6: Example of a function generator (left) and BNC to alligator clips breakout cable used with it (right).

\n", - "\n", - "To start using a function generator, make sure you connect the BNC to alligator clips breakout cable to the `MAIN` connector of the generator.\n", - "\n", - "The function generator allows you to select the characteristics of the output signal. You can select its shape, frequency, amplitude, introduce an offset, among other parameters. As an example, to select a frequency of 10 Hz, you'd press the `FREQ` button, then press the number `10`, and finally, press the `Hz/Vpp` button.\n", - "\n", - "> ⚠️ **WARNING:** If the `OUTPUT` button is not activated, no signal is generated.\n", - "\n", - "> ⚠️ **WARNING:** Like the DC Power Supply, the function generator can be dangerous to you and your circuit. Always make sure you selected the correct settings before turning on the `OUTPUT` button. A badly configured function generator can damage electronic components." - ] - }, - { - "cell_type": "markdown", - "id": "20c74226", - "metadata": {}, - "source": [ - "### Oscilloscope
\n", - "\n", - "An oscilloscope is a piece of equipment used to measure electrical signals, typically consisting of time-varying voltages on a two-dimensional grid (`time x voltage`). When connected to a power source through a probe, the oscilloscope displays the corresponding real-time waveform immediately. A typical oscilloscope looks like this:\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 7: Example of an oscilloscope.

\n", - "\n", - "You can adjust what you see on the main screen by using the knobs and buttons on the right side. Modern oscilloscopes have an `AUTO` adjustment button which automatically adjusts the window to fit the signal being measured. Just try it!\n", - "\n", - "Another very useful feature of digital oscilloscopes is that you can measure characteristics of the signals (e.g. amplitude, frequency, and peak voltage), by pressing the `MEASURE` button.\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 8: Example of signal characteristics provided by the oscilloscope after pressing the MEASURE button.

\n", - "\n", - "To connect the oscilloscope to your circuit use oscilloscope probes. The alligator clip side of the probes connects to `GROUND`, while the other side measures the output signal, as illustrated below:\n", - "\n", - "\n", - " \n", - "\n", - "\n", - "
\n", - "
\n", - "

Figure 9: Oscilloscope probes (left) connected to a circuit (right).

\n", - "\n", - "If you look to the side of the oscilloscope probes, you will see a red button/switch which allows you to choose the attenuation factor of the probe (between `x1` and `x10`). The attenuation enables the impedance presented to the circuit under test to be increased by a factor of ten, which enables more accurate measurements to be made.\n", - "\n", - "\n", - "> ⚠️ **WARNING:** Make sure the attenuation of the probe and the one shown on the oscilloscope are the same by pressing `CH[n] > Probe` (where `n` is the channel) and choosing the appropriate factor. \n", - "\n", - "\n", - "Finally, the oscilloscope allows you to save the current screen on an external USB in image format. To do so, insert the USB storage device, press `STORAGE` and select `Bit Map` in the type menu. Then select any storage position between 1 and 200 with the multifunction control knob, and press F4 (storage key) to complete the storage process." - ] - }, - { - "cell_type": "markdown", - "id": "5f6cd122", - "metadata": {}, - "source": [ - "## 2.2. Testing the Tools: Generating and Visualizing Waveforms \n", - "\n", - "1. Turn on the function generator and oscilloscope.\n", - "2. Connect the BNC to alligator clips breakout cables (`MAIN` output of the generator) directly to the oscilloscope cable (`CH1` of the oscilloscope).\n", - "3. Following the indications on the [Function Generator section](#section:function_generator), set the controls of the function generator to produce a sine wave of about 1000 Hz frequency and a few volts amplitude. \n", - "4. Following the indications on the [Oscilloscope section](#section:oscilloscope), visualize the signal in the oscilloscope, verify if the waveform characteristics correspond to the expected, and save the screen to a USB." - ] - }, - { - "cell_type": "markdown", - "id": "1d87701a", - "metadata": {}, - "source": [ - "# 3. Development Environment " - ] - }, - { - "cell_type": "markdown", - "id": "4f6b7c0e", - "metadata": {}, - "source": [ - "## 3.1. Setting up the Development Environment " - ] - }, - { - "cell_type": "markdown", - "id": "bb04ad51", - "metadata": {}, - "source": [ - "### Installing Arduino IDE \n", - "\n", - "The Arduino Integrated Development Environment (IDE) is an open-source software that connects to the Arduino hardware to upload programs and communicate with it.\n", - "\n", - "You need to download and install the latest version of the Arduino IDE from: [https://www.arduino.cc/en/software](https://www.arduino.cc/en/software). \n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 10: Download the latest version of the Arduino IDE.

\n", - "\n", - "> ⚠️ **WARNING:** Make sure you install the latest version of the Arduino IDE (and not the hourly builds). If you don’t have the latest version installed, uninstall Arduino IDE and install it again, otherwise, it may not work.\n", - "\n", - "\n", - "> 📋 **NOTE:** To get a better understanding of the Arduino Software (IDE) and its functionalities, a more comprehensive guide on this topic is available at: [https://www.arduino.cc/en/Guide/Environment](https://www.arduino.cc/en/Guide/Environment).\n", - "\n", - "
\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "4a963950", - "metadata": {}, - "source": [ - "### Installing Seeed Studio Boards in Arduino IDE \n", - "\n", - "The Arduino IDE can be used to program other Arduino-based devices. In these laboratory sessions we will be using the Seeeduino Nano.\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 11: Seeduino Nano.

\n", - "\n", - "\n", - "However, only the official Arduino boards are already supported by the software upon installation (you can browse them on `Tools > Board`). To install the add-on support for other supported devices (such as the Seeeduino Nano), follow these next instructions:\n", - "\n", - "1. In the Arduino IDE, go to `File > Preferences`:
\n", - "\n", - "

\n", - "\n", - "

\n", - "

Figure 12: Open the Preferences window on Arduino IDE.

\n", - "\n", - "2. Enter the following links in `Additional Board Manager URLs` (in the `Preferences` window) as shown in the figure below. Then, click the `OK` button.:\n", - "\n", - "```\n", - "https://raw.githubusercontent.com/Seeed-Studio/Seeed_Platform/master/package_legacy_seeeduino_boards_index.json\n", - "```\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 13: Enter the links into the highlighted text box.

\n", - "\n", - "> 📋 **NOTE:** If you already have the URL of another board in the \"Additional Board Manager URLs\" field, you can separate the URLs with a comma.\n", - "\n", - "3. Open the Boards Manager by accessing `Tools > Board > Boards Manager`\n", - "\n", - "

\n", - " \n", - "

\n", - "

Figure 14: Open the Boards Manager window.

\n", - "\n", - "4. Search for Seeeduino Nano and press the \"Install\" button for the \"**Seeeduino AVR** by **Seeed Studio**\".\n", - "\n", - "5. The add-on should be installed after a few seconds." - ] - }, - { - "cell_type": "markdown", - "id": "e949ebb9", - "metadata": {}, - "source": [ - "## 3.2. Testing the Tools: Compiling and Uploading \n", - "\n", - "When you open a `New` (blank) sketch, you should see something like this:\n", - "\n", - "\n", - " \n", - "\n", - "\n", - "
\n", - "

Figure 15: Overview of the Arduino IDE Graphical User Interface (GUI). Hovering with the mouse pointer on each button shows a summary of its function.

\n", - "\n", - "Now, let's upload this blank sketch to make sure that everything is working in your environment:\n", - "\n", - "1. Select the correct board by clicking on `Tools > Board`.\n", - "\n", - "2. Click on the verify tool (checkmark). After a few seconds, we can see the result of the action in the console (box in the bottom).\n", - "\n", - "3. Click on the upload button, and it will start uploading the sketch to the board. When it is finished, a notification will appear. If there are any problems when uploading, the errors will be listed here as well." - ] - }, - { - "cell_type": "markdown", - "id": "d63f993c", - "metadata": {}, - "source": [ - "***" - ] - }, - { - "cell_type": "markdown", - "id": "35f8749e", - "metadata": {}, - "source": [ - "![scientisst-notebooks_bottom-banner](./_Resources/bottom-banner.png)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.10.0" - }, - "vscode": { - "interpreter": { - "hash": "7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{"cells": [{"cell_type": "markdown", "id": "2162fad8", "metadata": {}, "source": ["![scientisst-notebooks_top-banner](https://raw.githubusercontent.com/scientisst/notebooks/59632d3d477981a3b1cc12157e12bbdcdb45def8/_Resources/top-banner.png)"]}, {"cell_type": "markdown", "id": "5b6a1998", "metadata": {}, "source": ["# B003 Introduction to the Laboratory Equipment "]}, {"cell_type": "markdown", "id": "c5be1c9e", "metadata": {}, "source": ["### Keywords \n", "`Electronics`, `Equipment`, `Instrumentation`, `Arduino`, `Arduino IDE`, `Seeeduino Nano`"]}, {"cell_type": "markdown", "id": "1eb41d14", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Contributor(s):** Ana Sofia Carmo, Afonso Raposo, Prof. Hugo Silva\n", "\n", "**Date of creation:** 2021\n", "\n", "**Last update:** 09/2022"]}, {"cell_type": "markdown", "id": "93f954d7", "metadata": {}, "source": ["### Description \n", "\n", "In this lab, you will become familiar with the main tools (or _instruments_) available in an instrumentation laboratory and how to properly setup your workspace for the upcoming sessions and projects. This guide includes a rundown of **laboratory equipment**, as well as the configuration of the **Arduino-based development tools** on your computer."]}, {"cell_type": "markdown", "id": "5bb201d0", "metadata": {}, "source": ["### Materials \n", "\n", "**_Workbench equipment_**\n", "* DC power supply with probes\n", "* Multimeter\n", "* Function generator\n", "* Oscilloscope\n", "\n", "**_Complementary equipment_**\n", "* 1 pair of power supply probes\n", "* 1 pair of multimeter probe\n", "* 1 pair of oscilloscope probes\n", "* BNC to alligator clips breakout cable\n", "* 1x Seeeduino Nano\n", "* 1x Breadboard\n", "* 1x 220\u03a9 resistor"]}, {"cell_type": "markdown", "id": "ec46c012", "metadata": {}, "source": ["***\n", "\n", "\n"]}, {"cell_type": "markdown", "id": "c641fd15", "metadata": {}, "source": ["# 1. DC Power Supply & Multimeter "]}, {"cell_type": "markdown", "id": "34873fdd", "metadata": {}, "source": ["## 1.1. An Introduction to the Tools "]}, {"cell_type": "markdown", "id": "0d6124d5", "metadata": {}, "source": ["### DC Power Supply
\n", "\n", "A DC power supply is a type of power supply that gives direct current (DC) voltage to power a device. Because DC power supplies are commonly used on an engineer's or technician's bench workbench to power experimental circuits, they are also often called a \"workbench power supply\".\n", "\n", "A typical DC power supply is shown in the figure below, along with the connection probes:\n", "\n", "\n", "\n", "\n", "
\n", "

Figure 1: Example of a DC power supply (left) and connection probes (right).

\n", "\n", "The power supply has knobs that allow the selection of the desired voltage and the current it outputs. Remember that if the current is 0, the output will have 0 volts. Some power supplies even have an `OUTPUT` button that allows toggling the output voltage between `ON` and `OFF`.\n", "\n", "

\n", " \n", "

\n", "

Figure 2: Example of DC power supply (with an OUTPUT button).

\n", "\n", "\n", "> \u26a0\ufe0f **WARNING:** To protect your circuit, you should always adjust the limit current (i.e. the highest value it can reach)! To do so, proceed as such: \n", "> 1. Without the probes connected to the circuit, adjust the `VOLTAGE` to a value between 0.5V and 5V.\n", "> 2. Turn the `OUTPUT` to `OFF` and temporarilly short-circuit the power supply terminals (+) and (-) using the connection probes.\n", "> 3. Turn the `OUTPUT` to `ON` and adjust the `CURRENT` control to the desired limit value.\n", "> 4. Remove the short circuit and set the `VOLTAGE` to the desired value.\n", "> 5. Turn the `OUTPUT` to `OFF` again before connecting the power supply to your circuit.\n", "> 6. Turn the `OUTPUT` to `ON` and check if the `VOLTAGE` value is as expected. If it is not, the current limit may have been set to too low - in this case readjust it slightly.\n", "\n", "You can easily power your circuit with a power supply, for example by connecting and then wrapping a wire around each alligator clips and connecting the other end to the circuit, as such:\n", "\n", "

\n", "\n", " \n", "

\n", "

Figure 3: Powering a circuit using wires connected and wrapped around the alligator clips.

\n", "\n", "> \u26a0\ufe0f **WARNING:** The power supply is capable of damaging your circuit. Always be extra careful when using this device. Always verify the selected voltage before connecting to your circuit. Voltages too high can damage your circuit components and even be dangerous to you."]}, {"cell_type": "markdown", "id": "0a5f86dc", "metadata": {}, "source": ["### Multimeter \n", "\n", "A Multimeter is known as a multitester or VOM (Volt-Ohm Milliammeter). It is an all-in-one electronic measuring instrument that combines several measurement functions, including **AC/DC voltage, current and resistance**. Thus, it is crucial for analysis and/or troubleshooting of your circuit or electronic designs!\n", "\n", "A typical multimeter nowadays looks like the left image below. As you can see, it has a selection knob that allows you to select what to measure, according to the symbols on the right. \n", "\n", "\n", "\n", "\n", "
\n", "

Figure 4: Example of multimeter (left) and symbol legend (right, src: https://www.techtonions.com/how-to-use-a-multimeter/).

\n", "\n", "A very useful feature of multimeters is the ability to test for **continuity**. This can be used to check if there is a short circuit in your circuit or to verify if something is not connected properly. Just turn the knob to the continuity test position and press the blue button. Now if you touch the probes together the multimeter will *beep*.\n", "\n", "Note the ports on the bottom. There will always be at least 3 ports:\n", "\n", "> **COM**: stands for common, and it will always be connected to Ground or \u2018-\u2018 in any DC circuit. As a convention, always connect the Black probe to the this port. \n", "> **mA \u03bcA / V\u03a9**: used for measuring voltage (V), current in milliampere range (mA), resistance (\u03a9), and more. \n", "> **10A**: used to measure current only in the Ampere range (>200mA). \n", "\n", "> \u26a1 **TIP:** Additionally, some multimeters have numbers on the knob. This allows you to choose the range/magnitude of your measure. For example, if you want to measure the voltage of a 1.5V battery, you'd choose the the 2V range on the DC voltage (if you chose the 20V range, you'd still get a reading, but it would be less accurate). "]}, {"cell_type": "markdown", "id": "64038589", "metadata": {}, "source": ["## 1.2. Testing the Tools: Powering a Circuit \n", "\n", "1. Following the indications on the [DC Power Supply section](#section:power_supply), set the `VOLTAGE` to 5V.\n", "\n", "2. Assemble your simple circuit, as shown in [Figure 3](#powering_circuit), and turn the `OUTPUT` to `ON`. \n", "\n", "3. Turn on your multimeter and set it to read DC voltage; by placing the multimeter probes in parallel with the resistor, check the voltage value.\n", "\n", "4. Now, set the multimeter to read current; by placing the multimeter probes in series with the resistor, check the current value."]}, {"cell_type": "markdown", "id": "7ab8633b", "metadata": {}, "source": ["# 2. Function Generator & Oscilloscope "]}, {"cell_type": "markdown", "id": "6c2efc7d", "metadata": {}, "source": ["## 2.1. An Introduction to the Tools "]}, {"cell_type": "markdown", "id": "ff86c13b", "metadata": {}, "source": ["### Function Generator
\n", "\n", "A function generator is usually a piece of electronic equipment or software used to generate different types of periodic signals with known characteristics (amplitude, waveform and frequency). Some of the most common waveforms produced by the function generator are the sine wave, square wave, triangular wave, and sawtooth shapes.\n", "\n", "

\n", " \n", "

\n", "

Figure 5: Types of waves often produced by the function generator.

\n", "\n", "Function generators are used in the development, test, and repair of electronic equipment. For example, they may be used as a signal source to test amplifiers or to introduce an error signal into a control loop. A typical function generator looks like this:\n", "\n", "\n", "\n", "\n", "
\n", "

Figure 6: Example of a function generator (left) and BNC to alligator clips breakout cable used with it (right).

\n", "\n", "To start using a function generator, make sure you connect the BNC to alligator clips breakout cable to the `MAIN` connector of the generator.\n", "\n", "The function generator allows you to select the characteristics of the output signal. You can select its shape, frequency, amplitude, introduce an offset, among other parameters. As an example, to select a frequency of 10 Hz, you'd press the `FREQ` button, then press the number `10`, and finally, press the `Hz/Vpp` button.\n", "\n", "> \u26a0\ufe0f **WARNING:** If the `OUTPUT` button is not activated, no signal is generated.\n", "\n", "> \u26a0\ufe0f **WARNING:** Like the DC Power Supply, the function generator can be dangerous to you and your circuit. Always make sure you selected the correct settings before turning on the `OUTPUT` button. A badly configured function generator can damage electronic components."]}, {"cell_type": "markdown", "id": "20c74226", "metadata": {}, "source": ["### Oscilloscope
\n", "\n", "An oscilloscope is a piece of equipment used to measure electrical signals, typically consisting of time-varying voltages on a two-dimensional grid (`time x voltage`). When connected to a power source through a probe, the oscilloscope displays the corresponding real-time waveform immediately. A typical oscilloscope looks like this:\n", "\n", "

\n", " \n", "

\n", "

Figure 7: Example of an oscilloscope.

\n", "\n", "You can adjust what you see on the main screen by using the knobs and buttons on the right side. Modern oscilloscopes have an `AUTO` adjustment button which automatically adjusts the window to fit the signal being measured. Just try it!\n", "\n", "Another very useful feature of digital oscilloscopes is that you can measure characteristics of the signals (e.g. amplitude, frequency, and peak voltage), by pressing the `MEASURE` button.\n", "\n", "

\n", " \n", "

\n", "

Figure 8: Example of signal characteristics provided by the oscilloscope after pressing the MEASURE button.

\n", "\n", "To connect the oscilloscope to your circuit use oscilloscope probes. The alligator clip side of the probes connects to `GROUND`, while the other side measures the output signal, as illustrated below:\n", "\n", "\n", " \n", "\n", "\n", "
\n", "
\n", "

Figure 9: Oscilloscope probes (left) connected to a circuit (right).

\n", "\n", "If you look to the side of the oscilloscope probes, you will see a red button/switch which allows you to choose the attenuation factor of the probe (between `x1` and `x10`). The attenuation enables the impedance presented to the circuit under test to be increased by a factor of ten, which enables more accurate measurements to be made.\n", "\n", "\n", "> \u26a0\ufe0f **WARNING:** Make sure the attenuation of the probe and the one shown on the oscilloscope are the same by pressing `CH[n] > Probe` (where `n` is the channel) and choosing the appropriate factor. \n", "\n", "\n", "Finally, the oscilloscope allows you to save the current screen on an external USB in image format. To do so, insert the USB storage device, press `STORAGE` and select `Bit Map` in the type menu. Then select any storage position between 1 and 200 with the multifunction control knob, and press F4 (storage key) to complete the storage process."]}, {"cell_type": "markdown", "id": "5f6cd122", "metadata": {}, "source": ["## 2.2. Testing the Tools: Generating and Visualizing Waveforms \n", "\n", "1. Turn on the function generator and oscilloscope.\n", "2. Connect the BNC to alligator clips breakout cables (`MAIN` output of the generator) directly to the oscilloscope cable (`CH1` of the oscilloscope).\n", "3. Following the indications on the [Function Generator section](#section:function_generator), set the controls of the function generator to produce a sine wave of about 1000 Hz frequency and a few volts amplitude. \n", "4. Following the indications on the [Oscilloscope section](#section:oscilloscope), visualize the signal in the oscilloscope, verify if the waveform characteristics correspond to the expected, and save the screen to a USB."]}, {"cell_type": "markdown", "id": "1d87701a", "metadata": {}, "source": ["# 3. Development Environment "]}, {"cell_type": "markdown", "id": "4f6b7c0e", "metadata": {}, "source": ["## 3.1. Setting up the Development Environment "]}, {"cell_type": "markdown", "id": "bb04ad51", "metadata": {}, "source": ["### Installing Arduino IDE \n", "\n", "The Arduino Integrated Development Environment (IDE) is an open-source software that connects to the Arduino hardware to upload programs and communicate with it.\n", "\n", "You need to download and install the latest version of the Arduino IDE from: [https://www.arduino.cc/en/software](https://www.arduino.cc/en/software). \n", "\n", "

\n", " \n", "

\n", "

Figure 10: Download the latest version of the Arduino IDE.

\n", "\n", "> \u26a0\ufe0f **WARNING:** Make sure you install the latest version of the Arduino IDE (and not the hourly builds). If you don\u2019t have the latest version installed, uninstall Arduino IDE and install it again, otherwise, it may not work.\n", "\n", "\n", "> \ud83d\udccb **NOTE:** To get a better understanding of the Arduino Software (IDE) and its functionalities, a more comprehensive guide on this topic is available at: [https://www.arduino.cc/en/Guide/Environment](https://www.arduino.cc/en/Guide/Environment).\n", "\n", "
\n", "\n"]}, {"cell_type": "markdown", "id": "4a963950", "metadata": {}, "source": ["### Installing Seeed Studio Boards in Arduino IDE \n", "\n", "The Arduino IDE can be used to program other Arduino-based devices. In these laboratory sessions we will be using the Seeeduino Nano.\n", "\n", "

\n", " \n", "

\n", "

Figure 11: Seeduino Nano.

\n", "\n", "\n", "However, only the official Arduino boards are already supported by the software upon installation (you can browse them on `Tools > Board`). To install the add-on support for other supported devices (such as the Seeeduino Nano), follow these next instructions:\n", "\n", "1. In the Arduino IDE, go to `File > Preferences`:
\n", "\n", "

\n", "\n", "

\n", "

Figure 12: Open the Preferences window on Arduino IDE.

\n", "\n", "2. Enter the following links in `Additional Board Manager URLs` (in the `Preferences` window) as shown in the figure below. Then, click the `OK` button.:\n", "\n", "```\n", "https://raw.githubusercontent.com/Seeed-Studio/Seeed_Platform/master/package_legacy_seeeduino_boards_index.json\n", "```\n", "\n", "

\n", " \n", "

\n", "

Figure 13: Enter the links into the highlighted text box.

\n", "\n", "> \ud83d\udccb **NOTE:** If you already have the URL of another board in the \"Additional Board Manager URLs\" field, you can separate the URLs with a comma.\n", "\n", "3. Open the Boards Manager by accessing `Tools > Board > Boards Manager`\n", "\n", "

\n", " \n", "

\n", "

Figure 14: Open the Boards Manager window.

\n", "\n", "4. Search for Seeeduino Nano and press the \"Install\" button for the \"**Seeeduino AVR** by **Seeed Studio**\".\n", "\n", "5. The add-on should be installed after a few seconds."]}, {"cell_type": "markdown", "id": "e949ebb9", "metadata": {}, "source": ["## 3.2. Testing the Tools: Compiling and Uploading \n", "\n", "When you open a `New` (blank) sketch, you should see something like this:\n", "\n", "\n", " \n", "\n", "\n", "
\n", "

Figure 15: Overview of the Arduino IDE Graphical User Interface (GUI). Hovering with the mouse pointer on each button shows a summary of its function.

\n", "\n", "Now, let's upload this blank sketch to make sure that everything is working in your environment:\n", "\n", "1. Select the correct board by clicking on `Tools > Board`.\n", "\n", "2. Click on the verify tool (checkmark). After a few seconds, we can see the result of the action in the console (box in the bottom).\n", "\n", "3. Click on the upload button, and it will start uploading the sketch to the board. When it is finished, a notification will appear. If there are any problems when uploading, the errors will be listed here as well."]}, {"cell_type": "markdown", "id": "d63f993c", "metadata": {}, "source": ["***"]}, {"cell_type": "markdown", "id": "35f8749e", "metadata": {}, "source": ["![scientisst-notebooks_bottom-banner](./_Resources/bottom-banner.png)"]}], "metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "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.10.0"}, "vscode": {"interpreter": {"hash": "7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad"}}}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/B.Instrumentation/B004 Digital to Analog Converter - DAC/B004 Digital to Analog Converter - DAC.ipynb b/B.Instrumentation/B004 Digital to Analog Converter - DAC/B004 Digital to Analog Converter - DAC.ipynb index 6eadf94..2026b18 100755 --- a/B.Instrumentation/B004 Digital to Analog Converter - DAC/B004 Digital to Analog Converter - DAC.ipynb +++ b/B.Instrumentation/B004 Digital to Analog Converter - DAC/B004 Digital to Analog Converter - DAC.ipynb @@ -1,515 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#

Digital to Analog Conversion - DAC

" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Digital to Analog Converter - DAC " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Keywords \n", - "```Digital to Analog Conversion (DAC)```, ```Digital Signal Processing (DSP)```, ```Arduino```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributor(s):** Afonso Raposo, Joana Pinto, Prof. Hugo Silva\n", - "\n", - "**Date of creation:** dd/mm/aa\n", - "\n", - "**Last update:** 2021" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# I. Introduction\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Background
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Digital systems often need to produce an effect in the physical world, in the form of continuous time-varying quantities. Such goal can be accomplished using the finite discrete numerical representation capabilities of embedded systems, to generate analog physical quantities (e.g. a voltage). This session aims at experimenting this process in practice, using the Arduino as a basic function generator and oscilloscope." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Note
\n", - "
\n", - " If you have difficulties with the hardware setup, use Tinkercad [1].
Files with pre-recorded data are also provided for some experiments.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
2. Objectives
\n", - "* Understand the process of converting a digital signal to an analog representation\n", - "* Learn how to use Arduino-type systems as a basic function generator and signal visualizer \n", - "* Explore the use of bitwise operators for low-level numerical manipulation\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
3. Materials (optional)
\n", - "* Arduino IDE\n", - "* 1x Breadboard\n", - "* 5x Jumper wires\n", - "* 10x 10kOhm resistors\n", - "* 1x Arduino (or analogous device)\n", - "* 1x USB cable" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# II. Experimental\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Adapt the firmware developed in the previous session to sample the analog inputs A0 and A1 at 50Hz, and stream them, together with the elapsed time since the board began running the program, through the serial port (the suggested baud rate is 115200bps). As before, a formatted sequence of comma-separated values (CSV) should be used (e.g. < TIME>,< A0>,< A1>); make sure that each sequence ends with a line feed character. \n", - "\n", - "Spreadsheet software of your choice was previously suggested to analyze the data, however, you can also acquire the data stream produced by your embedded system directly from a Python script. The following code can be used as a base (note that this is an optional step):" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "!pip install pyserial >/dev/null 2>&1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import serial\n", - "import time\n", - "\n", - "acqtime = 10\n", - "\n", - "try:\n", - " port = serial.Serial('',115200)\n", - " port.flushInput()\n", - " \n", - " fp = open(\"data.txt\", \"w\")\n", - " \n", - " print(port.name)\n", - " \n", - " t = time.time()\n", - " while (time.time()-t) <= acqtime:\n", - " data = port.readline()\n", - " print(data.strip())\n", - " fp.write(data)\n", - "except:\n", - " print(\"error\")\n", - "finally:\n", - " fp.close() \n", - " port.close()\n", - " print(\"stop\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - " Warning!
\n", - "
\n", - " The serial port can only be accessed by a single application at any given time, which means that, to acquire data in your Python script, the Arduino serial monitor needs to be closed (and vice versa). THIS FEATURE IS NOT AVAILABLE FOR THE EMULATOR.\n", - "\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# III. Explore\n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
1. Quizz
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "1) Modify your firmware so that, in addition to sampling and streaming the analog inputs, your Arduino works as a square waveform generator with [0; Vcc] amplitude, 50% duty cycle, and 2Hz frequency. You can sample the waveform by connecting the digital output pin to one of the analog inputs streamed by your firmware (e.g. A0)." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Example: 1 Hz\n", - "\n", - "import pylab as pl\n", - "import matplotlib.pyplot as plt\n", - "\n", - "fname = './data/L3.1-2Hz-115200bps.csv'\n", - "\n", - "raw = pl.loadtxt(fname, delimiter = ',')\n", - "\n", - "col_1 = raw[:, 0]\n", - "col_2 = raw[:, 1]\n", - "\n", - "plt.title('Example - 2 Hz', {'size':14})\n", - "\n", - "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", - "plt.ylabel('ADC', color = \"#fdc86e\")\n", - "\n", - "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2) Modify your experimental setup so that the output waveform amplitude is [0; Vcc/2], and the frequency can be adjusted through a command sent via the serial port (e.g. F5 would produce a 5Hz square wave). Test your setup for different waveform frequencies (in particular 95Hz) and discuss your results.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Example: 1 Hz\n", - "\n", - "import pylab as pl\n", - "import matplotlib.pyplot as plt\n", - "\n", - "fname = './data/L3.2-1Hz-115200bps.csv'\n", - "\n", - "raw = pl.loadtxt(fname, delimiter = ',')\n", - "\n", - "col_1 = raw[:, 0]\n", - "col_2 = raw[:, 1]\n", - "col_3 = raw[:, 2]\n", - "\n", - "plt.title('Example - 1 Hz', {'size':14})\n", - "\n", - "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", - "plt.ylabel('ADC', color = \"#fdc86e\")\n", - "\n", - "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", - "plt.plot(col_1, col_3, color = \"#474747\")\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# Example: 95 Hz\n", - "\n", - "import pylab as pl\n", - "import matplotlib.pyplot as plt\n", - "from scipy.signal import resample, medfilt\n", - "import numpy as np\n", - "\n", - "fname = './data/L3.2-95Hz-115200bps.csv'\n", - "\n", - "raw = pl.loadtxt(fname, delimiter = ',')\n", - "\n", - "col_1 = raw[:, 0]\n", - "col_2 = raw[:, 1]\n", - "col_3 = raw[:, 2]\n", - "\n", - "plt.title('Example - 95 Hz', {'size':14})\n", - "\n", - "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", - "plt.ylabel('ADC', color = \"#fdc86e\")\n", - "\n", - "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", - "plt.plot(col_1, col_3, color = \"#474747\")\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3) Devise a 3-bit DAC circuit considering the R-2R resistor ladder network (shown below), and characterize the expected behavior, namely the number of steps, step size, output voltages for each step, and other details that you may find relevant.\n", - "\n", - "\n", - " \n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "4) Using the circuit devised in the previous question, create a firmware that outputs a sawtooth waveform with positive ramp. Present and discuss your experimental findings based on parameters of your choice. The following firmware is provided as a starting point." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```C\n", - "\n", - "const byte TS = 100; // Sampling period\n", - "const byte a0 = 5; // LSB in\n", - "const byte NBITS = 3; // Number of bits\n", - "\n", - "byte data = 0; // Output value\n", - "byte mask = 1;\n", - "byte pin;\n", - "byte maxCode = 1;\n", - "\n", - "void setup()\n", - "{ \n", - "\tSerial.begin(115200);\n", - " for (pin = a0; pin < (a0+NBITS); pin++) {\n", - "\t\tpinMode(pin, OUTPUT);\n", - " maxCode *= 2;\n", - " }\n", - "}\n", - "\n", - "void loop()\n", - "{\n", - " mask = 1;\n", - " pin = a0;\n", - " \n", - " for (mask=001; mask>0; mask<<=1) { // Iterate through bit mask\n", - " if (data & mask) digitalWrite(pin,HIGH);\n", - " else digitalWrite(pin,LOW);\n", - " \n", - " pin++;\n", - " Serial.println(analogRead(A0));\n", - " }\n", - " \n", - " (data == maxCode ? data = 0 : data++);\n", - " \n", - " delay(TS);\n", - " \n", - "}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "import pylab as pl\n", - "import matplotlib.pyplot as plt\n", - "\n", - "fname = './data/L3.3.csv'\n", - "\n", - "raw = pl.loadtxt(fname, delimiter = ',')[:500, :]\n", - "\n", - "col_1 = raw[:, 0]\n", - "col_2 = raw[:, 1]\n", - "\n", - "plt.title('Example', {'size':14})\n", - "\n", - "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", - "plt.ylabel('ADC', color = \"#fdc86e\")\n", - "\n", - "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "##
2. References
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "1. https://www.tinkercad.com/dashboard?type=circuits&collection=designs\n", - "2. https://www.arduino.cc/reference/tr/language/structure/bitwise-operators/bitwiseand/ \n", - "3. https://www.arduino.cc/reference/tr/language/structure/bitwise-operators/bitshiftleft/ \n", - "4. https://en.wikipedia.org/wiki/%3F:#C " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - " \n", - " \n", - " \n", - " \n", - "
\"it\" \n", - " \"alternate\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
\n", - " Please provide us your feedback here. \n", - "
\n", - " Suggestions are welcome! \n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```Contributors: Prof. Hugo Plácido da Silva; Joana Pinto; Afonso Raposo```" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.10.0 64-bit", - "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.10.0" - }, - "vscode": { - "interpreter": { - "hash": "7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["#

Digital to Analog Conversion - DAC

"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Digital to Analog Converter - DAC "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Keywords \n", "```Digital to Analog Conversion (DAC)```, ```Digital Signal Processing (DSP)```, ```Arduino```"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Notebook Info \n", "\n", "**Contributor(s):** Afonso Raposo, Joana Pinto, Prof. Hugo Silva\n", "\n", "**Date of creation:** dd/mm/aa\n", "\n", "**Last update:** 2021"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# I. Introduction\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Background
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Digital systems often need to produce an effect in the physical world, in the form of continuous time-varying quantities. Such goal can be accomplished using the finite discrete numerical representation capabilities of embedded systems, to generate analog physical quantities (e.g. a voltage). This session aims at experimenting this process in practice, using the Arduino as a basic function generator and oscilloscope."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Note
\n", "
\n", " If you have difficulties with the hardware setup, use Tinkercad [1].
Files with pre-recorded data are also provided for some experiments.\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
2. Objectives
\n", "* Understand the process of converting a digital signal to an analog representation\n", "* Learn how to use Arduino-type systems as a basic function generator and signal visualizer \n", "* Explore the use of bitwise operators for low-level numerical manipulation\n", "\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
3. Materials (optional)
\n", "* Arduino IDE\n", "* 1x Breadboard\n", "* 5x Jumper wires\n", "* 10x 10kOhm resistors\n", "* 1x Arduino (or analogous device)\n", "* 1x USB cable"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# II. Experimental\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Adapt the firmware developed in the previous session to sample the analog inputs A0 and A1 at 50Hz, and stream them, together with the elapsed time since the board began running the program, through the serial port (the suggested baud rate is 115200bps). As before, a formatted sequence of comma-separated values (CSV) should be used (e.g. < TIME>,< A0>,< A1>); make sure that each sequence ends with a line feed character. \n", "\n", "Spreadsheet software of your choice was previously suggested to analyze the data, however, you can also acquire the data stream produced by your embedded system directly from a Python script. The following code can be used as a base (note that this is an optional step):"]}, {"cell_type": "code", "execution_count": 1, "metadata": {"collapsed": true}, "outputs": [], "source": ["!pip install pyserial >/dev/null 2>&1"]}, {"cell_type": "code", "execution_count": null, "metadata": {"collapsed": true}, "outputs": [], "source": ["import serial\n", "import time\n", "\n", "acqtime = 10\n", "\n", "try:\n", " port = serial.Serial('',115200)\n", " port.flushInput()\n", " \n", " fp = open(\"data.txt\", \"w\")\n", " \n", " print(port.name)\n", " \n", " t = time.time()\n", " while (time.time()-t) <= acqtime:\n", " data = port.readline()\n", " print(data.strip())\n", " fp.write(data)\n", "except:\n", " print(\"error\")\n", "finally:\n", " fp.close() \n", " port.close()\n", " print(\"stop\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", " Warning!
\n", "
\n", " The serial port can only be accessed by a single application at any given time, which means that, to acquire data in your Python script, the Arduino serial monitor needs to be closed (and vice versa). THIS FEATURE IS NOT AVAILABLE FOR THE EMULATOR.\n", "\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# III. Explore\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
1. Quizz
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["1) Modify your firmware so that, in addition to sampling and streaming the analog inputs, your Arduino works as a square waveform generator with [0; Vcc] amplitude, 50% duty cycle, and 2Hz frequency. You can sample the waveform by connecting the digital output pin to one of the analog inputs streamed by your firmware (e.g. A0)."]}, {"cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [{"data": {"image/png": "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", "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["# Example: 1 Hz\n", "\n", "import pylab as pl\n", "import matplotlib.pyplot as plt\n", "\n", "fname = './data/L3.1-2Hz-115200bps.csv'\n", "\n", "raw = pl.loadtxt(fname, delimiter = ',')\n", "\n", "col_1 = raw[:, 0]\n", "col_2 = raw[:, 1]\n", "\n", "plt.title('Example - 2 Hz', {'size':14})\n", "\n", "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", "plt.ylabel('ADC', color = \"#fdc86e\")\n", "\n", "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", "\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["2) Modify your experimental setup so that the output waveform amplitude is [0; Vcc/2], and the frequency can be adjusted through a command sent via the serial port (e.g. F5 would produce a 5Hz square wave). Test your setup for different waveform frequencies (in particular 95Hz) and discuss your results.\n"]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [{"data": {"image/png": "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", "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["# Example: 1 Hz\n", "\n", "import pylab as pl\n", "import matplotlib.pyplot as plt\n", "\n", "fname = './data/L3.2-1Hz-115200bps.csv'\n", "\n", "raw = pl.loadtxt(fname, delimiter = ',')\n", "\n", "col_1 = raw[:, 0]\n", "col_2 = raw[:, 1]\n", "col_3 = raw[:, 2]\n", "\n", "plt.title('Example - 1 Hz', {'size':14})\n", "\n", "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", "plt.ylabel('ADC', color = \"#fdc86e\")\n", "\n", "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", "plt.plot(col_1, col_3, color = \"#474747\")\n", "\n", "plt.show()"]}, {"cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAZgAAAEXCAYAAACQ3VJYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAz4UlEQVR4nO2deZgdVZnwf+/tTneWTjpbk4QsJCFRBFTASOMyjoKfRkRBZRzUkcAg4IAzjYAQtwHXAZWlUT+UxQEUBQaZgeHDhQ9x+xxaAiIkQaAJkMVAOklnX3q57/dHVXdu3+6+1dW3zq3lvr/nuc+tOnXqrbfOOXXesx9RVQzDMAwjanJxK2AYhmFkEzMwhmEYhhPMwBiGYRhOMANjGIZhOMEMjGEYhuEEMzCGYRiGE8zAGEaEiMjlIrIybj0MIwmYgTEShYjcIiI6xO+RuHVLGiJyjIg8KCLbRGSLiNwgIg1FfoYKy08GyP21iHxnCPdTRcQmzhkjxgyMkUT+LzCr6HdirBolDBE5GC+c1gDNwFLgCOCWIbyfzcCwvLUyWhrVjhkYI4nsV9WXi35bAUTkb0WkW0Te3udZRM4VkR0istA/XyoivxORThHZKiK/EJHXFPif75fkTxOR34jIXhH5k4i8TkSOFJE/iMhuEfm9iCwouO9yEVkpIp8QkbX+ff8lItNLvYyInCkiq0Vkn4g8KyKfFpFyv72TgDxwnqo+o6qPAp8EPiQii4r8bisKy71lPhsAEXlxmBrS/CjkG+nHDIyRKlT1N8A3gR+KyBQROQy4GvhnVV3je5sAXAscC7wd2A78t4jUFYn7EnAlcDSwDfgJ8G3g8/69Y4Hriu6ZD/wDcDLwTmAx8IPh9BWRs4GvA/8KvAa4CLgUOC/Mew9BPdCtqr0Fbn2G461FfltFZLOIPCoin4zAuPXxRgbWjO4H/gK8EpF8I+2oqv3sl5gfXhNPD7Cr6HdlgZ8xwKPAPcDjwJ0BMicAvcBb/fP5gALnFvg5yXf7YIHbGcCugvPLfTnzCtze6t+3uMDPyoLra4GPF+lzAbC6zHA6AugGlgN1wBTgbl+Xzxb4+6Kv41F4xm038IUA2b8GuoaIg71eljHkPZcCm4FD405D9kvOrzakPTKMSvBb4Jwit219B6raLSIfBVYBm4DjCz2KyKHAV/D6Jprwauo5YF6RzCcLjvtK3U8VuU0QkfGqusd326Cqawv8tOE1Vb0GeK5IjyZgLvB9Ebm+4FItIAyBiMwDVhc4fV1Vv17sT1VXicgyvNrb1/CM8nW+zvkCf18puO0JEanBq6F9dajnF3AnXg2vkKV4Nbxind/n+323qj4fINeoIszAGElkj6q2B/g5Ds9oTMYzItsKrt0PrAfOBTbgZb6r8Ur6hXQXHGsJt9E2KfXd90ngDyO85694tY0+tg7nUVV/DPxYRGbg1UwUuBCv43842oBJIjJDVUs1ZW0vjgMRebnYk4gcCdwOnK9e86Vh9GMGxkgdfsf7d4Dz8UrVPxKRt6hqj4hMAw7D6/x+2Pd/DNGl9dkiMldV1/nnx+IZkqeLParqKyLyV7xmo9tGIlxVe4Ag4zroOQAi8o/APuDBEt6P8v1sC/OMofAHN/w3cKOq3lyuPCN7mIExkki9iMwscutV1Q6/ieeHwG9U9fsicjdes9ZleP0NnXh9AWeLyDpgNt6ggJ6IdNsL3CoiFwLjgO8B/0dVnxvG/2XAt0VkG/AAXv/RMcBsVf23chQRkU8B/wPsBP4X3nsuV9Vt/vX3ATN9P3uBdwBfBm5Q1f3lPNvnp3g1xKuK4qtDBw4+MKoUMzBGEnknsLHIbQMwB/gcsAh4LYCqbvH7Ih4QkV+o6u9F5O/x+iNW4tUGLsLLDKPgReAOvJL7dOCXwCeG86yqN4nIbuAzwL/hZfSr8Gpg5XIsXt9HA97orXNV9YcF17vxRqtdjVfLWoM3mu27ETwb4G3+/4Yi9wV44WRUOaJqE3MNYySIyOXAqap6ZNy6GEYasHkwhmEYhhPMwBiGYRhOsCYywzAMwwlWgzEMwzCckMlRZNOnT9f58+fHrYZhGEaqeOyxxzaralNU8jJpYObPn8+KFSviVsMwDCNViMhLUcqzJjLDMAzDCWZgDMMwDCeYgTEMwzCcYAbGMAzDcIIZGMMwDMMJZmAMwzAMJ5iBMQzDMJyQyXkwUaK9+9GXfgq71oII1E2B7l0w+TDY3wl7X4ExE5GGQ9B8N2iP57dhPjJ2GnLQm0vL1zy88lt093rI9yAN89H9W0BySM04VHth8x+959ZO8HQYMwn2bUamvwGmL8HbIqXEM3a0e+/Q+BqkdgLU1IP2Qs14dOvjIGOgrhGpa0TzXdC7H7p3gCoy7/1I/dTS8vf8FX35NzCmARkzCd2/BambinZvh57dkO+GrU/A1KOgdx8yYR66ex3ku5GZb0OmvDYgjHph82NeuGz/CzL5cLTzKdi9DpqOQ8bNQDtXgtTCxPkASK4e7d2LNB6GTFpUUj6AdjyKvvIbZOpRaNd2T99pR8PuDVA/FXaugelvQKQWtNeLN+1BcvXQ1IzUTyktf/sz6NYnkLop3v17X4YxEyHnbbIpdZO9OEFBFWrHo9tWeWEzcSEytvTcN+3eia75CfTu89KnHw7s74QJ86B7u/ce+zthx7PIQW9Gu3bA7peQaccgs44vLV/z6Lr7QWqQ3BjIjYG+dNezB+3dh9SMRXv8jTVzY5DaBu98/xZkwYe9tFfqGbteQjc+DPVTkYZDoKsT3fw4TFoE+7dAbYP3ne3rgJ49oN1QM877biYtQqYdXVr+ttXo87dD46u9+/as98Jq0mLvfXJjoKMNxh+MTFoMdZPR7X9BJsyBKUciYw8qLb9rB/rsTVDv5xGTDvW+zbFN3jfQtR3t3gn7OqBhHux80btRBJm2BGl6Y0n5ANq5Et291pMxZhJ07/Rk9+5DJh/upaFJi73wSwCZXItsyZIlGtVEy/yjn4F816jvl2O+jowZ/sPKr38ANvxi1PKZ+XZyh3xg2Mua70UfvXD08oFcc2vJ6/m2FqfyteOP6JrbRy1f3nAFUjtuePk7X0BXXztq+RB/GOXbLuDADs/hkaP+FamfNux13fgrdO29o5YPSQijZMuXo7/kFTSGQff8FX3qymBBU48mt/iM0ekg8piqLhnVzUNgNZggioyLLDoDxh/slfJztZDvAcl5pbl8N/rCnV7JqJ+Ajf12rR14XjMeOeyfYOw02LfFewYA6j0r34M+fV3B/UETbwc/X478DGje0xvxal2I/x65kSXiEshrL/Hka77PxZPtu+nqa8IJ7OocKH/2e2Dq67w46K+9qR8fvbDjOXTdfQduyHfhbT45DPsHb3svh1/gh4/itSR7tQp69kJuDPrUFeHeoVj+6z7nlTyl1g+b3gP/yCjkDzQusvCjMG6mJ5881Iz1dEe9OPjrg7Bt1YEb8qU3/NTd6wa5yWsv8Q5y9dC713tW3/fSsxd95vqQ71Ak/8iLvfisqT8gV2q8ml/P7vLT6cKPwNiZMKbBqxGJ+M8bA/ledNVVZcln9lJk8hF+OsKLA/DfJQc7nvVaFvro2QslDAxd2we/w5EXe99V7Xjo7YKaugPPSwDODIyI/AA4CdjUt0GTiEwF7gTm4+1492FV7RQRAVqBE4E9wBmq+rh/zzLgC77Yr6rqra50HhET5pRsrtCGeUUGZhTyG+Z5xw2Daz46RCILi0yYU/J6uXVaGT/bqXzGzUTGHzy8/Hz5uwHLxAUlr5f9DmObkBIZQdnyJ8wtGUZMmIsWGpiwjJtZMp61Z8/oZfvIhLnDX6xrLD+Mxs8u+QzNjfEKAaNE6qcf+JaHkt+7b9SyARh7UOkwSgAuTd0twNIit+XAQ6q6GHjIPwd4D7DY/50DXA/9BukyoBlve9jLRKR0Y7dhGIaRCJwZGFX9LVDc9nAy0FcDuRU4pcD9NvV4BJgsIrOAdwMPqupWVe0EHmSw0TIMwzASSKUb62ao6kb/+GVghn88Gyhs5F3vuw3nPggROUdEVojIio6Ojmi1Hvgkh7JHIt/181NAYBBYGMWfjrIQB47fIQtBFEBsvUHqDV+LbAibqt6gqktUdUlTU2TbGRiGYRijpNIG5hW/6Qv/f5PvvgEo7K2a47sN524YhmEknEobmPuAZf7xMuDeAvfTxeM4YLvflPYL4F0iMsXv3H+X75Yhyq3EBdyfhWlOGZyrFT8hw9TioAJkL4xdDlP+CfB2YLqIrMcbDXYFcJeInAW8BHzY9/4A3hDldrxhymcCqOpWEfkK8Kjv78uqOnjSQpaQgIbZKmi3DcYCIRjXfTAWB0YwzgyMqn5kmEsnDOFXgfOHkfMD4AcRquaYsB+e4w89C/lAkNFNJTG/U9gwDR0HaYizuHUsfn72wjg5Uz4NwzCMTGEGxjAMw3CCGZjUkfxqsWEYBpiBGQWWwSef5MeRuO5XijsI4n5+JGTiJWLFDIxhGIbhBDMwhmEYhhPMwBiGETtZ3PjQMAMTHucLLca9SGEaqIK5P2XjOB0F9iGlIRLi1tF1HMSPGRjDMAzDCWZgDMMwDCeYgck61rRtpAJLqFnEDExogtr/k98umn6y0P6fdjIQxoHJyPVcpQyEYQBmYAzDMAwnmIExDMMwnGAGxjAMw3CCGZikEfn8Aus8NQwjHszAGOnD+WTXLBD3QIg0xEHcYVQuSdfPDIxhGIbhCDMwhlGVWNNp+kl+HJqBSRvJrxWnjyqYjzAY12vmhSX5mWXySH66NQMTmrS322aBiMM4iyv5xp1M7TMYAdkPJDMwhmEYhhPMwBiGYRhOMAOTOmwejJFBLJlmEjMwobHG6+RjYWidMCMh7jAqkxQMTjEDYxiGYTjBDIxhGIbhBDMwsVNu43PA/Vlo287iMOLYCRmmzuPA4jiLYWAGJizOmz2T365qpAHH/QspaP8vmyp4RdfEYmBE5NMiskpEVorIT0RkrIgsEJE2EWkXkTtFpM73W++ft/vX58eh84gJ/eElbUZ1AgkbplUQJOVjnfzx61j8/ErnHe6puIERkdnAvwBLVPVIoAY4DbgSuEZVFwGdwFn+LWcBnb77Nb4/wzAMI+HE1URWC4wTkVpgPLAROB64279+K3CKf3yyf45//QSRaqifG4ZLstfeX30kPw4rbmBUdQPwLWAtnmHZDjwGbFPVHt/bemC2fzwbWOff2+P7n1YsV0TOEZEVIrKio6PD7UvEik20jJyqLK9U4ztnjeTHYRxNZFPwaiULgIOBCcDScuWq6g2qukRVlzQ1NZUrrgTJj1QjZBzZKLXqJO6N66ogK4mjieydwAuq2qGq3cA9wFuAyX6TGcAcYIN/vAGYC+BfbwS2VFZlwzAMIyxxGJi1wHEiMt7vSzkBWA08DJzq+1kG3Osf3+ef41//laoVOQ3DMJJOHH0wbXid9Y8DT/k63ABcClwoIu14fSw3+7fcDEzz3S8Ellda54oS2B9gfTCRU5V9MGEpTke24ZgRTG2wl+hR1cuAy4qc1wDHDuF3H/B3ldArGiyzSh2ZrBAHpEPnRjUN30HcOmZ/DpzN5DcMwzCcYAbGMKqRTNbaqo3kx6EZGNdEnQaSXytOH9YHMwqsDyZ+kp9uzcCEJvmRatg8mOC1Lm2ORzCZeIlYMQNjGIZhOMEMjGEYhuEEMzDOsU4YI4FksVnQSBxmYBKHdZ5WHOvkD8a1QbJkmknMwIQl7gXyjGDCGoxMluZtomUwceuY/V1FzcAYhmEYTjADYxjVSCZrbVVGCuLQDEzWSX4arAABgZCCpob4KQrDyMPMEmpoUpBuzcCEJu62bSNyUlASjBxLp/FPRo29D8g9ZmAMwzAMJ5iBMYxqpBprbUbFMQPjnLAfsm04FjlBQWDNRYbhBDMwobHMKPlYHMXfV5iGOIi6MBfx490LcI4ZGMOw5iLDcIIZGMOoRsyoZoDkx6EZGNcEpoGQiWRQrTj5iaxsBmWGYd/Z5sGUT3EYJm8ejKbeaKZd/8GYgTEMw0glyS8YmYGJnLCRXuQ/dGk6+YmsbAaFScTvnPqS71DE28kvqagVxq1juek6bv2DMQNjGNVIJo1qtZH8ODQDkzqSX2pJHakobRtG+jAD45y4SxlxPz8JWBgknkiiqNriOfkFIzMwoUl+pCafhE3yy2JzUewLOWYBC6NyMQNjGIZhOMEMTOrIQqkqgzWGtJHFWpuROMzAOCfqxS5dP78SJMxIWnNRMMUGyTYcM0aAGZiwBH5XllnFjkUBcc+DSQdxh0GZz09BHMZiYERksojcLSJ/EZGnReRNIjJVRB4Ukef8/ym+XxGR60SkXUSeFJFj4tDZyDDWXGQYToirBtMK/FxVDwNeDzwNLAceUtXFwEP+OcB7gMX+7xzg+sqraxgZw4xq+klBHFbcwIhII/A24GYAVe1S1W3AycCtvrdbgVP845OB29TjEWCyiMyqqNJOKTeRBNyf/DQYTNkfki12GT1J7INJe2JPu/6DiaMGswDoAP5dRP4kIjeJyARghqpu9P28DMzwj2cD6wruX++7DUBEzhGRFSKyoqOjw6H6lhkZ1Uj2Mr9Akl7wSLp+xGNgaoFjgOtV9WhgNweawwBQb93tUClaVW9Q1SWquqSpqSkyZUMTOs7LTSTJT2SDCamz6wVAU9DUEDm2qGr8rzTo+XErFD1xGJj1wHpVbfPP78YzOK/0NX35/5v86xuAuQX3z/HdjNRShRl60qhGo2pUnIobGFV9GVgnIq/2nU4AVgP3Act8t2XAvf7xfcDp/miy44DtBU1pKSDoQw47v6D4ekj5aaTczDDo9hQ0NcRPCtJRClQsTepfYBC1MT33n4HbRaQOWAOciWfs7hKRs4CXgA/7fh8ATgTagT2+XyPVCFn8mAzDGEgsBkZVnwCWDHHphCH8KnC+a52io9Jt2yksfYe1L65rGJlsLrKJlsHEHQa24ZhhRE8W8/O0kUmjWm0kPw7NwKSN5Bda0oeV5keBhZkRjBkY1yS/kFF5Kp43WSQEE/dgkeRPtNTE1fqSb+TNwIQm+ZGafBK24VgWsQ3HIsDSabkMa2DybS3fzLe1nDuE+7n5tpYr3KplZJuklQSrkMSVxo0sUqoGczxwwxDuNwInuVHHGEHRsyJaGIZhlEspA1Ofa24dVMzJNbfmsVwuBHGXFON+/lBY8gmL8/b/uJNJ3M8fEWnoh0oWpQzM3nxby+JiR99trzuVko5ljsnH4sjmwYyElLcWpCAOS020/FfgZ/m2lq8Cj/luS4DPAhc41sswKof1RxiGE4atweSaW3+GtyfLO4Bb/N87gA/lmlsfqIBuhmG4woxq+klBHJZcKibX3LqSAwtQViUbt3ZxVusL/ef19X/P/v37+89nzZrF+PHjyefz7N69m02bNvVfO/KQcXyztbT8V7bs5syvPNN/Pq1xLVu2/5hZs2bR2NhILpdj9erV/denT5/O5s2b+89vXN40YKnpYjSvnPSlZ8jnC12XMm3aNHp6eti+fTsTJ05k3759dHd3D5J/+cdmc1xz6Xd45C+7+PJPChe4XgrAwoULGTt2LABdXV20t7ezcOFC9m5bx8at3QActXA8VwTIf3nTNs687EAY1Y1ZzkEzZtLV1cWmTZs49NBD6e3tZfz48Tz//PMD4kcE7v9pLzUl5O/v7uGUAvkAhx56Pt3d3axdu5aGhgZmzpxJe3s7dXV1LFq0iNWrD/j/4JuncE7AO9zxmy3c9qvN/TrV15/C7NnetkadnZ1s3boVgIMPPpjNmzfT1dXVf+87XjeRS45VSjXZPPTEdq76z5f7zw866Dw2beogl8sxduxYZs6cyf79+9mwYQOLFy/m+efbyee9DOrVc8Zy1TW9JTODzZ17OP3yA+/86kNeYVfPE+zYsYOdO3cO8FtXVzdAf4BLTp3F8SXDSPmX771I+0Yv7poaa9m2531MnjyZffv2oars2rULgMbGRrZv3z7g7g++eQpnv7F0hnv7w5u5/ddb+s8XLljOmhdeorGxkdraWnbu3ElXVxezZ89m3Lhx7Nqyjpc7PX3+9siJLD+2pHieWb+XT9+4tv/8iFfdhNTdycqVKwH65a5fv55x48bRtX8/u/fs6fd//3/kS8ZBd08PH/jSM/T63/KiORv569bf0tjYyMaNB9b//ehHP8rpp59eWtkKUXIeTL6tZVm+reWxfFvLbv+3It/WkgzNK0ShcQEGZF4AuVyOnTt3snXrVjo7OwdcW/nSXrbvGPjxFfOd//jzgPMt2/cyefJk9uzZw86dO6mpGZg11tfXDzi/+o6VJeV3dXUXGReora2loaGBiRMn9p83NjYiIuzbt2+A38tvD94ZYaBxgfHjxzNlyhTq6ur6f32Z0LZt2/qNC8ATa/YQxMNtAzP/ru4edu3axdixY2loaEBV2bNnD7lcjmnTpg3wqwrbtu0oKf9/Vqwe5NbR0UFvby9Tpkyht7e3P8Osqamhrq5ugN97/tA56P5i+oxLn06qyo4dO+js7OzPOBsaGti9e/egOH74ydJpCBhgXAB6enoAaGpqYtKkSdTV1TFu3Djq6+sRkX7jAvDM+n1sfPmVkvJvvndgOnvmpW3U1NTQ0NAwwL2mpobGxsZB93/j7uAF0PuMC0DH9h4mT57M3r17GTduHBMnTqSmpob6+npyucHZ1kjioNC4AKx54SUAuru72bJlC7W1Xva+YcMG1q5d229cAH6zMjgOCo0LwKpnX2Lbtm3955s2baK2tpbJkyfT2dk5wLgArN9QOoyeXNXeb1wA2tfvYMqUKYOMrSSob2ZYg5lva1mG19dyIfA4XvHpGOCb+bYWzTW3/rAiGiaMm2+8ntlzFwx7vfXrF/Gz367qP88X5+4BHH3YTP7t2luGvb5ly2Y+9rF/CCWzmPvvv7/k9aVLl5Yl/5577olUvhaNrvncBR/nbUs/Nqz/Pz/6MJd+8coQDxhc8r3rrrtK3hJFGBUXHqKU/7Uvf5EFiw4f9vqPrv8KP7r3/41a/rwZDdxww1CzGDx27drFqaeeOmr5AD/8Yeksptwwuu6qr/OqI44Z9vrJ7zuR/d3hvt9CLj73Q7zzA2cPe331nx/hwksvH7X8OQdN4Kabbx71/ZWgVI3sn4AP5JpbXyxw+1W+reVDwB1AVRoYw8gGyW+/N9JPqSaySUXGxbvBc5vkSqHEE7r2Ge5DloAHiNjqPkFh5H5L5vJx3YwRGEaDnh8ynQboH08zTbTv4Jpyn5+chrDhKTkPZpTXjERhJVULAyMabKJlWEo1kb0m39by5BDuAix0pE/ikYD1QeMuFVUDySw9hyNuHct+fvKDOJiY56LGnQYqQUkDM4SbAHPxJlsaDghKc9WQKI0ICEomKZhDYQSQgrxgWAOTa259qe8439ZyNPBR4O+AF4CfulctmQSXnuN9flWQASMct46u2//jfr+REPgtO1fA9QPip9Qw5VcBH/F/m4E7Ack1t76jQrplhJAlxcg/TCupZiMI0tWBHRbV0Q8HPiCkfBGB8l0Ga9iswo0WkVKqiewvwO+Ak3LNre0A+baWT1dEqwQT/N2mIdrTTeSjyDKJ2w6GqugHcz7SL/sjQksZmA8CpwEP59tafo439yX5qSblRN30UDxJ0agOAlNJwvpgkrcdcfJJgQ0vudjlf+WaW08DDgMexpvVf1C+reX6fFvLuyqkX/KIuQ/GGMlAiMrokWasD2YEc85cPz/5QVQ2JRe7BMg1t+4Gfgz8ON/WMgWvo/9S4JeOdcsGEXfBhP5ws1AyLPsVMhIGIaI+DRn8QKKIo7TPU8lAOi0i0MAUkmtu7cTbRnn4RYgyTuA8mArpYQxP+jJXB6SslhdLOSj1I0ITFolDkP1eprQRtvM04MPMYgUmbCd/VfZDBaSj4nQR1Acy6Gry87bUEZRK09hPZQbGMKqQ8ify23B6IxgzMCEJ30cSdrHLkAQPFworMXEMesWgOBh0noXittt0FHWHd/i+wpAPiIDAb7nCCoQdOJG0Zs6hMAOTcdJYrTbcU67RjTpzs3SaTWIzMCJSIyJ/EpH7/fMFItImIu0icqeI1Pnu9f55u399flw6A5BzW+zJwgS2yAn7ykFxVAUEbuuQ+A5s9wSHUcxbKgTdn/wgjrUG0wI8XXB+JXCNqi4COoGzfPezgE7f/RrfnzFCqrKD24gc1+nIKjCjIAVhFouBEZE5wHuBm/xzAY4H7va93Aqc4h+f7J/jXz9BYiweBbdV2wS2uLEwwv0Q3EwEcbqHKachncdVg7kWuAToW+FuGrBNVXv88/XAbP94NrAOwL++3fdvjIQI1hBMPyko6sVOwDBlx0GokSTUtE+EzN5qlxU3MCJyErBJVR+LWO45IrJCRFZ0dHREKbr4OQHXnT3aGCEWBcGUv1RM+vsKY+6mSkUYlUscNZi3AO8XkRfxFtA8HmgFJotI38oCc4AN/vEGvE3O8K83AluKharqDaq6RFWXNDU1uX0Dl9joHCMCAvOukMnCeTqydBqaNJinihsYVf2sqs5R1fl4qzX/SlU/hreg5qm+t2XAvf7xff45/vVfaYy5pvtSRxqSTcKpgpJh2ZQ92jHoevLjILC/1HYcK5skzYO5FLhQRNrx+lhu9t1vBqb57hcCy2PSb5SE3Sgq6Hr2lut3Xzp2K74yhJ1omf3MaxDO4zlZCSkNRjzUYpdRo6q/Bn7tH68Bjh3Czz68FZwTQsBil0WRbk1UlScF310FiHdTttAFoVhm8rsdERr4/CqYr5WkGoyBg85TM3CpqMVFTXA6CRcmloyM0WAGJiShN7uyD7PiVGXzUMWJNoxjKQTEvly/W/lJwAyMa8J+N2H7YAKX60+DhQuag1HeO6QjDIKIeI7EoOX6S89DKTYA0WeOKdhwzPlAOrffQRyYgXFMNTbPGNknevti30kWMQMTEtcdg5GvUhutuJgIFyg20CJ459XQhN76O/ntP0GLXbp/g/LiKAVBbAbGNeHzthSkGqPqidqAVGEZoCowAxOW0LsURbtR1KAPuwrsUei8rArCJIiwYRa1wYinBhPxpmwV7uQPu1VHGmqJZmAyTlDnbXWQgeJxzK8wqC8x6qbcfPkv6L4pNO3yK48ZmJCEXa4/dKLPwBIccWPDlIl907VUpNO4J1qmIYzKxAxM4oh8tcto5aWQQCOf/e+8bIqDMIlBVo2DOZKOGZiQhF+u3xJ9pamGkmHWiGM4f9xbbyRtxKkLzMAkjKjTTBLn4VTaCGejZOt4scugMCquwUSeu6WhDyZpJN/CmIEJSeACdcUT7asu0cdPGkp27ol7KfqQxLFSTNyBUAUJ1QxMwoh8uf4EGrjsf1bxE/mGY45HkRnhSUMUmIGJmLJHkVUDSdvIqRqjKGG5UxzfSex9MOVuW52wOBwKMzAJI+xkq0DSMA0mKG8pM++pxrlAUW9M5z7/j6IPxnU82zyYsJiBCYn7Uk/2ElkxzjedTkPRzhhAPMv1B112PA/G9b7VCcAMTGicZ4+lr4Zdrj+BBiusRuW+QXW2Ugak00HL9QfUYMJJj4WoJzU7H7ATUn4am9vNwDgmjYnCNUnMnIxwRF5LtM8kk5iBCUn4Dyvk/IXIV6lNQ/9DtJ0wgyp5mTDybtNRYBilIQxDV2BChlEE66UVKVD0gPJuTyJmYBJHCj7kMrE+kvAkzUhGPs0ygvdLVggZYAZmFIQtGYaVHrIPpgry6tAGyQyYGfERELjhmPNhyuGy38HL9UepjRvMwGSchBV848EWuyybQUGYxNzNcWJ3XYvM4rdqBiYkYb+r0KO4bLn+ssliCIUfIZWuUKjOYcrxS3CNGRjXxF4qiV2BQVQ670ta/8WocPwKQYNB0jFMOe0TLdMwICccZmBCErbdNGy9N/SWycYgshhGYY1k2sIglqViAvs7HT8/bF6SQrL/hqkj6mHKkYqLhEpnfUmcbJo0AtNJkYck2i/XaT1pfTBJjINizMCEJPz8AkeKGMOSttK7QSwfSuzpJO7nVwAzMM4pb5Jg2U9P4ETLiu/6mQkj7zgdhVwqJvqtvRMjZHjpjr+l0M2gjvSIEjMwIYl6lVrDGAnhm2fSkP0cII6vJPbl+t2KTwQVNzAiMldEHhaR1SKySkRafPepIvKgiDzn/0/x3UVErhORdhF5UkSOqbTOlST6lWjSb+DKbT3JxCiykETdlFschkls3XHeR+JU+ggWTEphOo6jBtMDXKSqhwPHAeeLyOHAcuAhVV0MPOSfA7wHWOz/zgGur7zKZZC+NGEkkDRmLmHI+vu5IPY+pBFQcQOjqhtV9XH/eCfwNDAbOBm41fd2K3CKf3wycJt6PAJMFpFZldX6AO4jNeJRZMnrgiH8Kn/lDdHNRjOl2yaywHkwxTsmR/4dRLHhWLTDsAYNY47YCA7eeiPoY01fOo61D0ZE5gNHA23ADFXd6F96GZjhH88G1hXctt53K5Z1joisEJEVHR0d7pR2TvoSUVhSUPAyjOSTgu8oNgMjIg3AT4ELVHVH4TX1iiKhclpVvUFVl6jqkqampgg1HUjky6CXKT/q58dBsI7lhUkawiCI0PWX0INRYiaS1ZTDjsIKyP6cbzhWVNN2vN1AHMRiYERkDJ5xuV1V7/GdX+lr+vL/N/nuG4C5BbfP8d2MlJL8z8IIwuLQGAlxjCIT4GbgaVW9uuDSfcAy/3gZcG+B++n+aLLjgO0FTWmJJ3ypKuzS9MEaJB5b7DiYrC8VE4OUoCByPV8rrPyURSkAtTE88y3Ax4GnROQJ3+1zwBXAXSJyFvAS8GH/2gPAiUA7sAc4s6LaVpxoE3EizUuld5zMQBOZc8LuB5/EzC7lySh0YTSJcVBExQ2Mqv6e4ZPnCUP4V+B8p0qFwHUfTCpSTaWxIMl8OoqlnywXchRZxKShD6VcbCZ/1klg6X3QIOWUT5DLAkFxMHi/seRlju6NVLIWu0wDZmBCEvrDCt12Hk68UR2EH2GULqpzuf60xVJ4zMAkjKi/syQO0a30YpeaT+Rs05C4ruUFrhUz4DSJWaPzmnA+5k4e55Ndo8cMTEhSN7/AyAjZXuyyOpfrj/fxlcAMTMZJwzIp7keRuRWfRKIejJKKIEz7KLIMNqebgTGMFJC4ps6oV5yIwYQFL9dvo8jKxQyMY8K2/0e+XH/SMqYhCCw9l/kOSgb6YEKPUo52MIr7aTBRLHbpeEMwx+nI9XcQB2ZgDMMwUkga6j9mYEISvmToRo8RPz4FhR7nsxdSEAZBuN7QMqiJavA8mHDyA58fQRyFb2YLmmhZ/ADHy/VncCCHGRjDMIw0knz7YgYmLOGHKcfb/h/380eE67bzDFRhwsZj6HQauNdV8TyY5FVhIl9Nx+1+Y+7lJwAzMIZhGIYTzMCEJPz8AkeKpOT5IyELNQznhJ4jEfbTDjeKLIEVmMjDqLiW5noodfBcpOSvplCMGRjDMAzDCWZgHOO8dJ6GYkyZVMErBhI+GTmeJBh5DSaGWmzgRMsK6TFKYl/qZgSYgck6rhfoi4CgDuZy38D1BLwsEP9SMcmfaOl8MEpgM2Xyv+VizMAYRgrI4m6HhcSyXH/QlsmVUSPTmIHJOGlY7NI2coqfwAze9TDlCEj9hN3Qy/W7UyUqzMAYRgZJQ/t83ASGkQVh2ZiBcYz7duH0t9sGh1GZi12mIAwCcd7+H/J6EjNfx/2NzhfTDOqLTGE6NgNjGIaRQtJQSzUD45jY99JKQaknZPN/9A9IAeGXQQn5aYdcrj9qoiidh9+wK2CipRRPtHRL8Cgyxwo4wAyMYRiG4QQzMI5x3W4acuBJIglayLH8DcfiDYVoSufZ3uwqkjByHc+u55QFhsHANJD8BjIzMIZhGIYjzMC4JuaSXypGnqSgdBw3Yd8glwv3acddy4tmJr/bBUHjrsWlMRmbgTEMwzCcYAbGMXGXDNNQeg8eRVbmO4Se5BEtkfSfhGz/Dz2ENXAORjhxYdEo+jdC12DCbh7ouAZja5EZhmEYxsgwA+OYNJY6qo4UxFH4/oU0jDE6QCwxkLIwSiOpMTAislREnhGRdhFZHrc+SSE430lB5ul4gpk1UwYTdjfFJOJcx7g7+VMQB8WkwsCISA3wXeA9wOHAR0Tk8Hi1MgwjzVj9xT21cSswQo4F2lV1DYCI3AGcDKyO8iFrnv4jV1xxRVkyxtQODNIrv3Ud9XXfHdb/2lf2DDivrQkXJc+t38E5yz447PWu7t5Q8oailPzRMLauht37DvQqX/jP55LLDf+5b9u5f8B5rqampHyvPHKAb1z1berr/vew/nfv7S4pbySUCqMoCr6fuaiFmprossTaMQPT2VXf/j7jbrh5WP/F6bQ4nY+EUmHU3VP+QIjPXnoJtbXRlZnrxwxMR5+5+AJqa0YuvyYonRaZuGu+cxPjbrxlWP979vUMOC+OwySSfA09ZgPrCs7XA82FHkTkHOAcgHnz5o3qIfVjxzNv1tQBbpMnjuPJ9i0AvOl1BwfK+NCyi/nRfX/Xf774kKaS/mc1NdK2cmP/+Znnfz7wGe960yJ++T/tALzx8BnU140p6f/lrev7jy//zD8Gyr/o3A9y1ffvAeCIhVOYMmlC4D19GdAZH3xroN+rr76KZZ/4l/7z+bOnlfQ/bxb8/okD7/CGvzm5pP9Zh7yG2dPHsWHzXiA4DmCg/EvP+3Cg/wvOej/X3nwfANMmjRmUborp2LaPfV1eJnr2ae8IlH/VVy/moi98q/98wZzSYTStcQJ/erYDgKNeNT1Q/okfPo/v//ih/vNXzz+opP85M6bwhyc39J+fd+GXAp/x/nccwX0PrwLgVXMncdC0SSX9b9xyIA4uu/jMQPkXnn0KV9/4X/3nC+eWfu+62hraN+wE4C2vn01d/biS/j9/+RV87IxPHpA/p7T86ZMn8PgzHf3nf3PiP5T0P3n6wSyaM5H29Z5OQXEAA9Pppy4KjoO4kTS0D4vIqcBSVf2Ef/5xoFlVPzWU/yVLluiKFSsqqaJhGEbqEZHHVHVJVPJS0QcDbADmFpzP8d0MwzCMhJIWA/MosFhEFohIHXAacF/MOhmGYRglSEUfjKr2iMingF8ANcAPVHVVzGoZhmEYJUiFgQFQ1QeAB+LWwzAMwxgZaWkiMwzDMFKGGRjDMAzDCWZgDMMwDCeYgTEMwzCckIqJlmERkQ7gpTLFTAc2R6BOJTGdK4PpXBlM58rRp/chqhq89MUIyaSBiQIRWRHljNZKYDpXBtO5MpjOlcOV3tZEZhiGYTjBDIxhGIbhBDMww3ND3AqMAtO5MpjOlcF0rhxO9LY+GMMwDMMJVoMxDMMwnGAGxjAMw3BCpg2MiMwVkYdFZLWIrBKRFt99qog8KCLP+f9TfHcRketEpF1EnhSRYwpkLfP9Pyciywrc3yAiT/n3XCciZe1rW0Lny0Vkg4g84f9OLLjns/7znxGRdxe4L/Xd2kVkeYH7AhFp893v9LdAKEfnsSLyRxH5s6/zl0o9R0Tq/fN2//r80b6LA51vEZEXCsL5KN899rRRILdGRP4kIvf754kN5xI6pyGcX/TlPiEiK3y3xOYdJXSOL+9Q1cz+gFnAMf7xROBZ4HDgG8By3305cKV/fCLwM0CA44A2330qsMb/n+IfT/Gv/dH3K/6973Gk8+XAxUP4Pxz4M1APLACex9vSoMY/XgjU+X4O9++5CzjNP/4e8E9l6ixAg388Bmjzw2TI5wDnAd/zj08D7hztuzjQ+Rbg1CH8x542CnS5EPgxcH+p+ExCOJfQOQ3h/CIwvcgtsXlHCZ0vJ6a8I9M1GFXdqKqP+8c7gaeB2cDJwK2+t1uBU/zjk4Hb1OMRYLKIzALeDTyoqltVtRN4EFjqX5ukqo+oF+K3FciKWufhOBm4Q1X3q+oLQDtwrP9rV9U1qtoF3AGc7JeSjgfuHuL9R6uzquou/3SM/9MSzykM/7uBE3y9Qr2LI52HI/a0ASAic4D3Ajf556XiM/ZwHkrnABIRzgH6JTLvGAXO845MG5hC/OaBo/FKqjNUdaN/6WVghn88G1hXcNt6362U+/oh3F3oDPApv/r9g76q+Sh0ngZsU9WeKHX2m0CeADbhfUTPl3hOv27+9e2+XmHfJVKdVbUvnL/mh/M1IlJfrPMIdXOVNq4FLgHy/nmp+ExEOA+hcx9JDmfwChy/FJHHROQc3y3pecdQOkNMeUdVGBgRaQB+ClygqjsKr/mlh8SN1R5C5+uBQ4GjgI3AVfFpNxhV7VXVo4A5eCWgw+LVKJhinUXkSOCzeLq/Ea9Z49L4NByIiJwEbFLVx+LWZaSU0Dmx4VzAW1X1GOA9wPki8rbCiwnNO4bSOba8I/MGRkTG4GXUt6vqPb7zK34VFf9/k+++AZhbcPsc362U+5wh3CPXWVVf8TPEPHAjXiY+Gp234FXfa4vcI0FVtwEPA28q8Zx+3fzrjb5eYd8lap2X+k2Uqqr7gX9n9OHsIm28BXi/iLyI12xxPNBKssN5kM4i8qOEhzMAqrrB/98E/KevY6LzjqF0jjXvKNVBk/YfXufZbcC1Re7fZGBH3Tf84/cysKPuj3qgo+4FvE66Kf7xVB26o+5ERzrPKjj+NF7bKcARDOyoW4PXSVfrHy/gQEfdEf49/8HAjrrzytS5CZjsH48DfgecNNxzgPMZ2Pl812jfxYHOswri4VrgiqSkjSL9386BDvPEhnMJnRMdzsAEYGLB8R+ApSQ77xhO59jyjkgSTlJ/wFvxqrBPAk/4vxPx2hIfAp4D/m9BhAvwXbz+g6eAJQWy/hGvE6wdOLPAfQmw0r/nO/irIzjQ+Ye+Tk8C9xUlms/7z3+GgpEo/n3P+tc+X+C+0E/c7X6CqS9T59cBf/J1Wwn8a6nnAGP983b/+sLRvosDnX/lh/NK4EccGGkWe9oo0v/tHMisExvOJXROdDj7Yfpn/7eqLyxIdt4xnM6x5R22VIxhGIbhhMz3wRiGYRjxYAbGMAzDcIIZGMMwDMMJZmAMwzAMJ5iBMQzDMJxQG+zFMKqHfFtL3zBUgJlAL9ABLAJuyzW3nufgmRcAW3PNrbeVKecO4Iu55tbnIlHMMMrEDIxhFJBrbt2Ct6QG+baWy4FduebWb7l6Xr6tpRZvnsQxQX5HwPV4a36dHYEswygbMzCGMQLybS1vBy7ONbee5BueBXiTzubhzY4+Dm/9pw3A+3LNrd35tpY3AFcDDcBm4Ixcc+vGItHHA4/nmlt7/Of8Gm8C6N/gzcY+HW/drtcCd+aaW7+Qb2uZgLds+hy8mddfyTW33om3GsEt+baW2j55hhEn1gdjGKPjUDzj8H68megP55pbXwvsBd6bb2sZA3wbODXX3PoG4AfA14aQ8xageCHIrlxz6xK8pTjuxVvy5UjgDL8Jbynw11xz6+tzza1HAj8HyDW35vFmWL8+0jc1jFFiNRjDGB0/82spT+HVIn7uuz8FzAdejWcUHsy3teD7Ka69gLfB3NNFbvcVyFrVV+vJt7WswVuE8Cngqnxby5XA/bnm1t8V3LsJOJjBRsswKo4ZGMMYHfvBqzXk21q6c82tfWsu5fG+K8EzDm8KkLMXb82wQbJ9WfsL3PNAba659dl8W8sxeOtFfTXf1vJQrrn1y76fsb5Mw4gdayIzDDc8AzTl21reBJBvaxmTb2s5Ygh/T+ONUBsx+baWg4E9uebWH+Gt7ls4QOBVeAsoGkbsmIExDAfkmlu7gFOBK/NtLX/GWxX7zUN4/RnwtiHcS/Fa4I/5tpYngMuArwLk21pmAHtzza0vj1Jtw4gUW03ZMGIm39byn8Al5c5fybe1fBrYkWtuvTkazQyjPKwGYxjxsxyvs79ctgG3RiDHMCLBajCGYRiGE6wGYxiGYTjBDIxhGIbhBDMwhmEYhhPMwBiGYRhOMANjGIZhOOH/A4M01drwh1r0AAAAAElFTkSuQmCC", "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["# Example: 95 Hz\n", "\n", "import pylab as pl\n", "import matplotlib.pyplot as plt\n", "from scipy.signal import resample, medfilt\n", "import numpy as np\n", "\n", "fname = './data/L3.2-95Hz-115200bps.csv'\n", "\n", "raw = pl.loadtxt(fname, delimiter = ',')\n", "\n", "col_1 = raw[:, 0]\n", "col_2 = raw[:, 1]\n", "col_3 = raw[:, 2]\n", "\n", "plt.title('Example - 95 Hz', {'size':14})\n", "\n", "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", "plt.ylabel('ADC', color = \"#fdc86e\")\n", "\n", "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", "plt.plot(col_1, col_3, color = \"#474747\")\n", "\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["3) Devise a 3-bit DAC circuit considering the R-2R resistor ladder network (shown below), and characterize the expected behavior, namely the number of steps, step size, output voltages for each step, and other details that you may find relevant.\n", "\n", "\n", " \n", "
\n", " R-2R resistor ladder (image by Lsibilla).\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["4) Using the circuit devised in the previous question, create a firmware that outputs a sawtooth waveform with positive ramp. Present and discuss your experimental findings based on parameters of your choice. The following firmware is provided as a starting point."]}, {"cell_type": "markdown", "metadata": {}, "source": ["```C\n", "\n", "const byte TS = 100; // Sampling period\n", "const byte a0 = 5; // LSB in\n", "const byte NBITS = 3; // Number of bits\n", "\n", "byte data = 0; // Output value\n", "byte mask = 1;\n", "byte pin;\n", "byte maxCode = 1;\n", "\n", "void setup()\n", "{ \n", "\tSerial.begin(115200);\n", " for (pin = a0; pin < (a0+NBITS); pin++) {\n", "\t\tpinMode(pin, OUTPUT);\n", " maxCode *= 2;\n", " }\n", "}\n", "\n", "void loop()\n", "{\n", " mask = 1;\n", " pin = a0;\n", " \n", " for (mask=001; mask>0; mask<<=1) { // Iterate through bit mask\n", " if (data & mask) digitalWrite(pin,HIGH);\n", " else digitalWrite(pin,LOW);\n", " \n", " pin++;\n", " Serial.println(analogRead(A0));\n", " }\n", " \n", " (data == maxCode ? data = 0 : data++);\n", " \n", " delay(TS);\n", " \n", "}\n", "```"]}, {"cell_type": "code", "execution_count": 1, "metadata": {"scrolled": true}, "outputs": [{"data": {"image/png": "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", "text/plain": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["import pylab as pl\n", "import matplotlib.pyplot as plt\n", "\n", "fname = './data/L3.3.csv'\n", "\n", "raw = pl.loadtxt(fname, delimiter = ',')[:500, :]\n", "\n", "col_1 = raw[:, 0]\n", "col_2 = raw[:, 1]\n", "\n", "plt.title('Example', {'size':14})\n", "\n", "plt.xlabel('Time (ms)', color = \"#fdc86e\")\n", "plt.ylabel('ADC', color = \"#fdc86e\")\n", "\n", "plt.plot(col_1, col_2, color = \"#fdc86e\")\n", "\n", "plt.show()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["##
2. References
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["1. https://www.tinkercad.com/dashboard?type=circuits&collection=designs\n", "2. https://www.arduino.cc/reference/tr/language/structure/bitwise-operators/bitwiseand/ \n", "3. https://www.arduino.cc/reference/tr/language/structure/bitwise-operators/bitshiftleft/ \n", "4. https://en.wikipedia.org/wiki/%3F:#C "]}, {"cell_type": "markdown", "metadata": {}, "source": ["\n", " \n", " \n", " \n", " \n", "
\"it\" \n", " \"alternate\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
\n", "
\n", " Please provide us your feedback here. \n", "
\n", " Suggestions are welcome! \n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["```Contributors: Prof. Hugo Pl\u00e1cido da Silva; Joana Pinto; Afonso Raposo```"]}], "metadata": {"kernelspec": {"display_name": "Python 3.10.0 64-bit", "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.10.0"}, "vscode": {"interpreter": {"hash": "7e1998ff7f8aa20ada591c520b972326324e5ea05489af9e422744c7c09f6dad"}}}, "nbformat": 4, "nbformat_minor": 4} \ No newline at end of file diff --git a/B.Instrumentation/B004 Digital to Analog Converter - DAC/_Resources/R-2R.png b/B.Instrumentation/B004 Digital to Analog Converter - DAC/_Resources/R-2R.png new file mode 100644 index 0000000..563bf82 Binary files /dev/null and b/B.Instrumentation/B004 Digital to Analog Converter - DAC/_Resources/R-2R.png differ diff --git a/B.Instrumentation/B004 Digital to Analog Converter - DAC/_Resources/logo.png b/B.Instrumentation/B004 Digital to Analog Converter - DAC/_Resources/logo.png new file mode 100644 index 0000000..bcecbe0 Binary files /dev/null and b/B.Instrumentation/B004 Digital to Analog Converter - DAC/_Resources/logo.png differ diff --git a/B.Instrumentation/B005 Analog-to-Digital Conversion (ADC)/B005 Analog-to-Digital Conversion (ADC).ipynb b/B.Instrumentation/B005 Analog-to-Digital Conversion (ADC)/B005 Analog-to-Digital Conversion (ADC).ipynb index 02e14cf..623621f 100755 --- a/B.Instrumentation/B005 Analog-to-Digital Conversion (ADC)/B005 Analog-to-Digital Conversion (ADC).ipynb +++ b/B.Instrumentation/B005 Analog-to-Digital Conversion (ADC)/B005 Analog-to-Digital Conversion (ADC).ipynb @@ -1,568 +1 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "1e2a027b", - "metadata": {}, - "source": [ - "![scientisst-notebooks_top-banner](https://raw.githubusercontent.com/scientisst/notebooks/59632d3d477981a3b1cc12157e12bbdcdb45def8/_Resources/top-banner.png)" - ] - }, - { - "cell_type": "markdown", - "id": "3cf183a2", - "metadata": {}, - "source": [ - "# B005 Analog-to-Digital Conversion (ADC) " - ] - }, - { - "cell_type": "markdown", - "id": "36a4cefd", - "metadata": {}, - "source": [ - "### Keywords \n", - "`Analog to Digital Conversion (ADC)`, `Digital Signal Processing (DSP)`, `Embedded Systems`" - ] - }, - { - "cell_type": "markdown", - "id": "e09b7dc0", - "metadata": {}, - "source": [ - "### Notebook Info \n", - "\n", - "**Contributors:** Ana Sofia Carmo; Afonso Raposo; Joana Pinto; Prof. Hugo Silva\n", - "\n", - "**Date of creation:** unknown\n", - "\n", - "**Last update:** 09/2022" - ] - }, - { - "cell_type": "markdown", - "id": "e00a3dd5", - "metadata": {}, - "source": [ - "

\n", - " \n", - "

\n", - "

Analog-to-digital conversion (ADC). From [ref].

" - ] - }, - { - "cell_type": "markdown", - "id": "043fa9be", - "metadata": {}, - "source": [ - "### Description & Objectives \n", - "In the end of this session you should be able to:\n", - "* Understand the process of converting an analog signal to a digital representation\n", - "* Analyze the effect of data types in the throughput of your embedded system\n", - "* Learn about profiling and identification of hardware limitations" - ] - }, - { - "cell_type": "markdown", - "id": "22321ddf", - "metadata": {}, - "source": [ - "### Requirements \n", - "\n", - "* Basic knowledge of Arduino IDE" - ] - }, - { - "cell_type": "markdown", - "id": "fd4d8658", - "metadata": {}, - "source": [ - "### Materials \n", - "\n", - "* 1x Breadboard\n", - "* 2x 10kΩ resistors\n", - "* 1x TMP36 temperature (TMP) sensor\n", - "* 1x Seeeduino Nano\n", - "* 1x USB cable" - ] - }, - { - "cell_type": "markdown", - "id": "01d58803", - "metadata": {}, - "source": [ - "***" - ] - }, - { - "cell_type": "markdown", - "id": "69307772", - "metadata": {}, - "source": [ - "# 1. Introduction " - ] - }, - { - "cell_type": "markdown", - "id": "bd05ef21", - "metadata": {}, - "source": [ - "##
1.1. The Analog World
\n", - "\n", - "Any physical quantity that varies with time, space, or any independent variable can be defined as a signal. As they exist in the world, signals have a representation in any infinitely small portion of time, hence being designated as **_continuous signals_**. \n", - "\n", - "However, computational systems (either embedded - like the Arduino - or not) are only capable of dealing with binary representations (e.g. does a pin have voltage or not?). These are defined as **_digital signals_**.\n", - "\n", - "> ❓ **DID YOU KNOW?** In the last lab, when you used the digital port to read the voltage from the function generator, there was a 1-bit analog-to-digital coversion involved!\n", - "\n", - "As you've seen in the previous lab while working with digital ports, the microcontroller translates 0V to binary 0 and 5V to binary 1. But how can one represent a voltage of 2.5V (e.g.)?\n", - "\n", - "The process of reducing a continuous signal to a discrete signal is defined as sampling, and has the goal of retrieving a digitally manageable numerical representation of the underlying process with a given numerical precision. " - ] - }, - { - "cell_type": "markdown", - "id": "e756c91c", - "metadata": {}, - "source": [ - "##
1.2. What is an ADC?
\n", - "\n", - "The **Analog to Digital Converter (ADC)** of an embedded system is a peripheral that is capable of converting an analog voltage (applied as an input to a pin), to a digital representation. This is done by mapping the voltage to a set of digital codes using a finite number of **bits**. \n", - "\n", - "On the Seeeduino board, the ADC pins have an `A` as a prefix of their label (`A0` through `A7`), to indicate these pins can read analog voltages.\n", - "\n", - "\n", - "

Figure 1: Highlight of the analog ports on the Seeeduino Nano (A0 to A7).

\n", - "\n", - "\n", - "Some of the relevant specifications of an ADC are _resolution_, _voltage range_ and _quantization noise_ [[1]](#principles):\n", - "\n", - "#####
Resolution
\n", - "\n", - "Resolution specifies the number of different values that the output of the ADC can have (with _bits_ as the unit). In the example of the digital port (**1-bit**) we represent the input voltage at the pin with a set of **two discrete levels** $[0, 1]$. Expanding the number of bits, also increases our representation space. For example using **2 bits**, if we consider all the possible states ($00$, $01$, $11$, $10$) we have a representation space of **four discrete levels**, i.e. $[0, 1, 2, 3]$). \n", - "\n", - "In a more general form, the representation space will have $2^n$ discrete levels, with $n$ being the resolution of the ADC.\n", - "\n", - "ADCs can vary greatly between microcontroller. The ADC on the Arduino has $n=10$-bit ADC meaning it has the ability to map the analog input voltage to $2^{12} = 1024$ ($0$ to $1023$) discrete levels. Other microcontrollers have $12$-bit ADCs ($2^{12} = 4096$ discrete levels) and some have $16$-bit ADCs ($2^{16} = 65536$ discrete levels).\n", - "\n", - "#####
Voltage Range
\n", - "\n", - "The voltage range is the maximum to minimum input voltage that can be used at the input of the ADC. Anything larger or smaller than the extremes of the range will **saturate**, causing a decrease in accuracy of the digitized signal. \n", - "\n", - "\n", - "

Figure 2: Illustration of an inadequate voltage range of ADC for a particular signal of interest.

\n", - "\n", - "\n", - "#####
Quantization Noise
\n", - "\n", - "The quantization noise (or error) corresponds to the difference between the analog input signal and the digitized output. This error becomes smaller the higher the resolution (i.e. more accurate representation).\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "4a40be77", - "metadata": {}, - "source": [ - "##
1.3. Building Blocks of an ADC
\n", - "\n", - "Although there are other steps involved, the core processes of analog-to-digital conversion are **Sampling**, **Quantization**, and **Encoding**.\n", - "\n", - "#####
Sampling: Discretization of Continuous Signals
\n", - "\n", - "The process by which the input voltage is _sampled_ at regular time intervals is called sampling. The **Nyquist-Shannon theorem** states that to correctly sample a signal composed of frequencies up to $f_{max}$, the sampling frequency should be _at least_ $2f_{max}$. The figure below illustrates what happens if a pure sine wave is sampled at a frequency below the required: the shape of the wave given by the grey dots has a much lower frequency than the input signal - this phenomenon is called **aliasing**.\n", - "\n", - "\n", - "

Figure 3: Illustration of sampling at two different frequencies and the corresponding discrete output. In yellow, the sampling frequency (fs) corresponds to the minimum defined by the Nyquist-Shannon theorem; in grey, a sampling frequency below the minimum results in aliasing.

\n", - "\n", - "\n", - "\n", - "#####
Quantization: Separation into Levels
\n", - "\n", - "Quantization is the process of separating the input (discrete) signal into quantization levels. In its simplest architechture, this is achieved by a cascade of _comparators_ that saturate to $+V_{cc}$ when the input voltage is larger than the reference or to $0$ otherwise. \n", - "\n", - "> ⚡ **TIP:** You can think of the quantizer as a sifting tool that separates rocks and dust into buckets according to their size: each bucket will hold a range of rock sizes.\n", - "\n", - "As stated before, the number of **quantization levels** is determined by the resolution of the ADC. For an n-bit ADC, the number of levels given by:\n", - "\n", - "$L = 2^{n}$\n", - "\n", - "The number of quantization levels allows us to calculate the **least significant bit (LSB)**, which represents the smallest interval that can be detected by the ADC (hence also called voltage resolution), and is given by:\n", - "\n", - "$LSB = \\frac{V_{cc}}{L}$\n", - "\n", - "\n", - "#####
Encoding: Binary Representation
\n", - "\n", - "Remember that up until this step, everything is _hardware_, i.e. the outputs of the comparators will be a set of $+V_{cc}$s and $0$s. The encoder will convert the outputs of the comparators binary code. \n", - "\n", - "> 📋 **NOTE:** In the 1-bit ADC, the quantizer doubles up as the encoder, since it outputs the binary code directly.\n", - "\n", - "The figure below illustrates the quantization levels and corresponding output digital code for a 3-bit ADC and ramp input signal. \n", - "\n", - "\n", - "

Figure 4: Quantization levels and corresponding output digital code for a 3-bit ADC and ramp input signal. LSB: least significant bit; Quantization error: difference between the analog input signal and the digitized output.

" - ] - }, - { - "cell_type": "markdown", - "id": "923b217f", - "metadata": {}, - "source": [ - "# 2. Hands On \n", - "\n", - "Now that we know how the Seeeduino **reads** analog values, let's see how we can use the values that the Seeeduino **outputs to us**." - ] - }, - { - "cell_type": "markdown", - "id": "2a7d5a79", - "metadata": {}, - "source": [ - "##
2.1. Reading Analog Voltage with the Seeeduino
\n", - "\n", - "The ADC reports a ratiometric (raw) value. This means that the ADC assumes that the operating voltage $5V$ corresponds to 1023 ($2^n-1$, given that discrete levels start at zero) and anything less than $5V$ will be a ratio between $5V$ and 1023, given by:\n", - "\n", - "$\\frac{2^n-1}{V_{cc}}=\\frac{ADC_i}{V_i} <=>\\frac{1023}{5}=\\frac{ADC_i}{V_i}$ \n", - "\n", - "This way, you can easily convert the ADC reading obtained in the `Serial Monitor/Plotter` ($ADC_i$) to the input analog voltage ($V_i$).\n", - "\n", - "1. As you did in the previous lab, use the function generator to feed a sine wave into the `A0` pin of your Seeeduino. \n", - "\n", - "\n", - "

Figure 5: Arduino UNO and function generator: circuit illustration.

\n", - "\n", - "2. To read an analog voltage on the A0 pin of the Seeeduino board, you can use the default example, `Examples > 01.Basics > ReadAnalogVoltage`:\n", - "\n", - "```cpp\n", - "// the setup routine runs once when you press reset:\n", - "void setup() {\n", - " // initialize serial communication at 9600 bits per second:\n", - " Serial.begin(9600);\n", - "}\n", - "\n", - "// the loop routine runs over and over again forever:\n", - "void loop() {\n", - " // read the input on analog pin 0:\n", - " int sensorValue = analogRead(A0);\n", - " // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):\n", - " float voltage = sensorValue * (5.0 / 1023.0);\n", - " // print out the value you read:\n", - " Serial.println(voltage);\n", - "}\n", - "```\n", - "\n", - "3. Finally, use the `Tools > Serial Plotter` to visualize the signal read by the Seeeduino." - ] - }, - { - "cell_type": "markdown", - "id": "92672c6a", - "metadata": {}, - "source": [ - "## 2.2. Assembling the Circuit " - ] - }, - { - "cell_type": "markdown", - "id": "375f78b2", - "metadata": {}, - "source": [ - "Consider the Resistive Voltage Divider represented in the following figure. Assemble the circuit on a breadboard, powering it from your Seeeduino, and connect the analog output of the circuit to an analog input of your choice. \n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "

Figure 6: Resistive divider: circuit diagram (left) and example circuit illustration (right).

\n", - "\n", - "> ⚡ **TIP:** The voltage in `A` is defined by the formula of a resistive divider: $V_{A} = V_{R2} = V_{cc}[\\frac{R_2}{R_1+R_2}]$.\n", - "\n", - "> 💡 **EXPLORE:** Using Kirchhoffs law, can you prove the given formula?" - ] - }, - { - "cell_type": "markdown", - "id": "ac6c8172", - "metadata": {}, - "source": [ - "## 2.3. Streaming the Data \n", - "\n", - "\n", - "The following firmware allows to sample the analog inputs at a **configurable sampling rate** and stream them through the serial port, **together with the elapsed time** since the board began running the program. A formatted sequence of comma-separated values (CSV) is used (e.g. `