So next, I want to get into embedded programming in a little bit more detail. So this will provide you with tools that you need to get in and program real programs with Arduino and other platforms. Am going to introduce the concept gradually by going through a set of example scenarios and then talk about how you would program to each of these scenarios. So let me throw a scenario at you. Suppose you have an Arduino, and you have a code running on there but it's not acting right, you're somebody that make a motor turn on but the motor is not turning on, you don't know what's going on. So you're thinking, well, maybe there's a bug in my program. How do you debug it? Well, the Arduino in other sorts of platforms have little LEDs on them. You can use those to debug, you could write something in your code that says, well, if I reach this line turn on an LED. But that's not a very efficient way to debug. The other thing is you may want to log information, may be you're doing performance debugging or you're monitoring the values of sensors or things like that. What if you want to log, reach your data from your Arduino, how do you do this? So this is a scenario to think about. Another scenario I want to mention is what if you want to measure is non-digital values? So we talked about, on the previous slides, how you could do digital to write digital values on or off, but what if you want to write non-digital value, you and motor to speed up and slow down or what if you want to read output from a sensor, which can be anything in a range, how do you do that? Well, I'm going to show you how to solve each of these two cases using a program. So this is a program which does analog I/O, and also there's something called serial programming. So it can be used to send information. So what you can see is, I still have the two function setup in loop and then I call some other things, like I call serial.begin, analogread, and so on. So here's the deal of serial, the analog or the Arduino has the ability to syntax back out the USB, and that's using a serial communications protocol. Your Arduino can access that functionality through the serial class. So instead of I'm doing serial.begin, and that's telling the Arduino libraries that I want to create a serial object and I'm going to call begin and this's going to set a parameter that denotes the speed of the serial communication, how many bits per second or how many baud per second. Then in the loop function, you can see I do serial.print lines. So I'm printing something, or in other words, I'm sending some text data over serial back to the computer. If you run this program in the IDE, you can see the serial output coming back. So if I write an Arduino program that the serial.print line, "Hello" and I run it, hello is going to come back and will be displayed in that little black window or in another window that you can pop up in the IDE. There's another function I have here called analog read, that solves the other use case I mentioned. Analog read allows you to read analog value from one of the analog pins, it's also an analog right if you want to write analog values. So something you should know is if you do serial communications, it can happen over USB, but can also happen over those two pins, the two serial pins I mentioned before. So actually, if you call serial, it will actually happen over both at the same time. So you have to be careful when you hook up your circuits. If you're using serial communication, don't use those two serial pins for anything else because your Arduino will write the data over USB and it will also write the date over to serial pins. So those are the serial communications. I'm not seeing the analog I/O functions here, they're analog read which reads analog data, and it's going to return an integer between zero and 1023. There's also analog write which sends a voltage level to a certain pin which you specify as a value between zero and 255. There's also analog reference, which we talked about a little bit before, and what that does is it sets what 1023 means for analog read. So by default, that's five volts. So if I get 1023 back from analog read, that means I'm reading five volts. What I can do is I can send my own voltage into analog reference, analog reference pin on the Arduino baud and I get one volt, for example, and then that resets analog read. So the maximum value of analog read is equal to the input voltage. So then if I set to one volt then if I read 1023 from analog read, that means I'm reading one volt. So that's useful for situations where you want to read voltage on a finer granularity, you can make that maximum voltage really small and you can read voltages very precisely. So here's another use case; suppose you want to send or read digital data, maybe you have some external component with a micro controller and you want to talk to it like a little LCD display or something like that. Here is another similar situation, maybe you want to measure pulses, maybe you have like an ultrasonic sensor and you want to send a pulse and then wait and measure how long it takes for the pulse to be reflected back, or measure how long a user is holding down a button, or how long a car is blocking a sensor so you can see how fast the car was going. Or maybe you want to generate tones, you have some little speaker and you want to modulate the speaker to send a tone, making an alarm when a burglar steps on alarm floor, on a smart floor or something like that, or make music play when you walk into a room. Well, to deal with these situations, there are a set of functions provided by Arduino which allow for digital streaming. One function that's used is known as tone and what tone does is it generates a continuous pulse wave at a certain frequency. So the tone function takes as input the pin you want to send the tone out, the frequency, how fast you want to modulate the tone, and optionally, it can take duration, how long you want to set a tone for. What this does is it generates a square wave of the specified frequency in hertz with a 50 percent duty cycle. So you can connect it to like a piezo buzzer, or a speaker, or something like that to play tones. Another function, which I imagine there is no tone. So what that does is it stops generation of the square root. So if you turn it on, it generate tone, you can turn that off. Another digital streaming function is known as pulse line. What pulse line does is it measures the duration of the next received pulse. So for example, if a value is high, pulse line waits for the pins transition from low to high, then it starts the timer and then it ends a transition on high to low. So in other words, it measures how long a pulse is. It return zero if no complete pulse was received before a timeout. So this is useful if you want to measure how long something is happening, like you want to measure is how long someone's pushing on a button or how long standing on a pad or something like that. You'll measure how long a circuit is closed or open, use this function for that. So another digital streaming function I want to mention is called shift in. What shift in does is it reads data from a data pin. So in particular, I specify data pin and a clock pin. I'll take these pins and I'll hook them up to the board on two of the pins, and what this function does is it'll read values from the data pin whenever the clock pin goes high. So this can provide a really simple way for different components to talk to each other. There's another function called shift out. Shift out is like the opposite version of this, is used on the sender side, that takes as input AD depend on the clock pin, so it knows what pins to communicate out. Also information about the value you want to send and also the bit order. So I can use these functions together to send data using a really simple encoding scratch strategy. This is similar to the encoding strategy we talked about in an earlier lecture. So that's digital streaming. Here's another use case; suppose you want to design a program that does multiple things at the same time, like maybe you have a drone is doing autopilot, is flying around, but then it also wants to listen to a human user who's pushing buttons and telling it what to do. So it has to listen and also navigate at the same time. Or maybe you have a camera feed, you want to display the camera feed, but you want to pop up a character pad when the user touches the screen. So this happens all the time, what if you want to do multiple things at the same time? Well, you can do that too with Arduino, and this introduces the concept of Interrupts. So an Interrupt is a programming construct that allows you to interrupt the flow of execution of a program due to some external event. So here, I have a program that's running in a loop, just like we usually do. But what the program is going to do is it's going to allow the loop to be interrupted if an external event occurs, and it's going to jump to some other function and execute that function then come back to the loop. In particular, the way I'm going to that is I'm going to tell the Arduino libraries to execute a loop, but at the same time pay attention to a certain pin, pin number 5. When that pin number 5 goes high, stop execution of the loop and jump over to another function. So you can see that happening here in this program. You're to have in setup is, I am setting two pins to be outputs. So there's the ledPin and there's an [inaudible] , and you're saying both has to be output, and then I'm attaching an interrupt, where I'm saying, pin number 5 attach an interrupt to that pin. So in other words, I'm telling the libraries to pay attention to pin number 5. I can't really pass in 5 directly because Arduino internally stores values in pin identifiers in a little bit different way that we read them on the board. So I have to use this other function, digital pin to interrupt to convert pin number 5 to be the Arduino's internal representation. So you should always just do that. Then if you look at loop, the loop function makes ledPin go high and low. So this is the main thing it's doing, is it's making the ledPin go high and low. It's just making led flash over and over. But what I want this program to do is if the user pushes a button five times, then print over a serial button press five times. So I want do both these tasks at the same time. So what I'm going to do that is going to have loop run, but I'm also going to have an alarm function, and you see when I did attachInterrupt I passed in the alarm function. So what that did is when that pin goes high, it's going to call that alarm function, that alarm function, the word alarm is a function pointer. So attachInterrupt knows to call that function pointer when that pin goes high. Now the alarm function you can see is it's going to make the alarm go high and then low, and that's going to increase the number of button presses. So what this thing is going to do is it's going to sit there and raise and lower the LED, when the user pushes a button that's going to make the alarm beep for two seconds and then stop beeping, and that's going to increase the counter, numbButton presses. Meanwhile loop is sitting there and it's looking at numbButtonPresses, it's just sitting there over and over, and if numbButtonPresses is higher than five, it's going to start printing button press five times. So there's a few functions that are used here. There's attachInterrupt which takes in a pin number, a function in a mode. It associates the function pointer to be called on the pin level change. There's different modes you can set. You can set that function to be called when the value is low, when the pin does any change, when the pin raises, when the pin falls. So you can change what events your code will react to. There's also this function digitalPinTodInterrupt, and that converts a pin number to an Interrupt number. There is also a function called noInterrupts. So if you're doing a critical section of code, where you don't want it to be interrupted, maybe you're dealing with something where performance matters a lot or you're doing something critical, some metal medical application where you can't interrupt a beating of a heart or something like that, then you call noInterrupts, and this disables Interrupts for a section of recourse. So you can call noInterrupts, do the critical stuff, and then call Interrupts again, to tell libraries you're willing to be interrupted again. A few things to note, the Arduino platform can only run one interrupt service routine at a time so you can't have interrupts interrupt interrupts. Although some microcontrollers do allow that. Another thing to note is that when you declare sheared variables, you have to use the volatile key word. So if you don't know C++ or if you haven't seen volatile before, what that means is you have to tell the compiler that, hey this is a variable which can be updated even though you don't see it in the program flow, because compilers often aren't very aware of interrupts and how they can happen. So compiler looking at this code might say, okay there's this loop function, and there's a function called numbButtonPresses, but I don't see any way that numbButtonPresses can be anything higher than zeros, initialized zero. There's nothing in that increments it. Because compilers often aren't smart enough to see that alarm function down there and know that can be called. So what volatile does is it says, okay this is an integer, and compiler even though you don't see a way to do it, don't optimize it out, include it in the binary because it can be incremented. So it prevents certain compiler optimizations that can remove pieces of your code which shouldn't be removed. So here's another situation that comes up a lot. What if something goes wrong, what if you build something and you deploy it and it's out there and then it crashes or it hangs, the program stops running, you've got some bug in it. What do you do? Well for a lot of programs you typically write, it might not matter you just go in and debug it. But when you deploy real stuff and it's running out there sitting on a drone that's flying in the air, you've got your plant watering system, when this stuff crashes, your plants can die and your drone can crash and medical applications, this stuff can be really bad. There's situations where locking up in feeling is not a good option. So it might be nice if you could design platforms to be self recovering in some way, when you're in situations where you can't get out there to help them. So to deal with this, there's this neat invention people came up with called the Watchdog Timer. In the watchdog timer, it's like a dead man's switch. What it is is, you've got your program and you're running it, and your program is expected to call a function every so often, like within every one second, and if it doesn't, you're run time is going to assume that your program hung and it's going to reset it, it's just going to restart it. So it's like a dead man switch, there's a counter that counts up continuously in the hardware overtime, and if that counter's not reset within a certain timeout, your board has rebooted. There's a few functions that are used here. You can see on the right here, I have a program and what it does is it calls setup, and the setup function enables a watchdog timer. In the Cassin value WTO two seconds. I'm telling it, okay, I have to enable this timer and I have to update it every two seconds, otherwise you can assume my program is dead. That's call waking up your dog. You're going to take your dog and wake it up. Then there's a loop function, and what the loop function does is it's going to process the data or do whatever it's supposed to do, and then it's going to reset the timer. It's going to pet the dog. You have to keep petting the dog or the dog is going to get angry and start barking inside your port. So this works fine if you know that process data is going to finish within two seconds. Processing has something that is just fronts through some values, it's going to finish in 10 microseconds or whatever, so that's pretty safe. So there's really two functions. There's an enable, where you can enable the timer, and then you can reset it periodically. There's other levels you can implement. The ATmega328 supports timers: 15 milliseconds, 30 milliseconds, 60 milliseconds, all the way up to eight seconds, and so you can choose based on what you know about your program. You might be thinking, "Hey, I took theory of computation, and it's impossible to tell if a program's crashed or not," and that's true in general, in theory. But in practice, you often know a lot about your program, and you might know with high certainty this function that's going to be called, it's going to happen within a second, and that's the observation that watchdog timers are really useful. They don't always work, but there's a lot of contexts where they're really useful and they can allow your program to keep executing in the field if you need to. So another scenario that you sometimes have to deal with is loss of power. You've got your device, it's out there, it's floating in the Arctic Ocean, it's running out of battery, what do you do? There's a lot of situations where you design something that needs to operate for long periods of time on low battery, and you would be reaching into your battery life, you may be in situations where you can't replace the battery because it's deployed in the desert somewhere and a grain facility. You may not have enough battery. You may not even have a battery. You're doing energy harvesting and sources are drying up, running at a solar power, what do you do? Well, something you can do if you have to do it is you can make your device go to sleep. Devices often have the ability to make certain parts of them go to sleep. Because if you think about it, you've got a board sitting there. Maybe it's not using the Wi-Fi, maybe you start using the voltage regulator right now. If you can make certain parts of it go to sleep, you can save electricity for those parts, and then you could turn them on later when you actually need them. So the Arduino and the ATmega328 support different sleep modes, and I'm showing them here on the right-hand side. There's power down where it saves the most power. There's also modes where you can turn off just the ADT converter or just the voltage regulator and so on. So you may certain parts of a go to asleep, and then you can wake them up by timer or get manually or when there's a pin change, you can make parts of it wake up. There's functions to enable and disable sleep. So what you can do, when you want it to go to sleep, you use sleep enable, and that makes it so you can go to sleep and then you can do sleep mode actually go to sleep. So it's like if you have a gun, guns have safety, so you can't just pull the trigger. Going to sleep is dangerous because you got your device, if you make part of the go to sleep that you need, that can be bad because you might miss sensor readings or your device might crash or do bad things. So there's a safety and the safety of sleep enable. You have to call seep enable first and then do sleep mode. So you can see an example here where I have a loop. What the loop does is it delays a little bit, and then it prints going to sleep, and it delays a little bit more just to give time for that serial data to propagate out. You don't want to go to sleep before your serial gets out, and then you go to sleep. You set the SLEEP_MODE. Here we're doing the most aggressive sleep mode, which is PWR_DOWN. Aid you sleep enable to turn off the safety, and then you attach an interrupt. What this interrupt is going to do is it's going to turn the board back on when a line goes high. Then you do SLEEP_MODE which turns the device to sleep. When it wakes up, then program flow is going to continue executing. It's going do sleep_disable and then detached interrupt. When that line goes high, it's going to call the wokeUp function up there. What wokeUp is going to do is it's going to call Serial.println that say, "We woke up." Then you could do whatever you want there. You can read sensors or whatever and then you can go back to sleep if you want. So this is useful for situations for example, if you have a device that's sitting there, collecting sensor readings, if there's something since the line goes high you wake up, read data, maybe write it to your SD card and then go back to sleep, and so you only need to use battery when you're actually receiving data. So you can do things like you can replace the delay calls and do other things when you're not doing anything important. Some of these power mode is going to actually saved that much power in Arduino's because you're using a voltage regulator, and the voltage regulator uses a lot of power on Arduino's. However, this concept is useful for other platforms, and there's also ways if you really care, you can hack out that voltage regulator on the Arduino. Some other ways to save power, you can avoid the linear regulator, you can lower voltage. So if you have a board that's using five volts, you can design to use 3.3 volts instead. You can reduce clock speed of your microcontroller. So you can also design for low-power as well. Another used case I want to mention is if you want to store information. So you receiving data, you want to log it and store it, you could send it to serial and log it on your computer. But what if you don't have a computer attached? You can send it to Wi-Fi. But what if you're not able to send, get someone else's sending right now? Another thing you might want to use retain your state across power outages. You might be recording a lot of data and then your power fails, you might want to keep that data and use it later, in-store configurations and user preferences. So the Arduino platform can do file IO. File IO is very similar to C++ file IO if you've seen that before or Java. You have a class and you can do open and close and all those sorts of things, you can do read and all that. So here are some examples of how you write to EEPROM and how you write to the SD card. So with EEPROM, it's more like a memory where you write to addresses. So you can see on the right, the way you do that with EEPROM is you specify an address you want to write to, and then write a value. So this is a program which reads a value, writes at the EEPROM at certain address, and then increments the address and writes the next value there and so on. On the right, we have an example of how to write to an SD card, where you have a file system. So what you do is you get an SD object, which is how you write to SD cards, and you initialize it with SD.begin, and then you do SD.open. You can open a file with a file name in there, and then you can write values to it. So here, we create a new SD called datafile and then we can write to the datafile doing datafile.println. So it's very similar to POSIX style open, close, println, and all these functions are supported. So I've shown you a lot of things here. I've shown you how to create devices, how to program them. Next, what we're going to do is we're going to go up the stack. We 're going to start getting into protocols and software and data analysis and the other sorts of things using IoT. So you know now how to build the device itself, and we're going to get into some of the more advanced algorithms and technologies that are built on top.