Firmware Launchpad
Launchpad is our effort to help new members get acclimated with some of the skills they may use on our team. It is absolutely not going to teach everything, but its meant to be a small project to pick up as your first ticket on the team that will incorporate the general kind of coding that you may become familiar with.
Full disclosure: the boards + environment used here are ESP32s - we do not actually use them in NER (instead, currently all of our boards are STM32s). The tooling here is quite simple, but don't be surprised if its a bit different than what you use after completing this. Similarly, ESPs are known for their Bluetooth capabilities - and while our car doesn't use Bluetooth, I thought it would be really cool to take advantage of it here. Again, this is just supposed to be a fun intro into embedded development that is a little bit more advanced than what you may see in a class like cornerstone- nothing more. Have fun and please ask questions as they come up! We will have dedicated time in the first several meetings of the semester to talk about this, but please slack us anytime throughout the week as needed!
1. Setting Up
Hopefully you’ve done the full setup described throughout this doc. If you have, the launchpad subsystem is embedded into your venv already! in your terminal (with the venv active), simply run
launchpad install
You should be greeted with a bunch of installs- and this sets up the ESP32 specific tooling. In order for these changes to be recognized, you should deactivate and then reactivate the ner-venv. Also note, you may see some things “error”, but the install continues. This is generally okay, so feel free to ignore.
Only if on Windows:
Unfortunately, Windows users need to manually install a driver to allow UART to USB comms. Go to this pageCP210x USB to UART Bridge VCP Drivers - Silicon Labs
Donwload the Windows Universal Driver
Unzip the file
Right click on the unzipped file called “silabser.inf”, and click install
Follow the prompts
Only if on Linux:
Linux needs to give permissions to access the USB device. run this command:
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules
Unplug the device, and plug it back in, and you should be all set
2. Clone the github classroom repo.
Follow the link posted here:
https://classroom.github.com/a/_1lecy_U
main.c - the application main code, with task/thread definitions and functional logic.
api.h/.c - These are the function calls you may need to use. While you should be able to complete the task using just this and other simple calls, you do not necessarily need to if you do not want. The purpose of this was to hide some of the messy syntax from you, and instead provide more clear APIs. Again, you do not need to edit this, but I encourage you to see what these do, since you' have to make calls to these functions. On top of the APIs defined there, I’ve included a comment in api.h with some more function signatures that you have access to that I found helpful to complete the task. Note: I did not create APis to hide FreeRTOS stuff, since you should become familiar with them !
When testing with the magnet, do not let the metal magnet touch the board. It is a big piece of metal, and can short components together. It doesn't need to be too close to work!
That’s all for now!
2. Create the app
Your goal is to create a simple application that utilizes a few of the tools embedded into the ESP chip:
Bluetooth
Hall Effect Sensor (magnetic field strength)
This application, running freeRTOS, should:
continuously read magnetic field data
blink an LED based on the strength of that field (stronger field == faster blinking)
Utilize an interrupt (ISR) to trigger the LED blink
Broadcast the raw data over Bluetooth
Broadcast this data over serial monitor
To complete this, find the comments labeled
// TODO -
This indicates some functionality that you must implement - and usually follows up with an explanation of what needs to be done. This should be doable with only the API functions in api.h/.c, the other function signatures shown in a comment within api.h, and some simple C logical code. You do not need to edit anything that isn't given a “TODO” comment
That's all! You are not expected to necessarily know anything about freeRTOS, interrupts, or any of these skills; Just because I haven’t in detail explained these things in this doc does not mean you are expected to understand it. I literally am keeping these instructions somewhat vague intentionally to ensure I don't sway you towards doing this a certain way, because there are multiple ways to do it. Ask questions, do some individual investigation, or use whatever tools you want to help. freeRTOS and interrupts are used extensively in our vehicle apps, so getting some experience with them here will help out.
3. Testing
You’ll need a micro-USB cable to connect your laptop to the device. If you don’t have one around, stop by the Richards Makerspace and test it with one of ours down there.
Once your code is ready to build, and assuming you’ve run “launchpad install” in the venv, you can do so with the following command:
lpbuild
To upload the built code to the board, run
To view logs
To view the Bluetooth data, download the NRF connect app on your phone. In the scanner, you should see an ESP device. Connect to that and you should be able to see the message!
Similarly you
4. Tips/keep in mind
The value returned from the sensor is a raw ADC value. This means it is a unitless value, understood as a strength “percentage”. To understand this value, the resolution of the ADC needs to be known. For this device, the default resolution is 12 bits. This value is simply the number of bits used to depict this percentage - the more bits, the higher the precision you are able to achieve.
Ex. for a ADC with 12 bit resolution:
The highest number that can be expressed with 12 bits is 2^12 = 4096. A raw ADC value of 2048, for instance, means 50% “strength”. Really, its just looking at this value as a percentage of the resolution.
The hall sensor normally would need to be calibrated to account for the ambient magnetic field in your environment. Doing so is out of scope of this task, so don’t worry about it too much, just try to set it up so that the light does not blink much at the reading level it gets without the magnet nearby. Depending on your environment, this might be at different reading values. All apps have the same ADC resolution, but you may read stronger or weaker fields, which is okay. Regardless, the strength should increase as the magnet gets closer. To test this, you may want to simply guess and check - you should incorporate some sort of “offset” ADC value, where the LED doesnt/barely blinks if the reading is as low as you record when no magnet is nearby. Also, it doesn't need to be extremely precise. Maybe you only have 2 or 3 blink speeds for strength ranges - this doesn't need to be a continuous and fine grained speed increase for every tiny change in field strength
When Using multiple threads like in an RTOS application, data atomicity is important. If a piece of data is accessed from multiple threads, it is important to use a locking mechanism, like a mutex or semaphore, to make sure that sharing this data is done safely
Again, please ask questions! Bay times and meetings will dedicate time for launchpad discussions, if you are new to embedded, this stuff may seem really confusing and we are here to help make it less daunting.
Bonus: As mentioned, the LED that is being blinked in this program is not on the board, its connected to a floating gpio pin. While I may get some setups myself for you to use, if you want to do a little breadboarding, feel free to setup your own breadboard (we have some in the bay) and connect an external LED (we will have some in the bay). You may need to do some EE math to figure out what resistor to use so that you don’t explode the LED :)