Introduction
This is a continuation of design activity for the Sequans Monarch Go LTE-M module, for more information on this module please see the Networking with Sequans Monarch Go - Part I from a few weeks ago.
For the Smart Cities and AI demo application shown at CES 2020 (video) we needed a reliable, low-bandwidth data connection for the Ultra96-V2 Single Board Computer (SBC) Product LinkProduct Link that would be used for the object detection and vehicle tracking OpenCV application. Since the vehicle tracking application was already being developed in Python, the PYNQ V2.5 release was already being used as the platform of choice. Luckily, PYNQ is based upon an Ubuntu root file system so I knew there would be a good chance of getting this to work, but there was limited time to do so.
Thanks to some notes that james.flynn passed along to me, I already had a good head start on getting some of the dependencies needed for the Sequans Monarch Go Starter Kit (Avnet link) within the file system squared away, but I hadn't really tested this yet on Ultra96-V2 to know if there were any further roadblocks to success.
Establishing a Baseline
I set out to determine what sort of dependencies were missing from the vanilla PYNQ V2.5 distribution. To do this, I flashed a fresh image of the official Ultra96-V2 PYNQ V2.5 release using the instructions found on the Avnet Github:
https://github.com/Avnet/Ultra96-PYNQ/releases
After connecting up my Ultra96-V2 board to my work PC using a USB-micro cable and powering up with the fresh PYNQ SD card inserted, I used the built-in Jupyter notebooks to configure the WiFi onto my wireless network so that I can do all of the development work from my work PC via SSH:
After that, I connected up the Sequans Monarch Go Starter Kit to the USB Type-A ports of my Ultra96-V2 board:
Looking for those signs of life on the Monarch Go module meant that I needed to connect via SSH (used the user:password xilinx:xilinx then get su privilege) and check the device status using a minicom terminal (which also needed to be installed):
Looks like the LTE-M connection it is still working:
The ppp package and dependencies are also needed, so those are also installed with apt-get package manager:
The next step was to complete the setup outlined in the Adding PPP Infrastructure to Ubuntu section of my https://www.element14.com/community/people/kevinkeryk/blog/2020/02/21/networking-with-sequans-monarch-go-part-i blog article to add a PPP configuration that is compatible with the Sequans Monarch Go module.
- Create a new file named ppp0 file in the /etc/network/interfaces.d/ folder.
- Create a new file named sequans in the /etc/ppp/peers/ folder.
- Create a new file named connect in the /etc/chatscripts/ folder.
- Create a new file named disconnect in the /etc/chatscripts/ folder.
- Edit the /etc/network/interfaces file to add the ppp0 interface instance.
Since PYNQ uses a full Ubuntu-like root filesystem on the EXT4 partition of the SD card, the above changes will be persistent between system boots. Now we can try to start the ppp0 interface up using the ifup command:
According to this message, the ppp_generic driver is not statically built into the kernel, nor is it available as a kernel module that can be dynamically be loaded into the kernel at runtime.
Re-Building PYNQ with PPP Enabled in the Kernel
Here we will look at what is needed to add the ppp_generic driver support to our PYNQ system so that we can bring up the ppp0 interface.
There are some pretty thorough instructions for rebuilding PYNQ on the Avnet github, which appear daunting at first, but you can save a lot of time by reusing the BSPs that are pre-built for the PYNQ V2.5 release so this drastically reduces the steps needed to start the PYNQ build:
https://github.com/Avnet/Ultra96-PYNQ
After investigating this a bit, (I also got some advice from Fred K.) it turns out that there is actually a bsp.cfg file in the Ultra96-PYNQ/Ultra96/petalinux_bsp_v2/meta-user/recipes-kernel/linux/linux-xlnx/ folder which injects kernel config options into the PYNQ build process. So followed the directions in the README.md of the origin/image_v2.5 tag all the way through and just before running the make BOARDDIR=<LOCAL ULTRA96> step. At that point, I simply added the following lines to the end of the bsp.cfg file to enable the needed PPP kernel drivers:
CONFIG_PPP=y # CONFIG_PPP_BSDCOMP is not set # CONFIG_PPP_DEFLATE is not set # CONFIG_PPP_FILTER is not set # CONFIG_PPP_MPPE is not set CONFIG_PPP_MULTILINK=y # CONFIG_PPPOE is not set CONFIG_PPP_ASYNC=y # CONFIG_PPP_SYNC_TTY is not set CONFIG_SLHC=y CONFIG_CRC_CCITT=y
At that point, the PYNQ build can be launched. On my training VM, that gets launched with the following command:
make BOARDDIR=/home/training/Ultra96-PYNQ/
After waiting for quite a while, it turns out that the PYNQ build ultimately fails during the jupyterlab build step.
Looking a little closer, it looks like most of the build steps completed, including the Linux Kernel build step, and even the BOOT.BIN and image.ub files are built and sitting in the PYNQ/sdbuild/output/boot/Ultra96/ folder which are all that are really needed to get the updated kernel anyways.
Next, I shutdown the Ultra96-V2 (properly using the shutdown -h now command or pressing the SW4 power button once).
Now copy these two newly built files over to the FAT32 partition on the SD card, overwriting the existing BOOT.BIN and image.ub files on there.
Trying Again, this Time with PPP Build into the Kernel
At this point, I am going to switch over to the local USB gadget console for my command prompt, since I won't be able to access my Ultra96 across my WiFi network any longer during my tests of the ppp0 interface and we don't want to the two interfaces interfering with each other during the tests. Also note that when the Monarch Go is connected to Ultra96 there can be an added 300 seconds of wait time added to PYNQ boot cycle before you get a login. The only explanation that I can come up with is that the pppd connection scripts are waiting for the module to register with the network before continuing on with the boot sequence.
After powering up the Ultra96 with the updated BOOT.BIN and image.ub files on the PYNQ SD card, let's try to launch the ppp0 interface again, this time as root so that we can see the pppd debug info in the terminal:
The fact that an IP address was returned and DNS servers resolved is a pretty good sign. Used <CTRL-Z> then bg command to put that process into the background so that the networking configuration can be verified with the ifconfig command.
Then send some traffic to a preferred test site to verify satisfactory LTE-M connectivity:
Now that networking capability is demonstrated, the next sections will focus upon getting an application up and running that relies upon the new ppp0 networking interface.
During the Sensing the World Challenge a few months back, I did some work based upon the blog tutorials that @bwilless put together and I even presented a webinar with Hackster.io folks https://www.hackster.io/videos/406 to show how to build a device management dashboard with Microsoft IoTCentral. An entire IoT application could be build up from scratch using Microsoft Azure if your requirements call for it. However, I needed something that would get me results in a short amount of time so that I could demonstrate Ultra96 Smart Cities and AI at CES 2020 pretty and my solution needed to integrate well with PowerBI so that I could show business analytics dashboards for the application later on, so I asked for help from the Avnet IoTConnect team.
Switching to the Avnet IoTConnect Cloud Solution
The folks in the Avnet IoTConnect team pointed me to the easy to use IoTConnect SDK Python client for the device side programming. After configuring a few variables to match the IoTConnect account details I was assigned, I had some test data posting from my Ultra96-V2 board pretty quickly.
First, I downloaded the IoTConnect SDK for Python to my Ultra96 board and extracted the contents of the archive:
unzip iotconnect-sdk-python-v2.4.0.6d927fbb.zip
Then change directories into the unpacked iotconnect-sdk folder and install the iotconnect Python libraries and dependencies:
cd iotconnect-sdk pip3 install iotconnect-sdk-2.0.tar.gz
Not wanting to corrupt the original example code files, I copied the Python 3 example application over as my hello_world.py application for when I start modifying the code to fit my Smart Cities application later on.
cp sample/example_py3.py hello_world.py
The Python example client is launched by specifying the IoTConnect instance that should be connected to remotely. Since I am working directly with the Avnet instance, I specify that at the command prompt. When the client application launches, I enter in my Device ID (device serial number) along with my Company ID which serves as a connection key for my device management space. There are other (arguably more secure) ways to provision devices in IoTConnect using certificates, but this is sufficient for development work right now and I have blotted out the key string for security purposes. Then three temperature data values are manually entered and sent up to IoTConnect: { 55, 66, 77 }
Inside of the IoTConnect management interface, the Device Live Data tabs allow users to quickly verify that my Ultra96Dev1 device is connected and that those test values entered are being registered as incoming device data reports.
I also wanted to make sure that I could visualize the data easily so I setup a custom dashboard and added a Live Chart widget that used the temp input from my Ultra96 as the data source. On the Ultra96 side, I hand entered in the following values for temperature into the IoTConnect example client to make sure they came out on the other side in my dashboard as expected: { 11, 22, 33, 44, 55, 44, 33, 22, 11, 22, 33, 44, 55, 66, 55, 44, 33, 22, 11, 0 }
That graph is auto-scaled nicely as the data comes through and provides a nice visual representation of my (simulated) telemetry data coming from my Ultra96. Of course the Smart Cities and AI application builds upon this foundation quite a bit, but you can see that all the building blocks are in place, along with the Sequans LTE-M connectivity piece, to build up an IoTConnect application with a flexible edge device like Ultra96 rather quickly. Due to a late notice, we needed to start-to-finish put the application together with less than 26 working days so we needed something that we knew had a lot of pieces working already, luckily the Avnet team was able to pull this off in time and it all worked amazingly well thanks to the Sequans Monarch Go LTE-M connectivity!
If you are interested in learning more about implementing applications using Avnet IoTConnect, please let me know in the comments below what you would like to see.
If you need to get some information quickly to evaluate what the benefits and capabilities of IoTConnect are, be sure to check out the Whitepaper from the Avnet website:
https://www.avnet.com/wps/portal/us/solutions/iot/software/iot-platform/
The folks in the Avnet IoT group also gave me access to the new IoT Partner Program which can help launch you extend the scale of your own businesses and accelerate the adoption of IoT with your end customers: www.avnet.com/iotpartnerprogram
Conclusion
As you can see, once the PPP support was added to the Linux Kernel build used by PYNQ, adding the LTE-M connectivity was pretty straightforward. If you are interested in learning more information on how PYNQ can be leveraged to accelerate your applications, there is an excellent training course put together by Fred K. that helped me out a lot. I highly recommend the Turbocharge Python with Ultra96 PYNQ course on Hackster.io to help answer a lot of the questions that might come up regarding PYNQ.
https://www.hackster.io/workshops/ultra96?ref=sequans
I completed the course as soon as it came out and got one of these handy completion certificates:
Let me know if there are other aspects of this Ultra96-V2 plus Monarch Go application that you would like to see explored further.