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 :doc:`ota-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 :doc:`/datatypes/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. #. Download Thonny from https://thonny.org (Windows, macOS and Linux installers) and install it. #. 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 ``>>>``. #. Show the file panes with *View → Files*. The upper pane lists your computer, the lower pane (*MicroPython device*) the board's flash filesystem. #. 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. #. 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 (:doc:`/hardware/findyiot`, :doc:`/hardware/logger-pro`). Customizing a report -------------------- Pick which parameters go to the server by editing ``datalist`` in ``last.py`` and passing it to ``report()``: .. code-block:: python 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``: .. code-block:: python 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 :doc:`/datatypes/system-ids`. Debugging on the device ----------------------- Use Thonny's Shell (or ``mpremote repl``) and interrupt ``boot.py`` with Stop / Ctrl+C. Useful moves: .. code-block:: python 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 --------------------------- .. code-block:: bash make html # bootstraps .venv/ and builds on first run open _build/html/index.html Or manually, with your own environment: .. code-block:: bash pip install -r requirements.txt sphinx-build -b html . _build/html