# CSCI 250: Sensor Lab

## Goal / Turnin

The goal of this lab is to get practice deploying an actual sensor and displaying its data in Python. In the process, you will learn how to use an Arduino, the most popular platform for working with sensors, robots, and other devices. Arduino is a microcontroller; that is, a computer that runs one program at a time – called the sketch, firmware, or firmware sketch – allowing the computer to focus all its efforts on interacting with sensors and other devices.

## Part 1: Run Blinky on Arduino

As “Hello world!” is to introductory programming classes, “Blinky” is to Arduino. Although there are many kinds of Arduino (the most basic being the Arduino Uno we're using in this lab), every Arduino comes with at least one LED, a tiny light that can be used to indicate the status of your program. Blinky is the nickname for the Blink sketch that allows you to test the LED, by turning it on and off at regular intervals.

To run Blinky, first make sure your Arduino is plugged into your computer, using the USB cable I've provided. On the computers in our lab, you can plug the cable into one of the USB ports on the left side of the monitor. Once you do this, the LED will probably start blinking immediately, because Blinky comes installed as the default firmware sketch. Still, it will be worth going through the Blinky exercise.

As with IDLE3 for Python, Arduino has its own Integrated Development Environment (IDE). To launch the Arduino IDE, open a terminal window from your desktop (as you do to launch IDLE3), but instead of typing idle3, type arduino.

Once the Arduino IDE is up and running, the Arduino IDE should be ready to work with your Arduino Uno by default. To make sure that this is the case, go to the Tools menu. About halfway down the menu, you should see Board: Arduino/Genuino Uno. A few menu items below that, you should see Port: /dev/ttyACM0. If you don't see those values for the settings, use the menu to change the values. If you have difficulty doing that, let me know.

To upload (a.k.a flash) the Blinky sketch onto your Arduino, go to the File menu in the Arduino IDE, and follow the path to Examples / Basics / Blink. Another window will pop up, allowing you to work with the Blinky sketch. Since it's already pre-written for us, all we need to do is upload it onto our Arduino. You do this by clicking on the little (right-arrow) icon at the top of the IDE. A little orange progress bar will appear at the bottom of the IDE, after which your Arduino will blink rapidly (indicating upload in progress), and then the little orange LED should start (or return to) blinking at a slow and steady pace.

As a final step with Blinky, you're going to edit the C++ code in the IDE window to blink faster. Since you can't overwrite a built-in sketch, you'll save a personal copy of Blinky: Do File / Save As ..., and save the sketch to your desktop. Although you probably haven't seen C++ code before, it should be obvious how to edit the sketch to make the LED blink faster. Once you've done that, show me your fast-blinking Arduino.

## Part 2: Reading an analog sensor signal using Arduino

The simplest kind of signal you can get from a sensor is an analog signal. Unlike the digital signals we're studying in class (TTL, I2C, USB), an analog signal has a smoothly-varying voltage corresponding to the quantity you're sensing (light, temperature, pressure, etc.). The Arduino's built-in analog-to-digital convert (a.k.a. A/D Converter, or ADC) converts such a signal to a number that can be displayed or used in the sketch.

Each team has one such sensor, which you should now plug into your Arduino. Each sensor already has a set of jumper wires attached to it, each wire ending in a metal pin that you will plug into the appropriate place on the Arduino. (By convention, the term pin is also used to refer to the place on the Arduino where you insert the actual pin from the jumper.) So, connect the black (ground) wire to the GND pin on the Arduino, the red (power) wire to the 5V pin next to GND, and the green or blue (signal) wire to the pin marked A0.

As with Blinky, there's a pre-written sketch you can run to test your analog sensor: go to File / Examples / Basics / AnalogReadSerial. After uploading the sketch as you did for Blinky, you can display the values from your sensor by going to Tools / Serial Monitor. A new window should pop up, scrolling the values for your sensor. These will be “raw” values from the A/D converter, which normally we would then convert to meaningful units (degrees, millibars, centimeters, etc.) using additional code. For now it is sufficient to verify that you can see the numbers changing as you change the input to your sensor (move the flame closer, cover/uncover the light sensor, blow warm air on the heat sensor).

Because the Arduino IDE is running on your computer, the Arduino must be communicating with it over a serial channel; that is what you are monitoring with the Serial Monitor. You can also monitor a serial channel with a so-called “terminal emulator” program. Once such program is Python's miniterm script. To run this script make sure that your Arduino serial monitor is closed, and issue the following line in your terminal window:

  miniterm.py /dev/ttyACM0

You should see the same kinds of numbers scrolling by in the terminal window.

## Part 3: Displaying a signal in real time using Python

Displaying analog values from the Arduino is nice, but it would be more helpful to be able to plot them in real time. Because Matplotlib does not have built-in functions for plotting a signal in real time, I have written a little Python package that makes this easy. Like a lot of open-source software nowadays it is hosted on github. To get the package, just launch a terminal from the desktop and issue the following command (as usual, copy/paste is easiest):
  git clone https://github.com/simondlevy/RealtimePlotter

You should now see the RealtimePlotter folder on your desktop. Close the terminal window, open this new folder, and launch a new terminal from there. Now you can get a simple demo of the plotter by issuing the command
  python3 slowfast.py

You should see two signals scrolling by: a red dashed signal labeled Slow, and a solid blue signal labeled Fast. These signals are generated by the slowfast script using sine waves, as a simple way of making sure that the RealtimePlotter code is working correctly.

## Part 4: Displaying your sensor in real time

To use an analog sensor with your Arduino, you'll need to take two more steps:
1. Download one more package. Again, do this from a terminal launched from the desktop:
  git clone https://github.com/tino/pyFirmata

Inside the new pyFirmata folder you'll see a pyfirmata folder. Drag this pyfirmata folder into your RealtimePlotter folder.

2. Upload the Firmata sketch (File / Examples / Firmata / StandardFirmata) onto your Arduino, so it can talk to pyFirmata. (When I uploaded this sketch, I got a lot of nasty-looking orange warnings in the Arduino IDE, but it still worked.)
To help you connect your sensor to the real-time plotter, I've written a little script sensorlab.py, which you should download into your RealtimePlotter folder and run from the command line in the terminal window (instead of hitting F5 in IDLE, which as we've already seen makes it harder to figure out to debug your code):
  python3 sensorlab.py

Although you may get some nasty warnings in the terminal window, you'll soon see that the script just plots some random values between 0 and 1. It also is labeled with the convention XXX to show you where code will need to be added or modified. Once you've got the code working, you should remove the XXX, and replace the comment with a typical comment (e.g., # Connect to the Arduino).

Based on the example on page 267 of the textbook, you should now be able to add / modify code in the XXX locations. Since PyFirmata can be a bit flaky, I made sure to check that the value returned from board.analog[0].read() was not equal to None, before setting the ycurr value to it. Note also that it typically takes a few seconds for pyFirmata to connect to the Arduino.

Whichever sensor you have, you will find it helpful to print out the values you're getting from it. This will help you figure out the minimum and maximum values for initializing the plotter. As a final step before showing me your demo, see whether you can find any online documentation about how to convert the raw sensor value to meaningful units (like degrees Celsius, lumens, etc.)

## Finishing Up

Once you're done with all parts, please give me a demo, and have each of your team members sign the sign-out sheet to receive full credit for the lab.