Difference between revisions of "EGR 224/Arduino Interfacing With Hardware II"

From PrattWiki
Jump to navigation Jump to search
(Bit Counting Assignments)
(Code Overview)
 
(2 intermediate revisions by the same user not shown)
Line 59: Line 59:
  
 
=== Code Overview ===
 
=== Code Overview ===
The goal for this code is to set up two digital output pins (P2 and P3) to serve as the 1's and 2's digit of a 2-bit binary number.  In the setup, the code will initialize each channel and set the output LOW.  In the loop, there is a loop that will go through the valid possible values of a 2-bit binary number (0, 1, 2, 3).  This inner loop will print the decimal equivalent of the number to the Serial Monitor and then use a function <code>send_to_lights()</code> to do the work of determining which lights should be on and which should be off.  The inner loop waits for half a second so we humans can track the lights as they change rather than enduring a stroboscopic light show.  
+
The goal for this code is to set up two digital output pins (P2 and P3) to serve as the 1's and 2's digit of a 2-bit binary number.  In the setup, the code will initialize each channel and set the output LOW.  In the loop, there is a loop that will go through the valid possible values of a 2-bit binary number (0, 1, 2, 3).  This inner loop will print the decimal equivalent of the number to the Serial Monitor and then use a function <code>send_to_lights()</code> to do the work of determining which lights should be on and which should be off.  The inner loop waits for half a second so we humans can track the lights as they change rather than enduring a stroboscopic light show. Here is the full code; each section is described below.
 +
<SyntaxHighlight lang=C++>
 +
// Set up Global variable
 +
int NL = 2;
 +
 
 +
void setup()
 +
{
 +
  // Start Serial Monitor
 +
  Serial.begin(9600);
 +
  // Initialize pins for lights and set low (off)
 +
  for (int light=2; light<=NL+1; light++){
 +
    pinMode(light, OUTPUT);
 +
    digitalWrite(light, LOW);
 +
  }
 +
}
 +
 
 +
void loop()
 +
{
 +
  for (int n=0; n<round(pow(2, NL)); n++)
 +
  {
 +
    Serial.println(n);
 +
send_to_lights(n); 
 +
delay(500);
 +
  }
 +
}
 +
 
 +
void send_to_lights(int val)
 +
{
 +
  for (int light=2; light<=NL+1; light++)
 +
  {
 +
    digitalWrite(light, bitRead(val, light-2));
 +
  }
 +
}
 +
</syntaxhighlight>
  
 
==== Global Variable ====
 
==== Global Variable ====
Line 98: Line 131:
  
 
==== send_to_lights ====
 
