Deploying TinyML: The Arduino Blink Example

142 阅读5分钟

In this reading, we will deploy the Arduino Blink example to make sure everything is working properly and to give you your first experience deploying code to your Arduino!

The Arduino Blink Example

Preparing for Deployment

  1. Use a USB cable to connect the Arduino Nano 33 BLE Sense to your machine. You should see a green LED power indicator come on when the board first receives power.

  2. Open the Blink.ino sketch, which you can find via the File drop-down menu. Navigate, as follows: File → Examples → 01.Basics → Blink. You’ll notice that Arduino has provided a wealth of examples to choose from should you like to explore the board more on your own outside of the course material. There is great documentation about those examples on the Arduino website.A screenshot of the top left of the Arduino IDE showing the navigation to the blink example which opens up a series of submenus below and then to the right of the choices. The correct path is as follows: File (first option on the top menu) → Examples (about half way down) → 01.Basics (first option) → Blink (third option). You’ll notice that Arduino has provided a wealth of additional examples to choose from should you like to explore the board more on your own outside of the course material. Click the Blink example to open up the correct code in the IDE. Do note that Arduino sometimes changes the ordering of menu items during updates to the IDE so please follow the words and do not be alarmed if they are in slightly different locations.

  3. Use the Tools drop-down menu to select appropriate Port and Board. This is important as it is telling the IDE which board files to use and on which serial connection it should send the code. In some cases, this may happen automatically, but if not, you’ll want to select:

  • Select the Arduino Nano 33 BLE as the board by going to Tools → Board: <Current Board Name> → Arduino Mbed OS Boards (nRF52840) → Arduino Nano 33 BLE. Note that on different operating systems, the exact name of the board may vary but/and, it should include the word Nano at a minimum. If you do not see that as an option, then please go back to Setting up the Software and make sure you have installed the necessary board files. Another screenshot of the IDE showing another set of menus and submenus that need to be traversed to select the correct board. The correct path is: Tools (4th option) → Board: <Current Board Name> (about 2/3rds of the way down)→ Arduino Mbed OS Boards (nRF52840) (3rd option)→ Arduino Nano 33 BLE. (3rd option). Do note that Arduino sometimes changes the ordering of menu items during updates to the IDE so please follow the words and do not be alarmed if they are in slightly different locations.

  • Then, select the USB Port associated with your board. This will appear differently on Windows, macOS, Linux, but will likely indicate ‘Arduino Nano 33 BLE” in parenthesis. You can select this by going to Tools → Port: <Current Port (Board on Port)> → <TBD Based on OS> (Arduino Nano 33 BLE). Where <TBD Based on OS> is most likely to come from the list below where <#> indicates some integer number.

    • Windows → COM<#>
    • macOS → /dev/cu.usbmodem<#>
    • Linux → ttyUSB<#> or ttyACM<#>

Another screenshot of the IDE showing another set of menus and submenus that need to be traversed to select the correct port. The correct path is Tools (4th option) → Port: <Current Port (Board on Port)> (about 3/4 of the way down)→ <TBD Based on OS> (Arduino Nano 33 BLE) (location depends on your machine). Do note that Arduino sometimes changes the ordering of menu items during updates to the IDE so please follow the words and do not be alarmed if they are in slightly different locations.

  1. Finally, use the checkmark button at the top left of the UI to verify that the code within the example sketch is valid. 

A screenshot of the top left of the Arduino IDE showing the verify checkmark right below the top menu items all the way on the left.

Verification will compile the code, so take note of the status and results indicated in the black console at the bottom of the IDE. The level of detail presented here will depend on whether or not you have enabled ‘verbose output during compilation’ in Preferences. You should most likely at the end see a final output indicating how much memory the sketch will take on the Arduino once it is uploaded. Something like: “Sketch uses 86568 bytes (8%) of program storage space. Maximum is 983040 bytes. Global variables use 44696 bytes (17%) of dynamic memory, leaving 217448 bytes for local variables. Maximum is 262144 bytes.” As you can see, this is a very simple example and does not take up much space. While, as you’ll see in a moment, uploading your code will also verify your code automatically, it is often helpful to verify your code first as you can iron out any compilation errors without having any hardware on hand.

