Lab 01a

Getting Started

The questions below are due on Tuesday February 05, 2019; 10:00:00 PM.
 

Partners: You have not yet been assigned a partner for this lab.
You are not logged in.

If you are a current student, please Log In for full access to the web site.
Note that this link will take you to an external site (https://oidc.mit.edu) to authenticate, and then you will be redirected back to this page.

Goals:Today we'll hook up several initial components of our embedded system: the ESP32 microcontroller, the Liquid Crystal Display, and a button. The ESP32 is a powerful Wifi-enabled microcontroller development board built onto a small form-factor board. You'll also install several core pieces of software for the semester, before establishing communication between the microcontroller and the LCD, and finally implementing a simple state machine from a button.

You will work with a partner for this and all other labs in 6.08. Your partner should be listed at the top of the page along with a table location to sit at (all computer stations have numbers taped on them). Go find them!

Although you'll sit with your partner at one of the Macs in 38-530, you will use your personal laptops to access the course website and to interface with the microcontroller. The computers in the class do not have the right software on them.

Please use the 6.08 wireless network (id: 6s08, password iesc6s08) when connecting your laptops to WiFi and eventually your labkit.

Questions? In the lower right corner of your page will be a queue control pop up. If at any time you have a question, add yourself to the classroom queue (remember to add a table number) and a staff member will come around to help you.

1) Software

Today we'll be starting to use our embedded system based around the ESP32. For ease of deployment we'll use the Arduino environment and the add-on ESP32 core. You need to install some software on your laptop. Please follow the OS-appropriate instructions.

1.1) Windows Users

  • First install Arduino (even if you've already got it, install it again to get the most up-to-date distribution). The Arduino IDE can be found here. Download the appropriate distribution for your laptop's operating system. Note: Windows Users do NOT install the Windows App. Install only the regular Windows distribution!
  • Next install the ESP32 core. Open up Arduino and do the following:

    • Go to File>Preferences
    • Under the Additional Boards Manager URL field paste in: https://dl.espressif.com/dl/package_esp32_index.json and then Click OK
    • Now go to Tools>Boards>Boards Manager
    • In the window that pops up, search for esp32. One option should appear. Install it.
    • Now to prepare your Arduino environment to work with the ESP32, go to Tools>Boards>ESP32 Dev Module
    • You should be good to go now with software. We'll test it in a little bit.
  • You will also need to install a cable driver for your laptop. Go to here and install. Your operating system must be somewhat recent for this to be valid so if you get bugs, please talk to a staff member. In the zip file you download, there should be a README that will have somewhat clear instructions.

    • click “download VCP” under the appropriate version of Windows
    • Unzip the folder, run Installer_x64.exe if 64 bit or Installer_x86.exe if 32 bit

If you've done everything above and no errors came through, it means you've installed most of the correct software. Assuming this all went through, we can't do anything else until we get some hardware, so move onto the next part.

1.2) Mac OSX Users

  • First install Arduino (even if you've already got it, install it again to get the most up-to-date distribution). The Arduino IDE can be found here. Download the appropriate distribution for your laptop's operating system. Note: Windows Users do NOT install the Windows App. Install only the regular Windows distribution!
  • Next install the ESP32 core. Open up Arduino and do the following:

    • Go to Arduino>Preferences
    • Under the Additional Boards Manager URL field paste in: https://dl.espressif.com/dl/package_esp32_index.json and then Click OK
    • Now go to Tools>Boards>Boards Manager
    • In the window that pops up, search for esp32. One option should appear. Install it.
    • Now to prepare your Arduino environment to work with the ESP32, go to Tools>Boards>ESP32 Dev Module
    • You should be good to go now with software. We'll test it in a little bit.
  • You'll also need to install a cable driver for your laptop. Go to here and install. Your operating system must be somewhat recent for this to be valid so if you get bugs, please talk to a staff member. Mac Users: After installing, go to System Preferences > Security and click on the messable about enabling Silicon Labs Drivers on your machine!

Mac users should check the Security&Privacy tab in System Preferences, even if it looks as though the Cable Driver was downloaded and the Mac never informed the user that they need to override the security preferences in order to download the software.

If you've done everything above and no errors came through, it means you've installed most of the correct software. Assuming this all went through, we can't do anything else until we get some hardware, so move onto the next part.

1.3) *Nix Users

Below are instructions for relatively tame (Ubuntu-ish/Debian) family distributions. Note some nightly build of a Arch might have separate issues that we'll do our best to help with, but can't guarantee it'll work.

