Friday, May 3, 2024

Caravan/motor-home leveler part 2 (MicroPython software)

For an index to all my stories click this text

This is the second story about building a caravan/motorhome leveling aid. This story focusses on the software for the ESP8266. 

Short intro:
I am going to show how to build an electronic device that you can put on your motorhome/caravan's table. And then that device sends it data to an app on your phone. So you can go outside and look at your phone's screen while leveling your caravan/motorhome !!




The above video demonstrates how the device works. It is not connected to an USB powersupply as it is powered by batteries. And the hardware communicates wiressly with the phone.

The previous story showed how to build te hardware and casing for this project. You really need that setup to continue. Here is a link to that story:
http://lucstechblog.blogspot.com/2024/04/caravanmotor-home-leveler-part-1.html

Programming the ESP8266 is done with Thonny as the program is written in MicroPython.

If you want to know more about Thonny and programming in MicroPython please consider buying one of my books listed at the bottom of this page. These books focus on the Raspberry Pi Pico and Pico W (the wifi version) but most of the programs and details also work on the ESP8266 and ESP32 after altering the pin numbers.

Considerations.

In a previous story on this weblog I demonstrated how to get human readable data: plain angles in degrees from an MPU6050. That program is usefull for starting several projects. But that framework displays it's data in Thonny's shell. You can find that story here:
http://lucstechblog.blogspot.com/2024/04/mpu6050-data-in-degrees-instead-of.html

That is of no use for this project. We want to see the angles in a simple manner on our Phone's screen. So the program needs to send it's data over wifi.
The caravan/mobilehome leveling aid is build for campers that are installing their caravan/mobile home on a camping site or in the free nature. The problem that occurs in such situations is that is most of the time no wifi is available.
So the software needs to start as a Access Point (AP) so your phone can contact it.

The other thing to consider is that the information that the ESP8266 is going to send over Wifi must be accessible on your phone. So it must be send in a form that we can pick up by a program for Android.

Both issues are taken care off in the next program.

The MPU6050 Library

Using the MPU6050 in a MicroPython program requires a library.
A MicroPython library is actually just a MicroPython program that simplifies a certain problem. In this case the problem is the communication with the MPU6050.

For your convenience I hereby give the library as discussed before:

'''
Luc Volders library for MPU6050
'''

from machine import Pin, I2C
import time
 
def init_mpu(i2c, address=0x68):
    i2c.writeto_mem(address, 0x6B, b'\x00')
    time.sleep_ms(100)
    i2c.writeto_mem(address, 0x19, b'\x07')
    i2c.writeto_mem(address, 0x1B, b'\x00')
    i2c.writeto_mem(address, 0x1B, b'\x00')
    i2c.writeto_mem(address, 0x1C, b'\x00')
 
def read_data(i2c, addr, address=0x68):
    high = i2c.readfrom_mem(address, addr, 1)[0]
    low = i2c.readfrom_mem(address, addr + 1, 1)[0]
    value = high << 8 | low
    if value > 32768:
        value = value - 65536
    return value
 
def get_data(i2c):
    readx = read_data(i2c, 0x3B) / 16384.0
    ready = read_data(i2c, 0x3B + 2) / 16384.0
    readz = read_data(i2c, 0x3B + 4) / 16384.0
    
    return readx, ready, readz


Copy this program and paste it in a new empty tab in Thonny's editor. Then save it to your ESP8266's memory into the lib folder. Use the name lucsmpulib.py

If you have any problems with this please refer to the story about the MPU6050 which you can read here: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


The MicroPython program

And here is the program that makes the magic happen.

'''
Caravan and Mobile Home leveling aid
http://lucstechblog.blogspot.com/

Version with http server
The x and y values are rounded
ESP is configured as Access Point
'''

from machine import Pin, I2C
import utime
import math
from lucsmpulib import init_mpu, get_data

import socket
import network

ssid = 'Caravan-Leveler'
password = '123456789'

ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid=ssid, password=password)

while ap.active() == False:
  pass

print('Connection successful')
print(ap.ifconfig())

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) # esp8266
init_mpu(i2c)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)


def webpage():
    readx, ready, readz = get_data(i2c)
 
    x = math.atan2(ready, math.sqrt(readx * readx + readz * readz)) * 180 / math.pi
    y = math.atan2(-readx, math.sqrt(ready * ready + readz * readz)) * 180 / math.pi
    z = math.atan2(readz, math.sqrt(readx * readx + ready * ready)) * 180 / math.pi
    
    print("=======================================================")
    
    print(1, x)   # Tilt angles X-axis
    print(2, y)   # Tilt angles Y-axis
    if (x <= 0):
        x = math.floor(x)
    else:
        x = math.ceil(x)
    if (y <= 0):
        y = math.floor(y)
    else:
        y = math.ceil(y)
        
    html = ""
    html = html + '<!DOCTYPE html>'
    html = html + '<html>'
    html = html + 'Hi, this is the Pico'
    html = html + '<br>'
    html = html + '===================='
    html = html + '<br>'
    html = html + 'X = ' + str(x)
    html = html + '<br>'
    html = html + 'Y = ' + str(y)
    html = html + '<br>'
    html = html + '</html>'
    return (html)

while True:
  conn, addr = s.accept()
  print('Got a connection from %s' % str(addr))
  request = conn.recv(1024)
  print('Content = %s' % str(request))
  conn.send('HTTP/1.1 200 OK\n')
  conn.send('Access-Control-Allow-Origin: *\n')
  conn.send('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\n')
  conn.send('Access-Control-Allow-Headers: Content-Type\n')
  conn.send('Content-Type: text/html\n')
  conn.send('\n')
  response = webpage()
  conn.send(response)
  conn.close()


