Longboard Sensor Module
Longboard Sensor Board
Danny Andreev and Sam Ragsdale
- 1 Overview
- 2 Objectives
- 3 Challenges
- 4 Gantt Chart
- 5 Bill of Materials
- 6 UI Decisions
- 7 Communication Protocol Decisions
- 8 Model and Print Mounting Box
- 9 Comfortable with hardware interface on Raspi
- 10 Sensor interface
- 11 Sensor recording and testing
- 12 UI for data
- 13 Results
- 14 Code Overview
- 15 Assembly Tutorial
Our plan is to create a sensor board that can be strapped to a longboard or other vehicle. It will measure locations, altitude, and accelerations, relaying all this information to local storage. The stored information will be processed and mapped to give a ride “diagnostic” or an overview of the position, velocity, and acceleration overplayed onto a map of the path taken during the ride. This information can be stored on a server and accessed off a phone or computer.
A successful project constitutes a 3d printed case which contains a sensor module. This module can be turned on, and will record the trip. Then the module needs to be able to transfer the data to a computer of phone for further processing. The module should also be able to be charger via usb. The GPS and accelerations data wil lthen be overlayed onto a map pulled using the google maps API
Danny will need to become more comfortable with the hardware interface of the Raspi and brush up his python skills. The biggest issue has been in parsing and creating a URL that is used to receive maps from the google maps API. Since google wants to limit the processing required on their end, the way in which URLS are compressed is very tedious and confusing.
Since there will be a simple WIFI connection, and no hardware access, there are few attack vectors present on this device, save for physical destruction. Going underground or loosing gps will eliminate gps accuracy, but location can be extrapolated from the accelerometer for short breaks in gps. Minimal operational cost. No user safety concerns
Bill of Materials
Raspberry Pi Zero W - Amazon
Printer resin (we used the Formlabs Form 2, which runs at $150/1L, our print was about 80mL)
We decided that the user interface would be an apache server running on the Raspi. A python program would begin to loop and take readings when a button is pressed.The data is then stored in a database. Every time the user presses the button again to finish recording, the python program generates a static HTML template that Apache serves to anyone that connects. The user can connect to the Raspi as a WAP or with ethernet given that they have ICS (Internet Connection Sharing) turned on. This is required because the user must be able to communicate with the Raspi while it communicates with the Google Maps API.
Communication Protocol Decisions
This turned out to be quite simple. After lots of tinkering we decided that GPS was too inconsistent over UART so we changed it to serial with a usb cord straight off of the GPS chip. When using serial, we can use the python GPSD library to do all of the communication and calculation required for GPS location and fix. For accelerometer we just had to connect the SPI pins and the power and find the right bit addresses for the power management pins and the accelerometer bus.
Model and Print Mounting Box
This turned out to be quite quick. The CAD model is in the GitHub repo. It features room for a 4 cell 18650 pack, a boost converter (3.7V->5V), a charge circuit, a pi zero, an accelerometer, a GPS unit and a GPS antenna. The bottom half was printed on the Ultimaker in the lab, the top half was printed on a Formlabs Form 2.
Final week update: We ended up needing ethernet due to ICS restrictions on Wustl wifi (see UI decisions). This required us to fit the Raspi3 into the box made for the PiZero. To accomplish this we cut off a few mounting points, drilled some holes, and removed the battery pack from its shell (removing 2 cells in the proccess). After all of this was done, the box was significantly less pretty than planned, but worked.
Comfortable with hardware interface on Raspi
We spent a considerable amount of time learning Raspi. This included learning the file structures, how basic settings worked, and which bash commands were important. The more complicated part was learning how the internet settings worked. We originally planned on running the Raspi as a 2-way WAP (wireless access point) so that we could connect to the Raspi's wifi and see the html it was outputting while the Raspi could also talk to the Google Maps API (again see UI Decisions). We eventually got this working after spending lots of time in settings. Eventually all of this work was made futile by the decision to return to ethernet ICS.
Guides we used: <a>https://cdn-learn.adafruit.com/downloads/pdf/setting-up-a-raspberry-pi-as-a-wifi-access-point.pdf</a> <a>https://stackoverflow.com</a>
Here we implemented a python looping program that simply took readings from the GPS and accelerometer 5 times per second. The GPS has an update rate of about 1 time per second (the extras are filtered out later), and the accelerometer can output as many as 50 times per second. After getting the looping recordings working, they were stored in a SQL database.
To implement this we made helper classes in python for the accelerometer, the gps, and the db. The accelerometer class just hides all of the bus reading information away so that you don't have to worry about it when you want to get data. Calling AccelPoller.getXAccel() will return a float value of the x acceleration (likewise for y,z). The GpsPoller class runs in a new thread and continuously pulls GPS information off the bus so we're constantly getting current data. GPS was the trickier of the two interfaces as it would often loose it's "fix" on the satellites and output either 0, NaN, or slow update rate to once per 15 seconds. Lastly the DbHelper class allows us to write all of the data to each row in the DB by just calling the DbHelper.write() function and passing all the appropriate values. Additionally the DbHelper class has the CSV export to the mathematica/python script that generates the map.
General guide (which we used) for Raspi SQL database with python: http://raspberrywebserver.com/sql-databases/using-mysql-on-a-raspberry-pi.html
Sensor recording and testing
Initially this was a disaster. We found that our GPS unit was terrible near any buildings of reasonable size (3 stories or higher), and seemed to not be able to find a fix in most places on campus. Either our unit was bad or there was some interference (possibly the insane amount of wifi signatures on campus). Anyways, we eventually got it working
UI for data
As discussed before, the UI for data is an Apache server running on the Raspi. After the python loop is done collecting and storing data into the SQL db it calculates the 5 points of top speed from the data and inserts them into an html template using built in python templating. It also inserts a random name for the image into the template. It then runs the GoogleMaps.py script and passes it the name of the image.
The script that generates the map is fairly simple. It was originally written in mathematica, but we learned very late that mathematica can't actually be run on the raspberry pi, so we rewrote it in python. This script reads in the CSV generated by the DbHelper class, then cleans up the points a bit, scales them down to the max number that the google maps API can handle and then requests a static image from google maps. This image is then placed into the Apache Server index with the name passed to it from the data recording script.
After some last minute finagling, everything worked as expected. While our original plan did not happen exactly, we got fairly close to the results we were expecting. While it would've been nice to be able to connect to the module wirelessly, our wifi circumstances did not permit that. Additionally it would've been nice if we could've used our original case design, but the only difference externally between our original case design and the final was the wires hanging out. Most of those wires are convenient to have on the outside anyways, as the user would likely want to mount the antenna on the top, and charge the module from the built in cable.
The main "recording file" is called dboutput.py (https://github.com/samragsdalewustl/LongboardSensors/blob/master/dboutput.py). This file/program includes:
- GPS polling class that allows easy reading from the GPS module
- Acceleration polling class that allows easy reading from the acceleration module
- Database helper class that allows easy writing to a database
- The main recording loop which waits for a button press to start recording, and then waits for another button press to stop recording
- Post processing of the data to generate a csv and an html page (based on a template) which is served to the user via Apache
There is a secondary file called googlemaps.py that takes the csv output of all the data and sends a request to the google maps api for an image of the route. (https://github.com/samragsdalewustl/LongboardSensors/blob/master/googlemaps.py)
- Takes [csvName] argument and generates a map image using the google maps api
- Places this map image into the Apache folder so that it can be served to the user
For the demo we ran the dboutput.py program with a "-o [csvName].csv" tag which runs the program without the recording portion, instead using an old csv to generate the html template and associated google maps route image.
The full tutorial for the assembly of our project as well as all accompanying files can be found on our GitHub page at Full Assembly Instructions