Because of some install issues, we strongly recommend installing from the Development Repo. This is different and a bit more involved than the Windows and Mac installations above. The Arduino Installer from the Boards Manager does a poor job setting the appropriate permissions in the broad array of Linux environments.
  • First install Arduino (even if you've already got it, install it again to get the most up-to-date distribution). The Arduino IDE can be found here. Download the appropriate distribution for your laptop's operating system.
  • Next install the ESP32 core. It is found here.Follow the appropriate instructions for installing in Linux (it will involve install git). Follow the instructions for Using Arduino IDE with the development repository.
  • Pay close attention to what the output of copy-pasting that script says. If there is an error or some text about unicode not existing you need to change the word python to python2.7 in that command string.
  • Make sure to install everything/run the scripts using Python2, not Python3! You should have this on your machine regardless, but some of you have renamed it from other classes.

  • You'll also need to install a cable driver for your laptop. Depending on what you want, there are two versions (try the version 3/4 one first):

When you've installed everything you should be able to open up Arduino and in the top right you should be able to see in the menu Tools>Board>ESP32 Dev Module. If you see that, it means you've installed most of the correct software.

The only other issue that may appear, dear *Nix user is that you don't have permission to program your ESP32. This can be fixed temporarily (after the device has been plugged in by running either):

sudo chmod 666 

on whatever port your ESP32 shows up as (for example on my Ubuntu box, it'll be /dev/ttyUSB1 or /dev/ttyUSB0). This is only a temporary fix, however, and will need to be re-run every time you plug in the device.

The other (longer term) option is to add yourself to the dialout group. Do this by running the following command:

sudo usermod -a -G dialout YOUR_USERNAME_HERE

where you replace your username in. Once this is done, you will need to restart your computer for this change to take permanent affect.

Assuming this all went through, we can't do anything else until we get some hardware, so move onto the next part.

2) Hardware

Each person should obtain from staff the parts for today, which for reference are:

  • The ESP32 Dev Board
  • The TFT Display
  • 3 mini breadboards with backpiece
  • A kit of wires
  • A micro USB cable
  • A button switch
  • A padded envelope which you can use to hold everything (we'll eventually provide LiPoly-safe bags but those are delayed)

This is the start of your 6.08 kit and you must keep this all semester and bring it to every lab.

2.1) An Important Test...

With parts in hand, the final test which makes sure everything is working, is to take a peek at Tools>port in your Arduino environment. You should see maybe one thing listed. Take note of what is there. Now take your Micro-USB-to-USB cable, connect it to your ESP32 board and then to the computer, and take a fresh peek at Tools>port. You should hopefully see one more thing. On Windows this will often be something like COM3. On Mac/Unix it will probably be USB_to_UART.... If it appeared, then you are 99% good.

Check Yourself:

Does your ESP32 appear under Tools>port when you connect it to your computer? If not, ask for help from a staff member.

OK we're now ready to start assembly.

Each partner should build up their own system and do their own wiring. This will be yours to use for the duration of the course, so treat it nicely!

We will construct our circuits on a proto-board (also known as a "breadboard"), which provides an array of holes into which wires and components can be inserted. Certain rows and columns of the holes are electrically connected together, and the holes have spring-loaded clamps in them providing a convenient way to securely connect components together. Specifically, each column of 5 holes is connected internally. If you insert one end of side of a component into one set of the holes in a column of 5, and then insert one side into a second set of holes across the gap, the pins will not be connected together.

If you were to rip the back off your breadboard (DO NOT DO...we ruined the one in the photo so you don't have to!) you could more clearly see which rows and columns are connected.

breadboards side by side

The back of a breadboard, revealing the metal connectors inside. Note how there are many short connectors (with five connecting holes), usually used for linking signals, and only several longer connectors, often called "rails" or "busses" and which we'll use for power distribution.

The strategy in using a breadboard is to place components at conveniently close locations to one another and then use hookup wires to connect the appropriate electrical pins together to enable communication, control, transfer of signals and power, etc.

There are good and bad ways to wire a breadboard, just like there are good and bad ways to write code. The general rule is to keep the wires short and sweet...avoid large loops. Because poor wiring now will have an impact on you through the semester, we will provide suggested wiring and placement schemes in this and many of the labs.

We'll eventually have quite a few components so we're going to attach three breadboards together for our system, but first, we need to break off both the power rails from the middle breadboard. Take one of your breadboards and snap off the rails connected to either side of the protoboard, like this: (use scissors available in class to cut off the excess paper. Take care not to expose the sticky back just yet).

remove the rails

Remove the rails from the central breadboard. there are scissors and other cutting implements around to assist you in doing this.

Here's more of a storyboard for your benefit:

board assembly 1

You'll start with (A) three half-breadboards and a backing piece of acrylic. (B) We'll ultimately want all three boards to sit side-by-side linked together, but as they are, they're too large. Lay them out so that they are in line and can order them. (C) Take the middle one and remove one of its inner rails by bending it down, and (D) with scissors cutting it off carefully. (E) Attach the side to the main central board so you'll end up with (F). (G) Repeat for the other side, to (H) ultimately end up with three boards linked together like shown.

Once the boards are together, we'll mount it on a piece of acryllic for stabilization by exposing the sticky breadboard backing:

board assembly 2

We want the three boards to ultimately be attached to the piece of acrylic to add some stabilization. (A) To accomplish this, lie your breadboard set on its face, and carefully remove the adhesive back (B) resulting in an exposed sticky surface. (C) Take the piece of acrylic and while using your eyes to line it up, (D) attach it to the breadboards and apply pressure on contact (E) so that you end up with a stable board assembly like shown.

Now it is time for parts!

2.2) The ESP32

We'll first place our ESP32 into the breadboard. We recommend placing it approximately where shown in the figure below. We'd like to make sure that the red and blue rails are connected to the pins marked 3.3V or 3V3 and 0V or GND on your ESP32, respectively. Depending on the model of your ESP32, the pin labels may be different. This is achieved using some short wires like so:

esp connection

Adding two wires to connect where the ESP32's 3.3V and GND pins will be to the rails we want to be 3.3V and Ground.

Then insert the ESP32 like shown:

esp to oled connections

Gently insert the ESP into the breadboard so its pins line up with the wires we just inserted.

The ESP32 has a ton of pins on it in addition to those that channel power. A list is shown below:

esp pinout

A pinmap of most of what we'll use the ESP32 for this semester. Don't worry we'll go over what many of these acronyms mean in good time.

Although we'll want to gradually gain experience hooking up components by referencing their data sheets, today we'll walk you through the connections in detail.

On the ESP32, we'll very often be using pins with labels that look like IO4 or IO15, etc, however many ESP boards that we got in this year's batch just have the pin number on them. Either if it says "IO5" or just "5", they are the same thing and the "IO" part stands for Input/Output, and the number following that. These pins can often serve several purposes, depending on how they are configured in the setup function of our code. We'll use a subset of these pins now to establish communication with our LCD.

2.3) The LCD Display

