Link Search Menu Expand Document

Networking and communication

Last day for on-time checkoff: Tuesday, 11/14 (two weeks)

Prelab due 10/30/22 at 11:00 am

Writeup due 11/13/22 at 11:00 am

About

In this lab, you will explore different ways microcontrollers can interact with other entities, such as other microcontrollers and the internet. You will use the MKR1000’s built-in serial capabilities, and then write your own software UART to build understanding of how serial communication works. You will also see how to use your MKR1000s’ built-in WiFi modules to communicate with a webpage. By the end of this lab, you should be comfortable with using your Arduinos to communicate with other devices.

Lab 7 Rubric

Resources

Starter code

Materials

Included in your kits:

  • 2x Arduino MKR1000 and USB cable
  • 5 resistors (3 x 1kΩ 2 x any size, both same size)
  • 1 x RGB LED or 1 each of red, blue, and green LED
  • Jumpers/wires

Provided:

  • None necessary

Steps

  1. If you haven’t registered your Arduino to the Brown-Guest network, installed the WiFi101 library, updated firmware, or uploaded the www.random.org SSL certificate as described in the prelab and this Ed post, do so now. Only one Arduino from each group needs to go through these steps.

  2. Your Arduino has built-in serial communication that you can use to send data between two Arduinos. Explore this here:

    1. Wire up the following circuit. Notice that the TX pin of one Arduino goes into the RX pin of the other Arduino, and vice versa. Check that you haven’t mixed this up before powering on your circuit. Also, be sure to connect the GND pins of both Arduinos to each other! For this circuit, you do not have to put both Arduinos on the same breadboard, or any breadboard at all. If you want, you can wire up this circuit by using 3 stranded jumper wires and putting them directly into the pin headers of the Arduinos.

      L07D01

    2. You can connect both Arduinos to one computer, or use two different computers. If you are using the same computer, you can switch between Arduinos by changing the port under Tools -> Port. You will have to do this even if you have multiple IDE windows open. Notice also that the Serial monitor changes which Arduino it is receiving data from based on which port is selected – this sometimes even happens in both IDE windows.

    3. The Serial documentation shows that the TX and RX pins of the MKR1000 are associated with Serial1. Hence, you can initialize the communication between Arduinos just like you initialized communication with the Serial monitor:

      void setup() {
        Serial.begin(9600);  // Initialize serial monitor
        while (!Serial);     // Wait for serial monitor to start (need this for USB serial)
        Serial1.begin(9600); // Initialize TX/RX communication (do not need to wait)
      }
      
    4. Make a new sketch called sender.ino that, in the loop() function, uses Serial1.write to send a string of your choosing, such as “Hello World!”, every 2 seconds, via Serial1. Upload it to one of your Arduinos.

    5. Make a new sketch called receiver.ino that, in the loop() function, reads bytes from Serial1 into a buffer and then prints that buffer to the Serial monitor (the computer screen). Refer to the Serial.read documentation to see how to do this (remember to use Serial1). You can cast bytes to chars directly, i.e. Serial.println((char) b) if b is of type byte. It is okay to print each character on its own line. Upload it to your other Arduino and open the serial monitor. If you see the Serial monitor printing your string from 2d above, get checked off by a TA!

  3. Now connect the sender to the internet!

    1. Download the starter code and open lab7.ino as a new Arduino project. Run the code on the sender Arduino and observe the output on the Serial monitor (you do not have to be running the receiver Arduino for this step). What do you see?

    2. Study the code in lab7_wifi.ino. In sendHTTPReq, the code uses the random.org http API to ask for a random number between 1 and 3 (inclusive). Typically, random.org uses atmospheric noise to generate random data, but you can also provide a seed so that it uses its pseudorandom number generation algorithm. Every time you make a request with the same seed, you will get the same result – this will be useful for us when we want all of the Arduinos in the class to be in sync! For now, our code uses millis() as the seed.

      In readWebpage, the code outputs the response from random.org. As given to you, the code prints the entirety of this response, including header information. Change the code so that only RED (for a response of 1), GREEN (for 2), or BLUE (for 3) gets printed to the Serial monitor whenever the file is fetched. You can ignore any server errors or responses that don’t have 1, 2, or 3. Hint: a successful HTTP response will have the message we’re looking for in the second-to-last character. How can you modify the while (client.available()) loop to keep track of the second-to-last character that was seen?

    3. Modify your sender code such that it sends one of ‘r’, ‘g’, or ‘b’ (depending on what it gets from random.org) gets sent to the receiver via Serial1 (remember to add Serial1.begin(9600) in setup). The end result is that the receiver should not be connected to the internet, but should be displaying the color corresponding to the HTTP request in (more or less) real-time because it is communicating with the sender (which is connected to the internet). Observe that the receiver is receiving and displaying these values (you should not have to change your receiver code). Get checked off by a TA.

  4. Now write your own Serial transmitter and receiver! As stated in the prelab, you will implement UART in software.

    1. Comment out the Serial1 code from step 3c. Also uncomment the lines in lab7.ino after the comment that says Uncomment for LAB STEP 4a. Observe how uartReceive is an interrupt service routine that triggers when inPin is FALLING (goes from HIGH to LOW). Check with your partner that you agree on why this is.

    2. Wire up the following circuit. For the LEDs, you may use one RGB LED or a red, a green, and a blue LED. Just make sure that red is connected to pin 0, green to 1, and blue to 2 (make a new sketch to test this if you’re using the RGB LED). The resistors between pins 3 and 5 of both Arduinos can be any resistance (technically they are not necessary if the pins are configured correctly, but we add them to limit the current just in case of a mistake in software).

      L07D02

    3. You will upload the same code to both Arduinos, except for the line under LAB STEP 4c/4g, which will configure one as the sender and one as the receiver. This means that both Arduinos are capable of sending and receiving data, even though, in this lab, the sender will be using the send function only and the receiver will be using the receiver function only. The writeup asks you more about this design.

    4. The sender and receiver have the following roles in this step:

      Sender: continuously reads 1, 2, or 3 from random.org using the seed described below and stores data in a buffer (sBuf). Reads from the buffer and sends ‘r’, ‘g’, or ‘b’ to the receiver via the UART.

      Receiver: reads ‘r’, ‘g’, or ‘b’ from the UART into a buffer (rBuf). Reads from the buffer and lights up the corresponding LED.

      sBuf and rBuf and the corresponding indices are defined in lab7.h. Characters are stored in 8 bits, so you can cast a char to a byte (and vice versa) easily (e.g. (byte) 'r').

    5. Code up the necessary code for the sender. We have commented LAB STEP 4e in some places of the code to guide you. In the function uartSend (lab7_uart.ino file), you should fill in the blanks according to the answers from your prelab. Notice how the clock period of the UART is enforced using software.

      You should make functions that read from/write to the buffer sBuf atomic, by disabling interrupts whenever you write to/read from the buffer. The Arduino functions interrupts() and noInterrupts() will help you accomplish this. Also remember to check that sBuf will not fill up before adding to it!

      We want all of the devices in the room (including the TA reference circuit) to have the LEDs changing in the same sequence, give or take a second or two. We can accomplish this by all using the same seed at the same time. For now, we’ve been using millis() as our seed in our HTTP request to random.org. However, millis() gives us the time since the power-on of our specific Arduino.

      In order to all have the same seed at the same time, we will use (the number of seconds since Jan 1, 1900) / 3 (rounded down using integer division) as our random seed, so that a new random value is received every 3 seconds. In order to get the time, we communicate with an NTP server (in class, we learned that NTP is a protocol that uses very precise time servers). We give you the code to do this in lab7_wifi.ino. The code borrows heavily from the WifiUdpNtpClient example found under Examples -> WiFi101. UDP is an internet protocol that is sometimes faster than TCP (used by HTTP requests), since it makes no guarantees about packets being received in order or at all. This is fine for a reliable time server for which we know the IP address. (More information about the difference between UDP, TCP, and other internet protocols is outside the scope of 1600 and can be learned in a networking class).

      You don’t have to make multiple requests to the NTP server – the one the starter code makes at the beginning of the code is sufficient to keep track of time for our purposes. Take a look at how we use millis and some values we stored to compute the current number of seconds since Jan 1, 1900 in the connectToNTP function, and adapt this idea to change the random.org HTTP request seed to (the number of seconds since Jan 1, 1900) / 3.

    6. Code up the receiver. We have commented LAB STEP 4f in some places of the code to guide you. When you check the parity bit for messages you receive, you should discard messages for which the computed parity does not match. You should also discard messages that are not ‘r’, ‘g’, or ‘b’. Similarly to the step 4e, you should fill in the blanks to uartReceive according to the prelab, make functions that read from/write to the buffer rBuf atomic, and remember to check that rBuf will not fill up before adding to it!

    7. Upload the code to both Arduinos, remembering to toggle the SENDER flag (under comment LAB STEP 4c/4g). Run and debug the code. When debugging, it may be helpful for the receiver to write what it is receiving (and the messages it may be discarding) to the Serial monitor. Once you are confident it works, get it checked off by a TA. Your TA will have a reference implementation that reads from the same website, so you should be seeing your LEDs and the TA’s LEDs display the same light sequence (give or take a second, and assuming the network is reliable).

  5. Turn in the lab7_uart.ino code on the Lab 7: Code Gradescope assignment