PHYS S-12 : Dan's Documentation

Networking

Day 9: 7/21

Product of Today's Work

Networking will be a big part of my project as I can't have hardwire connections from my laptop to a flying Huzzah. Today I'll try to setup WAN connections with my ESP32 via a firebase server. While a LAN connection is more than enough for me, I feel more comfortable with firebase, which allows me to easily establish a database and website. On the other hand, I would have to code everything on the Arduino IDE for a LAN only connection.

Learning

I started off by following the tutorials. A few problems arose due to mismatched versions of firebase, but I easily fixed them. The real issue was GitHub pages. For some unknown reasons, Github couldn't load my code onto my website.

Github error
Github Error

After a good two hours of struggling, Github finally seemed to fix itself.

Next, I went on Firebase's reference page and the esp32 firebase library to learn how to send and request informations between an esp32, a database, and a website.

The two functions I found particularly useful were set() and update(), which both allow me to make realtime changes to the database. The former completely replaces the preexisting data in a specified node, while the latter only changes one of its values.

Planning

A drew up a plan for the networking side of my final project.

Network Structure
Network Structure

I don't have the IMU and the Altimeter ready at the moment since I need to solder them at my friend's place. So for now, I will just build the database for the thermistor and the servo.

ESP32 Feather

I started off by hooking up the thermistor and the servo, and writing code to transmit their data to the database. I used the following code to build the database structure.


void setup() {
    //…
    //…
    //...
// Set initial data to 0. Not sure if some of these will be in "double", I'll fix this once I start testing the sensors
Firebase.setDouble(firebaseData, root + "Sensors/Temperature/Data", 0);
Firebase.setDouble(firebaseData, root + "Sensors/Humidity/Data", 0);
Firebase.setDouble(firebaseData, root + "Sensors/Altitute/Data", 0);
Firebase.setDouble(firebaseData, root + "Sensors/Velocity/Data", 0);
Firebase.setDouble(firebaseData, root + "Sensors/Orientation/Data", 0);

Firebase.setInt(firebaseData, root + "Motors/Servo/Data", 0); // set initial Servo angle to 0. (from 0 to 180)
//…
    //…
    //...
}
database structure
Database Structure

I added other sensor values that I won't be able to use yet, but it's good to plan ahead and write them in advance.

Then I converted my thermistor code from day 7 into a function and called it within the main loop.

Thermistor Problems

I quickly ran into problems with my analogRead() when I started testing. After fooling around for half an hour, I found this very helpful GitHub thread. Basically, all the ADC#2 pins on the esp32 are being used while Wifi is enabled. This meant that my analogRead pins were limited to A2, A3, A4, A7, and A9.

Anyways, I quickly switched pins, and it worked!

Database Changing According to Thermistor

Unfortunately, this pin reads in data slightly differently from the one I used for the calibration, pin 13. When I turn off the Wifi and use pin 13, it is always accurate. As a result of this difference in reading signals between these pins, my temperature reading is now 4 degrees off.

Servo Motor

I copied and pasted servo code from day 4. This turned out to be smooth sailing, and now the Servo motor responds when I change the database.

You can see my esp32 networking code here.

Web Interface

I finished linking my esp32 to my database, but now I need a webpage to act as an interface for the database.

I want to add a textfield that let's me change the servo's angle, and I want to display the thermistor's temperature as well.

To achieve the first goal, I threw together some javaScript and an html form.


<body>
    ...
    ...
    ...
<form>
    <label for="vol">Servo Angle (between 0 and 180):</label>
    <input type="range" id="angle" name="angle" min="0" max="180" onchange="updateServo()">
</form>
    ...
    ...
    ...
</body>

<script>
    ...
    ...
    ...
function updateServo(){
    var angle = document.getElementById('angle').value * 1.0;
    console.log("Current Angle" + angle);
    ref.update({
        "Motors/Servo/Data": angle
    });
}
    ...
    ...
    ...
</script>

To see this for yourself, go here.

Temperature reading

This required me to read data from the database using javaScript. It wasn't too difficult after I learned about the on() function in the firebase library. It lets me take a DataSnapshot of my database when a sepecified event occurs.


var tempRef = firebase.database().ref("/Sensors/Temperature/Data")
tempRef.on('value', function(tempDataSnapshot) {
    var temp = tempDataSnapshot.val();
    document.getElementById("tempDisplay").innerHTML = temp;
});
Website Changing According to Thermistor

Weather API

I want to display weather data on my website since knowing the weather will make flying the hot air balloon easier.

I did some digging online and found the endpoint for Boston's weather: https://api.weather.gov/stations/KBOS/observations/latest.

I wasn't quite sure how to request data from APIs using javaScript. After learning about various methods from this very helpful article, I landed on Axios. It provided me with a very easy way to pull data from an API, and it also automatically parses the JSON response into a javaScript object.

Here is the function I wrote for the API request.


function getWeather() {
    axios.get('https://api.weather.gov/stations/KBOS/observations/latest')
        .then((response) => {
            document.getElementByID("time").innerHTML = "Time: " +  response.data.properties.timestamp;
            document.getElementByID("temp").innerHTML = "Outside Temperature (Celsius): " +  response.data.properties.temperature.value;
            document.getElementByID("wind").innerHTML = "Wind Direction (degree): " +  response.data.properties.windDirection.value + ", Wind Speed (km/h): " +  response.data.properties.windSpeed.value;;
            document.getElementByID("humid").innerHTML = "Humidity (percent): " +  response.data.properties.relativeHumidity.value;
    });
}

Sometimes the values sent in by the API will be null. I double checked that it wasn't my fault by going to the endpoint myself. Sadly, I can't stop the National Weather Service from changing their database, so I can't do anything about it.

Again, go to the interface to test it out yourself.

Download My JavaScript File
Download My HTML File

Future Plans

Although I now have the underlying logic of the website, I still need to make it a lot more visually appealing. It would be nice to be able to control the Servo motor with a virtual knob. On top of that, I'll need to incorporate more sensors as I start soldering them.