lcd

Our nice LCD. You can see the pin labels are on the back!

The LCD is a Color Liquid Crystal Display (fancy). The LCD has eight connections/pins:

  • power supply (3.3 V) - VCC
  • ground (0 V) - GND
  • backlight control (to turn on the LED) that shines through the Liquid crystal)
  • five wires that serve as data connections for the SPI communications interface

oled schematic

LCD schematic. This is how we'll hook it up.

We'll learn more about SPI in the future, but for now we just need to know that the SPI set of wires (or "bus" as we call it in EECS) is how the microcontroller will communicate with the LCD to tell it what to display. We just need to connect the LCD SPI pins to the corresponding pins on the ESP32.

We recommend placing the LCD to the left side of your setup. To connect the LCD to power we'll use short wires to connect its pins back to the available +3.3V and GND power rails. You'll also need to make sure the back-light (LED pin) is connected to the 3.3V power.

esp to oled connections

We'll use some more wires to route a power path to the LCD and other wires for the data lines.

Then by paying attention and tracing the pin connections found in the schematic above we add appropriately sized wires for the five data lines. Note the wires in your kit are color-coded based off of length. The end result should be the similar to the image below. Your board does not need to look exactly the same, but if you want any custom-length wires, ask a staff member and they can show you where/how to do that.

esp to oled connections

Wires in place, without and with our LCD in place.

Before moving on, notice how in the left panel of the figure above we've added two extra jumper wires to connect to the lower +/- rails. This means that the second set of +/- rails is now also capable of providing 3.3V and GND as needed. We'll use this in a little bit!

2.3.1) Getting the LCD to Work

We now want to do something with that LCD. In order to do that we'll need to install a library. There's a few ways to do this in Arduino. What we'll do is manually manage our files. Download this TFT library, extract it (actually extract it, don't just double-click on it), and copy it into your Arduino libraries folder. This should be located under Documents/Arduino/libraries in your File structure (or something very similar.).

Exit Arduino, and then reopen it (you need to do that when manually installing libraries). Finally, extract the first starter code for today, compile it and then upload it using the Right Arrow Button.

