The statemachine is implemented using transition tables to keep track of
which event triggers which transition and what action to take during
that transition.
There are 2 kinds of transition tables used for this.
-**Inner transition table:** Each state has exactly one inner transition table.
Each entry in this table defines the event triggering an outgoing transition,
the target state of the transition, an optional transition guard and an
optional transition action.
-**Outer transition table:** This transition table assigns the definitions of
inner transition tables to their corresponding statemachine states.
The `processEvent()` function checks a new event and finds whether the current
state has a corresponding transition which is not currently blocked by a
transition guard. If a valid transition is found, the optional transition action
is executed and the statemachine transitions into the new state.
### st_Initialization
The default state upon starting the controller. This state will take some reference measurements to determine the relative height of later measurements.
### st_Measuring
The main state of the statemachine. While in this state,
sensor data will be pulled in as provided by the sensor task and stored in
the global `dataStore` object.
Additionally the current height will be calculated and checked against the
maximum measured height to be able to trigger the `ev_Falling` event.
When transitioning to the stopped state, the measured sensor values
will be stored to a file in flash to save them in case of a reboot.
### st_StoppedMeasuring
Idle state. Allows restarting (and thereby overwriting!!!) the measurements.
| None (always returned) | Returns current sensor values. These are not read from the buffer but instead freshly requested from the sensors. | `<url>/api/sensors` |
| `references` | Returns the current references and offsets values used for calibrating the sensor measurements | `<url>/api/sensors?references` |
This endpoint allows chaining of multiple parameters listed in the table. For example, sending a request `<url>/api/sensors?sampleCount&references`
will return the data from both of those parameters and a current sensor value. Adding the `from=` and `to=` parameters to this request,
will return a chunk of measured sensor values instead of a current sensor value.
### `/api/log`
**HTTP GET Requests:**
| Parameters | Expected response | Example request |
| None | Returns last log message | `<url>/api/log` |
| `from=`, `to=` | Returns chunk of log messages. Can be negative or positive indexed, e.g. `from=-1` and `to=-3` will return the 3 newest messages while `from=0` and `to=2` will return the 3 oldest. Requesting more messages than exist will not cause an error and only return the maximum currently available. | `<url>/api/log?from=-1&to=-3` |
### `/api/system`
**HTTP GET Requests:**
| Parameters | Expected response | Example request |
| `h=`, `m=`, `s=` | Sets the hours, minutes and seconds of the controllers internal clock. Parameters must all be used and must be in valid range or HTTP 400 will be returned. |
| `restart=true` | Restarts the controller. |
| `rezero=true` | Recalibrates the reference temperature and pressure for the relative height calculation |
| `start=true` | Triggers start event for state machine. Response of controller depends on current state. Cannot be sent along with `stop=true`. |
| `stop=true` | Triggers stop event for state machine. Response of controller depends on current state. Cannot be sent along with `start=true`. |
### `/api/file`
**HTTP GET Requests:**
| Parameters | Expected response | Example request |
| `filename=` | Tries to open a file with the given filename and returns it on success. Filename must start with a `/` | `<url>/api/file?filename=/style.css` |
| `data` | Returns the file storing the persisted measurement data from the previous measurement run. | `<url>/api/file?data` |
| `references` | Returns the file storing the reference measurements | `<url>/api/file?references` |
## Unit tests
## Known Issues
-**Sensor task dropping samples while old values are written to filesystem:**<br>
The sensor task often drops individual values due to missed deadlines when the
statemachine task is busy writing old sensor values to the filesystem.
This is likely caused by the filesystem operations taking too long.
Theoretically the sensor task should not be impacted by this as it is
explicitly executed on another processor core and has a higher priority than
any other task.
-**wifiScan function prevents webinterface log messages:**<br>
The `wifiScan()` function (defined in `main.cpp`) can prevent the webinterface from displaying log messages when used.
This is caused by the function finding networks with non-ASCII symbols in their name, printing them to the log and the
JSON parser in the webinterface failing to interpret those characters.
-**WiFi SoftAP signal extremely weak:**<br>
The WiFi network hosted by the controller when no other network can be connected to
is extremely short range and often drops the connection to client devices.
-**HMC5883 sensor does not work at all:**<br>
When using the HMC5883 sensor (compass), only `[Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1`
is logged to the UART. This is likely a driver issue. For the time being requests to this sensor have been
completely disabled in the `getSensorValues()` function in `sensors.cpp`.
-**[ 20758][E][vfs_api.cpp:105] open(): /littlefs/persistData.csv does not exist, no permits for creation:**<br>
This error indicates the LittleFS library is trying to open a file that does
not exist. To check whether a file exists with LittleFS, the program has to
try and open it. If the open command fails, the file does not exist.
This error is caused by the webserver periodically checking whether a file
containing data to download is available, to indicate this state to the user.
Once a file has been created due to the program entering the sampling state,
it goes away.
# Future Improvements
## Hardware improvement ideas:
- Onboard SMD LED for simple status indication
- Onboard switch for correctly entering debug mode
## Software improvement ideas:
- Fix the [known issues](#known-issues)
- Expand plotting script to perform post processing of data before plotting,
such as filtering out measurement spikes.
- Expand plotting script to also plot the flight path. This requires measuring
the orientation of the controller during flight though for which the HMC5883
sensor issue has to be resolved.
- Improve webinterface design
# Additional resources/guides
## General information
-[Getting Started with Seeed Studio XIAO ESP32C3](https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/): Getting started guide for MCU. Includes pinout and general information.
-[Seeed Studio XIAO ESP32C3](https://docs.platformio.org/en/latest/boards/espressif32/seeed_xiao_esp32c3.html): PlatformIO docs for using the XIAO ESP32C3.
-[First Steps with a GY-86 10DOF Sensor: MPU6050, HMC5883L and MS5611](https://www.youtube.com/watch?v=hvjNaIlHPV0): Getting started YouTube video.
## Debugging
-[Debug an ESP32-C3 via its JTAG interface](https://tutoduino.fr/en/tutorials/debug-esp32/debug-an-esp32-c3-via-its-jtag-interface/): Setup of JTAG debugging using on-board JTAG interface.
-[JTAG Debugging Tips and Quirks](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/tips-and-quirks.html): Tips and quirks for jtag debugging on an ESP32.
-[Use the PlatformIO Debugger on the ESP32 Using an ESP-prog](https://www.hackster.io/brian-lough/use-the-platformio-debugger-on-the-esp32-using-an-esp-prog-f633b6): Guide to using the esp-prog debug probe in PlatformIO.
-[ESP32 Web Server using Server-Sent Events (Update Sensor Readings Automatically)](https://randomnerdtutorials.com/esp32-web-server-sent-events-sse/): Example on how to automatically update information on a webpage from the controller side.