MEM 459/540 - Summer 2021 Lab 1: Three LED Blink Approaches Professor: Dr. Bor-Chin Chang Section: 001 Group: 01 Member Name Email Student ID Lauren Lugones Lml355@drexel.edu 14214305 Thomas Visconto tev23@drexel.edu 14156400 Tenzin Wangdak ttw38@drexl.edu 14243263 mam893@drexel.edu 14220231 Tz99@drexel.edu 14220024 Muhammad Meajun Tommy Zheng Abstract Within the experiment there were three individual Arduino codes that needed to be manipulated for the RC circuit to display the input/output response of the system according to the specified blink pattern. All three of the codes have been successfully updated, upon which the RC circuit will blink for 1 second, turn off for 0.5 seconds, and repeat that for 10 cycles. Furthermore, to read the output response of the system from the inputs, the individual Arduino code is updated to the Arduino board and a serial monitor will display the High and Low, where we can view the response of the RC circuit. Introduction The purpose of the lab was to illustrate that Delay, Polling, and Interrupt commands can achieve the same desired result through the Arduino program. Upon the results, certain conclusions could be made as to whether which Arduino command is more effective to utilize for LED blink approach. An advantage “interrupt” has over both “delay” and “polling” is that it can execute the same job while avoiding repeated polling, however, it also allows the microcontroller to perform other tasks instead of wasting time. The “delay” method exemplifies a simple, yet ineffective, process to control the state (Low or High) of a digital io (gpio) pin. The “polling” approach shows how to control the state (Low or High) of a gpio, and consequently blinks the LED attached to the pin. Additionally, the “polling” method is much better than utilizing the “delay” approach. The “polling” method requires the system to read the internal clock and can slow down the whole Arduino. The “interrupt” method uses an external clock to time and is more efficient than “polling” and “delay”. The experiment provides students with a better understanding of how to decipher which Arduino command is better suited for certain situations. This lab also gives its students an opportunity to become more familiar with the Arduino language, thus boosting their comprehension skills to replicate desired results. Experiment For this experiment the team assembled an Arduino board and breadboard with the configuration below. Figure 1: Schematic diagram of Arduino setup Figure 2: Arduino Setup For this experiment there are three sets of codes that are provided and need to be modified to be able to perform a delay task, a polling task, and an interrupt task. The provided code for each task can be seen in the results section. The red text in the results sections details the changed sections of code from the originally provided code. The provided code is provided in the appendix section of this lab report. Once the Arduino board is assembled, the Arduino serial monitor can be opened. The values from the Arduino serial monitor can get imported into a .txt file. This .txt file will get imported into a MATLAB file which will convert the serial data into a graph. The MATLAB code can be found in the appendix section of the lab report. The process of re-writing the code, running the serial monitor and importing the data into MATLAB to generate a graph needs to be done for the delay, polling, and interrupt setups. Results Delay: int pinx = 7; int statex = HIGH; int k=1; int j=1; unsigned long tms = 0; // the setup function runs once when you press reset or power the board void setup() { pinMode(pinx, OUTPUT); // initialize digital pin LED_BUILTIN as an output. Serial.begin(9600); } void loop() // the loop function runs over and over again until k=0. { while (k) { tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); delay(1000); // light is on for 1 second tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); statex = !statex; tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); delay(500); //light is off for 0.5 second tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); statex = !statex; j++; // increase j by 1 for each pass if (j >= 11) { // completes the cycle 10 times k=0; } } statex=LOW; digitalWrite(pinx, statex); } Figure 3: Graph of time (s) against state of led (x) for Delay method Polling: // Initialization const int Pinx = 7; int Statex = HIGH; int k=1; unsigned long Tms = 0; // current time in ms unsigned long previousTms = 0; // the previous time when the state of pinx was updated // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin pinx as an output. pinMode(Pinx, OUTPUT); Serial.begin(115200); Serial.println("MEM459_1gpio_polling.ino"); // The MEM459_1gpio_polling.ino is running } void loop() // the loop function runs over and over again until k=0. { while (k) { Tms = millis(); Serial.print(Tms); Serial.print("\t"); // prints a tab if ((Tms - previousTms) >= 1000) { Statex = !Statex; digitalWrite(Pinx, Statex); if (Statex == LOW) { // when LED is on, run for 1 second, else run for 0.5 seconds previousTms += 500;} else { previousTms += 1000; }} else Serial.println(Statex); if (Tms >= 15000) { // a cycle of 10 times is completed in 15000 seconds k=0; } } Statex=LOW; digitalWrite(Pinx, Statex); } Figure 4: Graph of time (s) against state of led (x) for polling method Interrupt: #include <TimerOne.h> int pinx = 7; //int pinx = 13; int j = 1; volatile int statex = HIGH; void setup() { pinMode(pinx, OUTPUT); Timer1.initialize(500000); // in micro seconds Timer1.attachInterrupt(gpioInterrupt); // gpioInterrupt to interrupt every 0.5 second Serial.begin(115200); } // The interrupt will toggle the states of Pins 7 and blink the LED accordingly void gpioInterrupt() { if (j==2) { //Change state from 1 to 0 every 2 cycle of 0.5s statex= LOW; digitalWrite(pinx, statex); j=3; //Increment counter for third 0.5s time cycle } else{ //Change state from 0 to 1 and reset j counter statex = HIGH; digitalWrite(pinx, statex); if (j==3) { j=1; } else j++; } } int k=1; unsigned long tms = 0; void loop() { while(k) { noInterrupts(); tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab Serial.println(statex); interrupts(); if (tms >= 15000) { k=0; } } noInterrupts(); } Figure 5: Graph of time (s) against state of led (x) for interrupt method Discussion In this lab the goal was to rewrite the three given programs, so that the LED will blink in the following pattern: ON for 1 second followed by OFF for 0.5 second and repeat for 10 cycles. The results were then graphed to display the digital output voltage, HIGH and LOW, represented by 1 and 0, respectively. The data collected in this experiment supports the initial objective of making the LED blink in the ON for 1 second and OFF for 0.5 second pattern. It is important to note that both the delay and polling program are inefficient. This is because the delay() and polling() command does not allow the microcontroller perform any other tasks while the command is active. To avoid this issue the interrupt() command is used. The interrupt command allows the microcontroller to perform other tasks while the command is active, making the interrupt script the more efficient of the three programs. This lab also provided C++ and Arduino experience. Conclusion In conclusion, all methods performed in this lab report still produce the same objective of turning the LED on for 1 second and off for 0.5 seconds. The output graphs for all three scenarios show the same output for the three different sets of codes. The differences in the code affect how the Arduino processes the data. The delay method uses the Arduino delay () function. The polling method uses checks for the condition of the light and checks to see if its satisfied. The interrupt function notifies the microcontroller that is ready to process the data. From our data, it was found that even though the delay function was the easiest to program, the interrupt method was the most efficient way of turning the LED on and off. The interrupt function runs no matter what other tasks the board is processing, therefore it does not have to wait for other tasks to finish before doing the action of turning the LED on and off. Appendix Provided Delay Code // Initialization int pinx = 7; // int pinx = 13; int statex = LOW; int k=1; int j=1; unsigned long tms = 0; // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(pinx, OUTPUT); Serial.begin(9600); } // the loop function runs over and over again until k=0. void loop() { while (k) { tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); delay(1000); tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); statex = !statex; tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); delay(1000); tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab digitalWrite(pinx, statex); Serial.println(statex); statex = !statex; j++; // increase j by 1 for each pass if (j >= 6) { k=0; } } statex=LOW; digitalWrite(pinx, statex); } Provided Polling Code // Initialization const int Pinx = 7; //const int Pinx = 13; int Statex = LOW; int k=1; unsigned long Tms = 0; // current time in ms unsigned long previousTms = 0; // the previous time when the state of pinx was updated // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin pinx as an output. pinMode(Pinx, OUTPUT); Serial.begin(115200); Serial.println("MEM459_1gpio_polling.ino"); // The MEM459_1gpio_polling.ino is running } // the loop function runs over and over again until k=0. void loop() { while (k) { Tms = millis(); Serial.print(Tms); Serial.print("\t"); // prints a tab if ((Tms - previousTms) >= 1000) { Statex = !Statex; digitalWrite(Pinx, Statex); previousTms += 1000; } else Serial.println(Statex); if (Tms >= 10000) { k=0; } } Statex=LOW; digitalWrite(Pinx, Statex); } Provided Interrupt Code #include <TimerOne.h> int pinx = 7; volatile int statex = HIGH; bool onn = 1; // add a random variable void setup() { pinMode(pinx, OUTPUT); Timer1.initialize(500000); // in micro seconds, initial status was off and ran for 0.5 seconds Timer1.attachInterrupt(gpioInterrupt); // gpioInterrupt to interrupt every 1 second Serial.begin(115200); } // The interrupt will toggle the states of Pins 7 and blink the LED accordingly void gpioInterrupt(){ if (statex == HIGH){ // if the LED is off, then the state is LOW and the random variable is 1 statex = LOW; onn = 1; digitalWrite(pinx, statex); } else if (statex == LOW & onn){//otherwise if both LOW and 1is met, then turn the LED on onn = 0; } else { // otherwise leave it off statex = HIGH; digitalWrite(pinx, statex); }} int k=1; //int j=1; unsigned long tms = 0; void loop() { while(k) { noInterrupts(); tms = millis(); Serial.print(tms); Serial.print("\t"); // prints a tab Serial.println(statex); //delay(10); // this 10 ms delay is to reduce the number of lines to be printed, it can be removed interrupts(); if (tms >= 15000) { // complete 10 cycles in 15000 seconds k=0; } } noInterrupts(); } Provided MATLAB Code fileID = fopen('polling.txt','r'); formatSpec = '%d %d' sizeA = [2 Inf] A = fscanf(fileID, formatSpec, sizeA) fclose(fileID) n = size(A) t = A(1,1:n(2))/1000; x = A(2,1:n(2)); figure(31) plot(t,x,'b-') title('x(blue) vs. time, sec') grid on grid minor