If all is right with the world, you should see a bunch of cool images and other stuff flying by in a repeating loop like shown below:

Check Yourself:

If your screen is not working, ask for help!

2.3.2) The Code in Detail

You now should look a little bit through this code and go over some of the main pieces. It will serve as a good example of the high level structure of many of our microcontroller-based programs for this term. Our microcontroller scripts will have a .ino suffix. There are always two primary functions defined in these .ino-type files: setup and loop, both of which take no arguments. When building and compiling code to place on the ESP32 microcontroller, the software will place these two functions into the following general file type:

#include <Arduino.h> //a library that contains basic libraries/functionality we use!
//all outside code gets placed in the following form.

void main(){ //runs once
  setup();
  while (1){ //infinite loop
    loop(); //runs repeatedly because it is in the infinite loop
  }
}

The net result is that setup runs once, and loop runs repeatedly and as fast as we allow it. The speed at which these functions execute is based on what exactly we do within them. Each line of code that we place in a function comes with certain computational cost, and roughly speaking, these computational costs correspond to time.

2.3.3) Communication

Writing code of more than a few lines is very difficult without an ability to debug it. In the Arduino environment, we can gain an insight into what the code is doing using communication up via the USB cable. In the Arduino environment, we achieve this with the Serial library. We initialize Serial communication by saying Serial.begin(115200); in the setup function and can report information up to the computer by calling Serial.print or more often Serial.println and using the Arduino Serial Monitor (Tools > Serial Monitor) to see what pops out.

2.4) Switch

We now have an output (the LCD). Next we'd like to add an input. For this lab we'll add a simple switch. It comes in three pieces and you can snap it together like a LEGO. Before we do that a quick note on schematic notation. Because we will very often use the 3.3V pin and the GND pin to provide power to components, we often don't explicitly show connections when drawing them in schematics. Instead we'll show those connections going to a common point and it is assumed that they are connected "off-page".

vcc and gnd

VCC (which on our board is 3.3V) and GND are used so often we will generally use the shorthand shown above to represent the connection.

OK now let's add in a switch to IO pin 19.

switch spot

The final schematic that we want with our switch.

The switches we can use can be shoved into the breadboard like shown. Take care to position it in the right orientation.

esp to oled connections

There are four pins on these switches. Each side of the switch is connected to two pins.

Earlier in our wiring adventure we connected up the lower +/- breadboard rail to 3.3V and GND and hid that connection underneath the LCD (take a look at Figure 11). This now allows easy wiring of our switch like shown below:

esp to oled connections

Everything all connected! With minimal long wires. Delicious.

3) Our First Input

How do we use this switch on the software side? We need to set it up as a digital input. This is accomplished by calling the pinMode function and specifying the pin number of interest and that we want to set it as an input. In the switch circuit that we just built, when the button is pushed, it connects the two terminals together, such that the ESP32's Pin 19 is now connected to GND, and thus the input that is read is a binary 0, which we often call a "LOW". What is the value when we're not pushing the button? If you think it is "HIGH" that's sorta correct...but also sorta not. A HIGH voltage of 3.3V does not just magically appear. It needs to be placed there just like a voltage of 0V needs to be placed onto the pin. In the current configuration, only one state has a well-defined voltage...namely the pushed state will show up (0V). When the button is unpushed, the state of the digital pin is actually undefined! This can lead to weird behaviors where the digital input randomly reads weird values and your code could interpret this as button pushes and not button pushes. In order to fix this, we therefore need to specify the input as a particular type called a pull-up and this can be done with specifying INPUT_PULLUP for the second argument.

How can we just use a random word like INPUT_PULLUP? It is because in other hidden files that are being used, that variable name is defined as a particular number that the pinMode function knows how to handle.

The result of doing this is that in the unpushed state the inputs to the digital pins are "pulled-up" to 3.3V which is a HIGH voltage, meaning that in both the pushed and unpushed states the state of our switch/digital pin circuit is now well-defined.

3.1) Active High vs. Active Low

You may be a little weirded out because in an unpushed state, our switch is "HIGH", and in a pushed state our switch is "LOW". This configuration is known as "Active Low" and is actually very common in electronics. Much less common in electronics is "Active High" which is when a switch's state is LOW normally and HIGH upon being pushed. From the engineering perspective of our class, we won't worry about the reasons for this bias towards Active Low, but we do need to use this knowledge to know how to interpret signals read in on our digital inputs.

So attached is some starter code.

const int input_pin = 19;