Let's get into some details:

from machine import Pin, I2C
import utime
import math
from lucsmpulib import init_mpu, get_data

import socket
import network


These lines import the necessary libraries. Quite a lot. All the libraries (except lucsmpulib) are included in the standard installation of MicroPython. The only extra library is lucsmpulib which you can install as discussed above.

ssid = 'Caravan-Leveler'
password = '123456789'

ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid=ssid, password=password)

while ap.active() == False:
  pass

print('Connection successful')
print(ap.ifconfig())


This is where the access point is created. The name of the access point (which you can find in the wifi section in your phone) is Caravan-Leveler and it's password is 123456789. You can change the name and password to your own liking but make sure to use something that is easy to remember.

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) # esp8266
init_mpu(i2c)


The i2c connection to the MPU6050 is activated, with the pins where the MPU6050 is connected to the ESP8266.

def webpage():
    readx, ready, readz = get_data(i2c)
 
    x = math.atan2(ready, math.sqrt(readx * readx + readz * readz)) * 180 / math.pi
    y = math.atan2(-readx, math.sqrt(ready * ready + readz * readz)) * 180 / math.pi
    z = math.atan2(readz, math.sqrt(readx * readx + ready * ready)) * 180 / math.pi

A function is created that builds the webpage that is going to be send to your phone or tablet.
The function starts with getting the raw x,y and z data from the MPU6050 and then uses some complicated math to recalculate this into human readable x,y and z degrees. We are not going to use the z value though.

print("=======================================================")
    
    print(1, x)   # Tilt angles X-axis
    print(2, y)   # Tilt angles Y-axis
    if (x <= 0):
        x = math.floor(x)
    else:
        x = math.ceil(x)
    if (y <= 0):
        y = math.floor(y)
    else:
        y = math.ceil(y) 

For our convenience and only for testing purposes the calculated values are printed in Thonny's shell. Please be aware that this only works when the ESP is connected to your computer through USB. In the real world you will have the ESP powered by the batteries and then there is no connection to your computer.

SAFETY WARNING:
Do not connect the ESP8266 to your computer with an USB cable while the batteries are placed. This might damage the ESP8266 or even damage your computer beyond repair. Use the batteries or the USB connection. I accept no responsibility for any damage done by not following these rules.


    html = ""
    html = html + '<!DOCTYPE html>'
    html = html + '<html>'
    html = html + 'Hi, this is the Pico'
    html = html + '<br>'
    html = html + '===================='
    html = html + '<br>'
    html = html + 'X = ' + str(x)
    html = html + '<br>'
    html = html + 'Y = ' + str(y)
    html = html + '<br>'
    html = html + '</html>'
    return (html)

These are the lines that build the actual webpage. Do not alter anything of these lines or the program on your phone (which is to follow) might not work.

while True:
  conn, addr = s.accept()
  print('Got a connection from %s' % str(addr))

The endless loop constan looks if some device is asking for a connection. If that is so a message is printed in Thonny's shell. Again: this is only for debugging purposes and not functioning in a real world environment.

  request = conn.recv(1024)
  print('Content = %s' % str(request))
  conn.send('HTTP/1.1 200 OK\n')

The connection is accepted and a confirmation is send to the phone/tablet that wants access.

  conn.send('Access-Control-Allow-Origin: *\n')
  conn.send('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\n')
  conn.send('Access-Control-Allow-Headers: Content-Type\n')
  conn.send('Content-Type: text/html\n')
  conn.send('\n')

This is very important. These lines are a safety measure from webservices. These lines assure that an external device (your phone/tablet) can get access to the data on this ESP. If these lines are omitted your phone's connection to the ESP will be rejected. This was covered on a previous story here on this weblog which you can find here: http://lucstechblog.blogspot.com/2024/03/solving-cors-error-in-micropython.html

  response = webpage()
  conn.send(response)
  conn.close()

The last step is to send the webpage and close the connection.

That's the complete software for the ESP8266 caravan/mobilehome leveling tool.

First test.

Let's see if this functions like we intended.

First step is to open your wifi settings on your phone.


In the Wifi settings there might be a listing of several access points in the environment. At your actual campsite I doubt there are so many as seen here. Look for the access point with the name Caravan-Leveler. Click on that to activate the connection.

The phone might ask for a password when you make the connection for the first time and then fill in 123456789.
If you have changed the name of the Access point and Password in the above program look for the right name and fill in your chosen password.

Then open a web-browser on your phone.
In the web-browser fill (in the search bar) in the IP address of the Access-Point.
ESP8266's always have 192.168.4.1



And here is the web-page that your browser will show.
The X and Y values will be different of course and depending on the angle your caravan-leveler is at.
As you can see in my test the X value was 32 so the leveler was tilted.

Try and play with this a bit.

Please try and play with this setup a bit. Use a set triangle (geo-driehoek in Dutch) to put your Caravan-Leveler at a certain angle and look what values the webpage shows.

Please note that every time you want a new reading you will have to refresh the webpage.

Next step.

This is fun but not very practical. Next step is a nice looking webpage with a red dot that moves over the screen showing at what angle the caravan-leveler is.
I actually made two versions of the software. One version in Javascript which you can convert into an APP for Android or use in your browser. And the other version is an APP made in APP-Inventor. But that is for next episode.

Till next time.
Have fun

Luc Volders