==== send_to_lights ====
This code will take a decimal value and then loop through the lights to determine how each light should be set.  As in the <code>setup</code>, there is a loop that loops through the pin numbers of the lights.  The core of this loop is the <code>bitRead(val, light-2)</code> part.  Arduino has a reference page on [https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitread/ bitRead()</code>.  The main idea is that you can give it an integer value for the first argument and a particular bit to read.  The function will convert the integer value into binary and then return the bit you asked for.  The second argument is basically which bit do you want, where bit 0 would be the LSB or 1's digit, bit 1 would be the 2's digit, etc.  Here are some examples of responses from <code>bitRead()</code>  
+
This code will take a decimal value and then loop through the lights to determine how each light should be set.  As in the <code>setup</code>, there is a loop that loops through the pin numbers of the lights.  The core of this loop is the <code>bitRead(val, light-2)</code> part.  Arduino has a reference page on [https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitread/ bitRead()].  The main idea is that you can give it an integer value for the first argument and a particular bit to read.  The function will convert the integer value into binary and then return the bit you asked for.  The second argument is basically which bit do you want, where bit 0 would be the LSB or 1's digit, bit 1 would be the 2's digit, etc.  Here are some examples of responses from <code>bitRead()</code>  
 
<syntaxhighlight lang=c++>
 
<syntaxhighlight lang=c++>
 
bitRead(6, 0) -> 0 // since 6 is 110 in binary and the 2^0 or 1's digit is 0
 
bitRead(6, 0) -> 0 // since 6 is 110 in binary and the 2^0 or 1's digit is 0

Latest revision as of 01:00, 26 March 2024

IMPORTANT NOTE

There are two breadboards in the bin

  • The smaller breadboard has a single row running along the top (all those are connected), a single row running along the bottom (all those are connected), and multiple groups of 5.
  • The larger breadboard hsa two sets of two rails at the top and two sets of two rails at the bottom. If you look at the blue and red lines at the top and bottom of the board, there are gaps in the middle - those gaps are meant to indicate that the left rails do not connect to the right rails; you can, of course, connect a wire between them if you want one long rail.

Inventory

You need to check the inventory of your box before you begin the lab. You will also be required to check your box in with a TA before leaving. Failure to get your inventory checked will result in a grade of 0 for this lab! Your box should contain:

  • Arduino Uno
  • USB Cable for Arduino Uno
  • 4 470 $$\Omega$$ resistors (yellow-purple-brown-gold)
  • 1 15 k$$\Omega$$ resistor (brown-green-orange-gold)
  • 5 LEDs (clear, red, yellow, green, and blue)
  • 18 wires(2 each of red, orange, yellow, green, blue, purple, black, white, brown, gray)
  • 2 buttons (one white, one brown)
  • 8-pin header
  • Smaller breadboard and larger breadboard (see note above about larger breadboard)
  • Screwdriver

If your box is missing anything or has anything extra, let a TA know at the start of lab to get your box in order.

Arduino Software Initialization

You may need to install the Arduino software on the computer. Search for "Arduino" - if nothing comes up as an installed program, go to Arduino Downloads and install the software.

Once installed. run it. A bank sketch should come up (or possibly the last sketch that was opened). Now connect the USB cable to your Arduino and then connect it to the computer. Wait for the computer to say it has finished recognizing / installing the Arduino. Once that is done, In the Arduino window, select the Tools menu, pick Board, and then find Arduino Uno or Arduino/Genuino Uno. Next go back to the Tools menu and select Port - there should be a COMN (Arduino/Genuino Uno). Finally from the File menu, pick Examples, 01.Basic, and Blink. Upload and run this on your board by clicking the right-arrow icon. After a few moments, the on-board light on the Uno should Blink. If that doesn't work, let a TA know.

Next, go to File, pick Examples, 01.Basic, and BareMinimum. Upload this to your Arduino. You should upload this sketch every time you plan to change the circuit connected to the Arduino so that all the pins are off.

Finally, to make the keypad work, you may need to install the Keypad.h library. To do that:

  • Go to the Sketch menu, then pick Include Library. If Keypad is already listed (likely near the bottom in the Contributed libraries section), the library is installed.
  • If Keypad is not listed, go to Manage Libraries and type keypad in the search box. Scroll down to the one named Keypad and install it.

Arduino Sketches

To create a new sketch, go to File and then New. The first time you want to upload and run a sketch, Arduino will ask you to save it somewhere. You can save it wherever you like, though "Documents" would be a good choice. Since these programs should already exist on Tinkercad, you will not be required to turn them in a second time.

Required Parts

All parts of the lab will require the Arduino, Arduino cable, and breadboard. Note: replace "small" resistors in the tutorials (220 $$ \Omega$$) with the 470 $$\Omega$$ resistors and replace the "large" resistor (10 k$$\Omega$$) with the 15 k$$\Omega$$ resistor.

Blink an LED

  • 1 470 $$\Omega$$ resistor
  • Red LED
  • 3 wires

Multiple LEDs

  • 3 470 $$\Omega$$ resistors
  • Red, Yellow, and Green LEDs
  • 5 wires

Pushbutton

  • 1 470 $$\Omega$$ resistor
  • 1 15 k$$\Omega$$ resistor
  • Red LED
  • 4 wires
  • Pushbutton

Traffic Signal

  • 3 470 $$\Omega$$ resistors
  • Red, Yellow, and Green LEDs
  • 7 wires (or connect short lead of LED to the ground rail directly, eliminating the need for three of the wires)

Bit Counting Assignments

The 2-bit counter example is at: 2-bit counter. If you would like to Tinker the model, you will need to be logged into Tinkercad before clicking the link. If all you want to do is look at the code or simulation, you can do that without logging in.

Code Overview

The goal for this code is to set up two digital output pins (P2 and P3) to serve as the 1's and 2's digit of a 2-bit binary number. In the setup, the code will initialize each channel and set the output LOW. In the loop, there is a loop that will go through the valid possible values of a 2-bit binary number (0, 1, 2, 3). This inner loop will print the decimal equivalent of the number to the Serial Monitor and then use a function send_to_lights() to do the work of determining which lights should be on and which should be off. The inner loop waits for half a second so we humans can track the lights as they change rather than enduring a stroboscopic light show. Here is the full code; each section is described below.

// Set up Global variable
int NL = 2;

void setup()
{
  // Start Serial Monitor
  Serial.begin(9600);
  // Initialize pins for lights and set low (off)
  for (int light=2; light<=NL+1; light++){
    pinMode(light, OUTPUT);
    digitalWrite(light, LOW);
  }
}

void loop()
{
  for (int n=0; n<round(pow(2, NL)); n++)
  {
    Serial.println(n);
	send_to_lights(n);  
	delay(500);
  }
}

void send_to_lights(int val)
{
  for (int light=2; light<=NL+1; light++)
  {
    digitalWrite(light, bitRead(val, light-2));
  }
}

Global Variable

The setup, loop, and send_to_lights() functions all need to know how many lights (bits) there are. NL is the number of lights and also the number of bits. Setting this as a global variable means later code can use that value rather than having a hard-coded number of lights.

// Set up Global variable
int NL = 2;

setup

There are two main parts to the setup. First, we will use the Serial Monitor to be able to track values. Second, we need to set up the pins on the Arduino as digital outputs and then set them to 0 so the lights all start off. Since we want to expand this code, the easiest way to do that is to run a loop that sets each pin. The loop variable could either be the power of 2 each pin represents (0 and 1) or the actual pin being used for those powers of 2 (2 and 3). In this code, the light variable is the pin being used, so the light variable should loop from 2 to one more than the total number of lights (in this case, that would be 3).

void setup()
{
  // Start Serial Monitor
  Serial.begin(9600);
  // Initialize pins for lights and set low (off)
  for (int light=2; light<=NL+1; light++){
    pinMode(light, OUTPUT);
    digitalWrite(light, LOW);
  }
}

loop

The loop function is itself going to contain a loop that iterates through all the possible values of a 2-bit binary number. The n value will start at 0 and iterate until reaching $$2^{NL}-1$$; for two lights, that means it will go through 0, 1, 2, and 3 before the inner loop ends (only to get called again when the loop function...erm...loops!). The inner loop will print the value being represented on the lights, call the send_to_lights(n) function (passing the value to be represented to that function), and then delaying by half a second. Note that the pow(2, NL) code essentially calculates $$2^{NL}$$, however the result is a floating point number, and there may be roundoff. Though the fact that we are using a < operator means slight smaller values than a true $$2^{NL}$$ would still work properly, round(pow(2, NL)) guarantees that the result from pow() is rounded to the nearest integer.

void loop()
{
  for (int n=0; n<round(pow(2, NL)); n++)
  {
    Serial.println(n);
	send_to_lights(n);  
	delay(500);
  }
}

send_to_lights

This code will take a decimal value and then loop through the lights to determine how each light should be set. As in the setup, there is a loop that loops through the pin numbers of the lights. The core of this loop is the bitRead(val, light-2) part. Arduino has a reference page on bitRead(). The main idea is that you can give it an integer value for the first argument and a particular bit to read. The function will convert the integer value into binary and then return the bit you asked for. The second argument is basically which bit do you want, where bit 0 would be the LSB or 1's digit, bit 1 would be the 2's digit, etc. Here are some examples of responses from bitRead()

bitRead(6, 0) -> 0 // since 6 is 110 in binary and the 2^0 or 1's digit is 0
bitRead(6, 1) -> 1 // since 6 is 110 in binary and the 2^1 or 2's digit is 1
bitRead(6, 3) -> 0 // since 6 is 110 (thus 0110) in binary and the 2^3 of 8's digit is implicitly 0

This means we can use a loop to interrogate each bit in the number and send that bit's value to the light using digitalWrite() - conveniently, digitalWrite() interprets 1 as HIGH and 0 as LOW for its second argument. As in the loop function, we have a decision to make about the looping variable - it could either be the digital pin we are setting or the bit location. To keep this loop consistent with loop's loop, the variable is the pin number, meaning the bit we are looking for is two less than the light number (i.e. the light connected to P2 needs bit 0, the light connected to P3 needs bit 1, etc).

Circuit Overview

Each bit will be represented by a different color light. The least significant bit will be a red light at the far right of the circuit board; more significant bits will be further to the left. Because the Arduino produces 5 V, and 5 V is higher than the maximum recommended voltage across an LED, we will put a 470 $$\Omega$$ resistor in series with the LED before connecting each bit's circuit to ground.

Arduino Support

Generating Random Numbers

The function random(a, b), where a and b are integers, will generate a random integer [a, b) (that is, between a (inclusively) and b (exclusively). If you wanted to roll a six-sided die, for example, you would use random(1, 7).

Getting an Integer from the Serial Monitor and Doing Something With It

See Worst Game Ever

For this game, the computer will generate a random number between 0 and 3. It will then expect you to type the number into the Serial Monitor input and send it. The Arduino will keep monitoring the Serial Monitor until it receives data. It will then use the Serial.parseInt() function to take the data it received and convert the information into an integer. Once it has the integer, it will increment the total number of times the game has been played. It will then use an if tree to print whether the answer was correct. Also, if the answer was correct, it will increment the variable keeping track of the correct number of answers. Finally, it will print out some boilerplate text and values as needed to communicate the state of the game.