Getting started

This guide takes you from a blank board to a device that reports to the HiGPS server, and shows where to plug in your own logic.

Firmware layout

Every Findy device runs MicroPython (v1.25) with these files on its filesystem:

boot.py

Runs on every boot. Arms a watchdog, commits a staged over-the-air update if one is pending (see Over-the-air update) and then does:

from last import fw
f = fw()
f.start()

If last fails to import, it falls back to the recovery base image, so a broken upload never bricks the device.

firmware_core.mpy

The framework - everything documented under API Reference. You normally never edit it; deploy it compiled.

last.py (or compiled last.mpy)

Your file. It owns:

  • databaseParams - the parameter registry (see System IDs);

  • datalist - which parameter IDs a report sends;

  • start(self) - the device’s main cycle;

  • measure(self) - what to measure on each wakeup (Logger Pro).

start/measure are plain functions attached to the framework class with fw.start = start and fw.measure = measure.

base.py

Recovery firmware: the OTA commands and a minimal report, nothing else. It only runs when last cannot be imported. Never put application logic in it.

Warning

Anything firmware_core reassigns at runtime (db, Gimei, connectionSuccess, timeOffset, registrationStart) must be accessed from last.py as core.X (via import firmware_core as core) - never through a plain from firmware_core import X, which would capture a stale copy.

Flashing MicroPython

Once per board. Either from Thonny - Tools → Options → Interpreter, link Install or update MicroPython (esptool) at the bottom of the dialog - or from the command line:

esptool.py --chip esp32 erase_flash
esptool.py --chip esp32 write_flash -z 0x1000 ESP32_GENERIC-20250415-v1.25.0.bin

Compiling the framework

The device cannot compile large .py sources in RAM, so firmware_core is always uploaded as bytecode. The mpy-cross version must match the firmware (v1.25 loads bytecode format 6.3):

pip install "mpy-cross>=1.23"
python -m mpy_cross firmware_core.py

This produces firmware_core.mpy next to the source. last.py and base.py are small enough to upload as source.

Uploading with Thonny

Thonny is the simplest way to put files on the board and to watch its serial output at the same time.

  1. Download Thonny from https://thonny.org (Windows, macOS and Linux installers) and install it.

  2. Connect the board over USB and start Thonny. Open Tools → Options → Interpreter, choose MicroPython (ESP32) and select the board’s serial port (or Try to detect port automatically). Click OK - the Shell pane shows the MicroPython prompt >>>.

  3. Show the file panes with View → Files. The upper pane lists your computer, the lower pane (MicroPython device) the board’s flash filesystem.

  4. In the upper pane browse to your firmware folder, select boot.py, firmware_core.mpy, last.py and base.py (Logger Pro also needs ulp_main.bin), right-click and choose Upload to /. Confirm overwriting the existing files.

  5. Press the board’s reset (EN) button or use Run → Stop/Restart backend (Ctrl+F2). The Shell shows the boot log.

Tip

The device deep-sleeps between cycles and Thonny cannot talk to a sleeping board - you will see Device is busy or does not respond. Press the board’s reset button and immediately click the red Stop button (or press Ctrl+C in the Shell) to interrupt boot.py before start() sends the board back to sleep. Once the >>> prompt is back you can upload files and type commands freely; the next reset runs the new firmware.

Note

Thonny uploads files as they are - it does not cross-compile. Compile firmware_core.py on your computer first (previous step) and upload the resulting .mpy. Uploading the .py instead makes the device run out of memory while importing it.

Uploading from the command line

Any MicroPython file tool works; mpremote shown:

mpremote cp boot.py :
mpremote cp firmware_core.mpy :
mpremote cp last.py :
mpremote cp base.py :
mpremote cp ulp_main.bin :        # Logger Pro only

Note

ulp_main.bin is the ULP co-processor program Logger Pro uses for pulse counting. Without it every Logger Pro measure() fails with [Errno 2] ENOENT. The findyIoT module does not use it.

First boot

Reset the board. On first boot the firmware reads the modem IMEI, creates the parameter database with the defaults from databaseParams and sends the defaults report to the server. From then on the device follows the cycle described on its hardware page (findyIoT module, Logger Pro).

Customizing a report

Pick which parameters go to the server by editing datalist in last.py and passing it to report():

datalist = ['421', '443', '230', '231']   # what this device reports

def start(self):
    self.report(False, datalist)          # alarm=False
    t = self.seconds_to_next_wakeup(int(core.db.read('421')))
    self.prepareSleep(t)                  # Logger Pro: prepareSleep(t, True)

fw.start = start

On Logger Pro the pulse/analog extras (437/540, 439/541, 594/520, 570/595) are appended automatically when the matching enable flags (636-639) are set in the database.

Adding your own parameter

Add a row to databaseParams in last.py:

databaseParams["900"] = ["W", 0, 0, 0, "0", "W"]   # my custom setting

then read/write it anywhere with core.db.read('900') / core.db.write('900', value) and include '900' in datalist to report it. The entry format is described in System IDs.

Debugging on the device

Use Thonny’s Shell (or mpremote repl) and interrupt boot.py with Stop / Ctrl+C. Useful moves:

import firmware_core as core     # loads the compiled .mpy - no RAM issues
core.modem.turnOn()
core.modem.us('AT+CREG?')        # raw AT command
core.modem.socketState(0)        # 2 = HiGPS socket connected

core.db.read('421')              # inspect a parameter

# Corrupted database (boot hangs in database.__init__):
import os, machine
os.remove('mydb')
machine.reset()                  # first boot recreates the defaults

Building this documentation

make html          # bootstraps .venv/ and builds on first run
open _build/html/index.html

Or manually, with your own environment:

pip install -r requirements.txt
sphinx-build -b html . _build/html