Deploying (Uploading) the Sketch

Once we know that the code at hand is valid, we can ‘flash’ it to the MCU:

  1. Use the rightward arrow next to the ‘compile’ checkmark to upload / flash the code. Note that pragmatically, this step will re-compile the sketch before flashing the code, so that in the future if you intend to sequentially compile and flash a program, you need to only press the ‘upload’ arrow.

A screenshot of the top left of the Arduino IDE showing the download right arrow right below the top menu items second from the left and one to the right of the verify checkmark we used in the last step.

As before, take note of the status and results indicated in the black console at the bottom of the IDE. The level of detail presented here will depend on whether or not you have enabled ‘verbose output during compilation’ in Preferences, accessible via the File drop-down menu in the IDE.

You’ll know the upload is complete when you see red text in the console at the bottom of the IDE that shows 100% upload of the code and a statement that says something like “Done in <#.#> seconds.” Again, if this is the first time you are uploading a sketch to an Arduino, the upload may hang for a little while until you get another administrator approval popup and approve it. Don’t worry, this is just a one time thing.

If you receive an error, you will see an orange error bar appear and a red error message in the console (as shown below). Don’t worry -- there are many common reasons this may have occurred. To help you debug, please check out our FAQ appendix with answers to the most common errors!

A screenshot of the Arudino IDE showing the blink sketch code at the top and the terminal output at the bottom. The terminal has an orange highlight that says “An error occuried while uploading the sketch” and then has a series of somewhat cryptic error messages in the text. As noted in the text if you see this orange error bar -- check out FAQ appendix first as we have documented the common errors. https://github.com/tinyMLx/appendix/blob/main/ArduinoFAQ.md

  1. At this point, you’ll want to look to the board itself. The orange LED opposite the green LED power indicator about the USB port should now be blinking!

A GIF of the tinyML kit running the blink sketch. We can see that the orange LED opposite the green LED power indicator about the USB port is blinking.

As a final note, if you’d like to learn more about how the process of flashing code to a microcontroller works, please check out this appendix document.

Understanding the Code in the Blink Example

Now that you have gotten the blink example deployed to your microcontroller, let's explore the code as shown below.

You’ll notice that it consists of two functions: setup, and loop. As we mentioned before, this is the standard setup for an Arduino sketch. This is because when the Arduino turns on it runs the setup() function ONCE to initialize (aka setup) the sketch. Then it runs the loop() function infinitely many times (aka it runs as an infinite loop) to execute the sketch. This works well for most tinyML applications as they are designed to respond to continuous sensor input. You can imagine in the case of Keyword spotting that we need to initialize the neural network and the microphone and then in a loop we want to listen to audio and trigger (or not) depending upon the output of the neural network!

// the setup function runs once when you press reset or power the board

void setup(){

  // initialize digital pin LED_BUILTIN as an output.

  pinMode(LED_BUILTIN, OUTPUT);

}

// the loop function runs over and over again forever

void loop(){

  digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)

  delay(1000);                     // wait for a second

  digitalWrite(LED_BUILTIN, LOW);  // turn the LED off by making the voltage LOW

  delay(1000);                     // wait for a second

}

You’ll also notice that both functions have the void return type as they do not ever return anything but instead have side effects.

For example, in the setup function the LED_BUILTIN (which is a shortcut name for the pin that controls the voltage to the LED) is set to be an output for the duration of the loop. In general, you will need to set all of the pins you use as either inputs or outputs during the setup function. If you wired up the camera yourself, you have already explored a lot of the special names reserved for the pins as shown on the pinout diagram.

In the loop function, you’ll notice that we are alternating between writing a HIGH (aka turning on the LED) and writing a LOW (aka turning off the LED). The delay of 1000 milliseconds (1 second) between each step is crucial as otherwise the light would turn on and off so fast that it would be imperceptible. In fact, if you make the delay too short the light will simply seem to be dim. This is a trick called Pulse Width Modulation that is actually used often in industry to e.g., control motors. If you’d like, feel free to experiment with modifying these delays and redeploying the code to see its effect!