void setup(){
    Serial.begin(115200); //initialize serial!
    //Set up an Active Low Switch!
    pinMode(input_pin,INPUT_PULLUP); //sets IO pin 19 as an input which defaults to a 3.3V signal when unconnected and 0V when the switch is pushed
}

void loop(){
    int value = digitalRead(input_pin);
    if (value){
        //executed if pin is HIGH (voltage of 3.3V)
       //code here for printing "unpushed" 
    }else{ 
        //executed if pin is LOW (voltage of 0V)
       //code here to print "pushed" 
    }
}

Copy-paste the code above into Arduino, and update the code shown above to print a message of "pushed" or "unpushed" on the serial monitor when the button is being pushed or unpushed, respectively.

Make sure that you have the correct BAUD (115200) chosen in your Serial monitor, otherwise a bunch of random question marks will fly by.

Checkoff 1:
Show your button-controlled Serial-printer to a staff member.

4) Stateless vs. Stateful

When running this code, when you press a button, your serial monitor displays one thing, and then when you don't press the button, another thing gets printed. At any point in time your system behaves based only upon its current input value and nothing else. It has no state.

State means "state of being" or something along those lines. Basically a system/device/machine in which what it does at any point in time is based not only on its current inputs, but also its past inputs is what we'll call a state machine. Most things in life that do anything interesting can be classified as one form or another of a state machine. Another way of thinking about state machines is that for a given identical input, its response might vary depending on its state, while a stateless system will always act the same way given an input. Me eating food is a state machine...I see food and I eat it...then I see food and I eat it...then I see food and I'm like, I'm good/full. My pet dog growing up was a stateless machine...he'd see food and eat it and then see food and then eat it...and so on...he'd never stop. (obv a joke because eventually he'd have a vomit output).

Anyways one way to visualize state machines is by using a state flow diagram like the one shown below, where upon starting the system begins in State 0. In State 0, if the getInput() function returns a 5, the machine moves into State 1, otherwise, it stays in State 0. If the machine is in State 1, if it gets a 2 as an input it moves to State 0, otherwise it stays in State 1.:

simple fsm example

State machine example.

In code form for our ESP32, this would look like the following.

int state;

void setup(){
  Serial.begin(115200);
  state = 0; //initialize!
}
    
void loop(){
  //handle state transition if it happens
  int input = getInput();
  if (input==5 && state==0){
    state = 1;
  }else if(input==2){
    state = 0;
  }
  //handle output based on state:
  if (state==1){
    Serial.println("Wheeee.");
    //do something corresponding to state 1
  }else{
    Serial.println("Whoooo.");
    //do something correspondign to state 2 
  }
}

If the system just printed "Wheeee.", and getInput() returns a 2 on its next call, what will the next thing printed by the system be?

Following the event in the previous question if call getInput() again returns a 2, what will the next thing printed by the system be?

The key piece here is that there is some sort of variable which "lives" beyond the scope of the function in question. In particular in our situation that is the loop function. Every time loop starts over, any variables declared within it are new, so having a variable outside of its scope allows us to remember information beyond each "run" of loop. We'll obsess over state variables more in the next lab. `

5) Final Assignment

We'd now like to implement a state machine that acts in the following way:

Feel free to use this code (and reference the earlier code) as a starting point: lab01a_assignment.zip

Some general documentation for the TFT library can be found here: TFTLibrary. Note that some specifics of that library (mostly in how to instantiate TFT objects) is different so use the code we provide for reference to how to instantiate the TFT object and write text, etc... but the majority of the docs, such as how to draw a square for example, are valid!

The system should operate in the following way:

  1. Starts displaying one word or image on the LCD (your choice. Feel free to experiment).
  2. When the user presses and then releases the button it starts displaying another image (again your choice, but it needs to be significantly different...like maybe a triangle, you pick, you're the artist).
  3. When the user presses and then releases the button again it goes back to displaying the first image.
  4. The system can continue to toggle between these two images based on button presses forever.

A rough state diagram looks like the following:

switch flow diagram

This is a switch flow diagram for our two-image state machine!

Your final system should look like something similar to the functionality in the video above.

Checkoff 2:
Show your working button state machine to a staff member, discuss your design and code, and answer any questions the staff has about the wiring you carried out. Staff will stress test to see if it works well or not.


This page was last updated on Wednesday February 06, 2019 at 07:32:02 AM (revision 1beb64e).
 
Course Site powered by CAT-SOOP 14.0.4.dev5.
CAT-SOOP is free/libre software, available under the terms
of the GNU Affero General Public License, version 3.
(Download Source Code)
CSS/stryling from the Outboxcraft library Beauter, licensed under MIT
Copyright 2017