From 0c0e9067f9d886925be725048c70a810b2f2b8ec Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Thu, 6 Jan 2022 16:12:44 +0100 Subject: [PATCH] First draft of new documentation --- .gitignore | 1 - docs/Makefile | 20 +++ docs/README.md | 1 - docs/make.bat | 35 +++++ docs/source/backlog.rst | 16 +++ docs/source/compiling.rst | 32 +++++ docs/source/conf.py | 55 ++++++++ docs/source/configuration.rst | 244 +++++++++++++++++++++++++++++++++ docs/source/contributing.rst | 5 + docs/source/functionallity.rst | 73 ++++++++++ docs/source/images/config1.png | Bin 0 -> 13295 bytes docs/source/images/config2.png | Bin 0 -> 19034 bytes docs/source/images/config3.png | Bin 0 -> 7854 bytes docs/source/images/config4.png | Bin 0 -> 11264 bytes docs/source/images/device.png | Bin 0 -> 16374 bytes docs/source/index.rst | 76 ++++++++++ docs/source/installation.rst | 32 +++++ 17 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 docs/Makefile delete mode 100644 docs/README.md create mode 100644 docs/make.bat create mode 100644 docs/source/backlog.rst create mode 100644 docs/source/compiling.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/configuration.rst create mode 100644 docs/source/contributing.rst create mode 100644 docs/source/functionallity.rst create mode 100644 docs/source/images/config1.png create mode 100644 docs/source/images/config2.png create mode 100644 docs/source/images/config3.png create mode 100644 docs/source/images/config4.png create mode 100644 docs/source/images/device.png create mode 100644 docs/source/index.rst create mode 100644 docs/source/installation.rst diff --git a/.gitignore b/.gitignore index 4aa2f51..83651f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ .pio/* .vscode/* *.map -docs/* test/*.md test/env/* test/*.py diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 0cfc994..0000000 --- a/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -Starting new docs diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..061f32f --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/backlog.rst b/docs/source/backlog.rst new file mode 100644 index 0000000..f9116f3 --- /dev/null +++ b/docs/source/backlog.rst @@ -0,0 +1,16 @@ +Backlog of changes +###################################### + +Documentation +------------- + +- Add library references to missing libraries from the latest release v0.5. +- Copy images to build folder for documentation +- Create page with list of releases +- Updates over OTA (from PC) + +Code +------------- + +- Support for MQTT +- Support for plato diff --git a/docs/source/compiling.rst b/docs/source/compiling.rst new file mode 100644 index 0000000..b57b217 --- /dev/null +++ b/docs/source/compiling.rst @@ -0,0 +1,32 @@ +Compiling the software +----------------------- + +VSCODE + PlatformIO +============================= +TODO + +Targets +============================= +TODO + +Source structure +============================= +TODO + +Options +============================= +TODO + +# Compiling the software + +I recommend that VSCODE with PlatformIO and Minfy extensions are used. Minify is used to reduce the size of the HTML files which are embedded into the firmware or uploaded to the file system. When using minify on a file, for example index.htm the output will be called index.min.htm. This is the file that will be used when buildning the image. + +By default the html files are embedded but there are options to upload them to the file system to reduce the size of the image if the size becomes to large for OTA. + +You can set the SSID and PWD as presets through platformio.ini by adding the settings to the following definitions: +``` +-D USER_SSID=\""\"" // =\""myssid\"" +-D USER_SSID_PWD=\""\"" // =\""mypwd\"" +``` + +There are more options in teh platform.ini file that enable/disable additional functions for logging level, pushing performance data to InfluxDB and more. If i get the time I will add some documentation around these. \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..cb2c115 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,55 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'GravityMon' +copyright = '2021-2022, Magnus Persson' +author = 'Magnus Persson' + +# The full version, including alpha/beta/rc tags +release = '0.5.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] \ No newline at end of file diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst new file mode 100644 index 0000000..647636a --- /dev/null +++ b/docs/source/configuration.rst @@ -0,0 +1,244 @@ +Configuration +----------------------- +The device can operate in two modes and must be in `configuration mode` in order for the web server to be active. + +One of the following conditions will place the device in `configuration mode`: + +- Gyro has not been calibrated +- Sleep mode has been disabled in the web interface +- Placed in horizontal mode 85-90 degrees +- Charger connected >4.15V + +Main index +========== + +URL: (http://gravmon.local) + +Configuration is accessed by entering the URL for the device, this will be the mDNS name *device.local* or the IP adress. The following chapter assumes the device name is *gravmon*. + +The main page shows the device readings; gravity, angle, temperature and battery charge. If the checkbox is active then the device will never go into sleep mode. This is useful if +you are collecting angle/tilt for calibration. If this is unchecked the device will change mode as explained before. + +.. note:: + + If you are connected to the device via a serial console (speed: 115200) you can see the connection sequence and get the Unique ID and IP adress from there. + + +Device +====== + +URL: (http://gravmon.local/device) + +.. image:: images/device.png + :width: 400 + :alt: Device Settings + + +* **Version:** + + Installed version of the code and html files. + +* **Device name:** + + This is unique name of the device. + +* **Device ID:** + + This is unique identifier for the device (ESP8266 id), this is required when using the API as an API Key to safeguard against faulty requests. + + +Configuration +============= + +URL: (http://gravmon.local/config) + +Device Setting +************** + +.. image:: images/config1.png + :width: 400 + :alt: Device Settings + +* **Device name:** + + This is unique name for the device. It will be used in pushing data as well as mDNS name on the network (.local) + +* **Temperature format:** + + Choose between Celsius and Farenheight + +* **Interval:** + + This defines how long the device should be sleeping between the readings when in `gravity monitoring` mode. You will also see the values in minutes/seconds to easier set the interval. 900s is a recommended interval. + +.. note:: + + The sleep interval can be set between 10 - 3600 seconds (60 minutes). + +* **Calibration values:** + + These are calibration data for the gyro. Place the device flat on a table and press the button to save the default orientation values. Without this calibration we cannot calculate the correct angle/tilt. + +.. note:: + + The device will **not** go into `gravity monitoring` mode unless calibrated + +Push Settings +************* + +.. image:: images/config2.png + :width: 400 + :alt: Push Settings + +* **HTTP URL 1:** + + Endpoint to send data via http. Format used is standard iSpindle format (see format section). + +* **HTTP URL 2:** + + Endpoint to send data via http. Format used is standard iSpindle format (see format section). + +* **Brewfather URL:** + + Endpoint to send data via http to brewfather. Format used is defined by brewfather (see format section). + +* **Influx DB v2 URL:** + + Endpoint to send data via http to InfluxDB. For format (see format section). + +* **Influx DB v2 Organisation:** + + Name of organisation in Influx. + +* **Influx DB v2 Bucket:** + + Identifier for bucket. + +* **Influx DB v2 Token:** + + Token with write access to bucket. + + +Gravity Settings +**************** + +.. image:: images/config3.png + :width: 400 + :alt: Gravity Settings + +* **Gravity formula:** + + Gravity formula is compatible with standard iSpindle formulas so any existing calculation option can be used. Is updated if the calibration function is used. + +* **Temperature correct gravity:** + + Will apply a temperature calibration formula to the gravity as a second step. + + This is the formula used for temperature calibration (temp is in F). Cal = 20C. + +:: + + gravity*((1.00130346-0.000134722124*temp+0.00000204052596*temp^2-0.00000000232820948*temp^3)/(1.00130346-0.000134722124*cal+0.00000204052596*cal^2-0.00000000232820948*cal^3)) + + +Hardware Settings +***************** + +.. image:: images/config4.png + :width: 400 + :alt: Hardware Settings + +* **Voltage factor:** + + Factor used to calcualate the battery voltage. If you get a too low/high voltage you can adjust this value. + +* **Temperature correction:** + + This value will be added to the temperature reading (negative value will reduce temperature reading). + +* **OTA URL:** + + Should point to a URL where the .bin file + version.json file is located. + + For the OTA to work, place the following files (version.json + firmware.bin) at the location that you pointed out in OTA URL. If the version number in the json file is newer than in the + code the update will be done during startup. + + Example; OTA URL (don't forget trailing dash), the name of the file should be firmware.bin + +:: + + http://192.168.1.1/firmware/gravmon/ + + + + Contents version.json + +:: + + { "project":"gravmon", "version":"0.5.0" } + + +Create formula +============================= +todo + +REST API +============================= +todo + +Data Formats +============================= + +iSpindle format +*************** + +This is the format used for standard http posts. + +:: + + { + "name" : "gravmon", // mDNS name + "ID": "2E6753", // esp device id + "token" : "gravmon", + "interval": 900, + "temperature": 20.5, // C or F based on setting, adjusted value. + "temp-units": "C", // C or F based on setting + "gravity": 1.0050, // Raw or temperature corrected gravity (based on setting) + "corr-gravity": 1.0050, // Temperature corrected gravity + "angle": 45.34, + "battery": 3.67, + "rssi": -12, + + // Extension fields + "run-time": 230, // ms, Runtime for this reading, this is an additional field not part of the standard format + } + + +Brewfather format +****************** + +This is the format for Brewfather + + +:: + + { + "name" : "gravmon", // mDNS name + "temp": 20.5, + "temp-unit": "C", + "battery": 3.67, + "gravity": 1.0050, + "gravity_unit": "G", // G = SG, Plato is not yet supported + } + + +Influx DB v2 +************ + +This is the format for InfluxDB v2 + + +:: + + measurement,host=,device=,temp-format=,gravity-format=SG,gravity=1.0004,corr-gravity=1.0004,angle=45.45,temp=20.1,battery=3.96,rssi=-18 + diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst new file mode 100644 index 0000000..798027b --- /dev/null +++ b/docs/source/contributing.rst @@ -0,0 +1,5 @@ +Contributing +----------------------- + +This section is under construction. + diff --git a/docs/source/functionallity.rst b/docs/source/functionallity.rst new file mode 100644 index 0000000..bc54196 --- /dev/null +++ b/docs/source/functionallity.rst @@ -0,0 +1,73 @@ +Functionallity +============== + +The main differences +-------------------- + +* **Operates in two modes `gravity monitoring` and `configuration mode`** + + In gravity monitoring mode it behaves just like the iSpindle, it wakes up at regular intervals, measure angle/tile, temperature, calculates gravity and pushes the data to defined endpoints. + + In configuration mode the device is always active and the webserver is active. Here you can view the angle/tilt values, change configuration options and more. When in this mode you can also interact with the device + via an REST API so data can be pushed to the device via scripts (see API section for more information)- + + *See the configuration section for more information on how to trigger the configuration mode.* + +* **Can send data to multiple endpoints at once** + + The orignial iSpindle can only have one destination, this sofware will push data to all defined endpoints so in theory you can use them all. However this will consume a lot of battery power so use only as many as needed. + + Currently the device supports the following endpoints: http (2 differnt), influxdb2 and Brewfather + + If you want additional targets please raise a feature request in the github repo. + +* **Build in function to create gravity formulas, so no need for using other tools for this part** + + Another big difference is that this software can create the gravity formula in the device, just enter the angle/gravity data that you have collected. You will also see a graph simulating how the formula would work. + +* **Automatic temperature adjustment of gravity reading** + + If you want to correct gravity based on beer temperature you can do this in the formula but here is a nice feature that can correct the gravity as a second step making this independant of the formula. + +.. note:: + + This feature needs more testing to be validated. + +* **OTA support from local webserver** + + When starting up in configuration mode the device will check for a software update from a local webserver. + +* **DS18B20 temperature adjustments** + + You can adjust the temperature reading of the temperature sensor. + +* **Gyro Movement** + + The software will detect if the gyro is moving and if this is the case it will go back to sleep for 60seconds. This way we should avoid faulty measurements. + +Other features +-------------- + +* Support for Celcius and Farenheigt as temperature formats. + +* Support SG (Plato is not yet supported) + +* Gyro data is read 50 times to ensure good accuracy + +Experimental features +--------------------- + +* Use the temperature sensor in the gyro instead of DS18B20 + + This works fine when the device has time to cool down between measurements and it saves a few milliseconds (reduced battery consumption). My testing shows that this is quite accurate. + +.. note:: + + This is not enabled by default. + +* Performance measurements + + I've also create a small library to measure execution code in some areas of the code that i know is time consuming. This way I can find a good balance between performace and quality. + + *See the compile section for more information.* + diff --git a/docs/source/images/config1.png b/docs/source/images/config1.png new file mode 100644 index 0000000000000000000000000000000000000000..f10c5a20ad797a61f8a914693db30da176583113 GIT binary patch literal 13295 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 literal 0 HcmV?d00001 diff --git a/docs/source/images/config4.png b/docs/source/images/config4.png new file mode 100644 index 0000000000000000000000000000000000000000..12a15ea4badf0262b281e5f1fb1d9ffcf18b5cd8 GIT binary patch literal 11264 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 literal 0 HcmV?d00001 diff --git a/docs/source/images/device.png b/docs/source/images/device.png new file mode 100644 index 0000000000000000000000000000000000000000..154cc5638a16da70429940fd20cf1c88acaa7a1c GIT binary patch literal 16374 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%0A-mrjSCMB0BC>{)kMb$@}Yf1m?7e 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 Qu0Di}gra!0s8P`W01n{8Z~y=R literal 0 HcmV?d00001 diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..94281e2 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,76 @@ +.. GravityMon documentation master file, created by + sphinx-quickstart on Wed Jan 5 22:46:42 2022. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to GravityMon's documentation! +###################################### + +GravityMon is a replacement firmare for the iSpindle hardware. It's used to measure gravity in beer and show the progress +of fermentation. + +For more information on this topic and function please visit https://www.ispindel.de. + +I started GravityMon because i like to create software and wanted to do some low level programming. I had done a few +projects based on esp8266 and also started to brew beer so this combination was quite natural. + +The hardware design comes from the fantastic iSpindle project so that is not covered in this documentation. + +My approach to this software is a little different from the approach that the orignial ispindle firmware has. + +.. note:: + + This software is in the early stages even though its more than one year old so if you find issues, please + open a ticket on github. + + I dont take responsibility for any errors that can cause problems with the use. I have tested v0.4 on 5+ brews + over the last 6 months without any issues. + +The main differences: +--------------------- + +* Operates in two modes `gravity monitoring` and `configuration mode` +* Send data to multiple endpoints when pushing data. +* Automatic temperature adjustment of gravity reading +* OTA support from local webserver +* Build in function to create gravity formulas (*New in v0.5*) + +There are also a experimental features such as: + +* Using the temperature sensor in gyro instead of DS18B20 (faster) +* Performance measurements (used to optimise code) + +**For a complete breakdown see the functionallity section.** + +Credits to +---------- +This software uses the following libraries and without these this would have been much more difficult to acheive: + +* https://github.com/jrowberg/i2cdevlib.git +* https://github.com/codeplea/tinyexpr +* https://github.com/graphitemaster/incbin +* https://github.com/khoih-prog/ESP_DoubleResetDetector +* https://github.com/tzapu/WiFiManager +* https://github.com/thijse/Arduino-Log +* https://github.com/bblanchon/ArduinoJson +* https://github.com/PaulStoffregen/OneWire +* https://github.com/milesburton/Arduino-Temperature-Control-Library + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + functionallity + installation + configuration + compiling + contributing + backlog + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/installation.rst b/docs/source/installation.rst new file mode 100644 index 0000000..16ff458 --- /dev/null +++ b/docs/source/installation.rst @@ -0,0 +1,32 @@ +Installation +------------ + +Official esptool +================ + +The prefered option for flashing esp8266 device is via the official esptool. Documentation can be found +here; https://docs.espressif.com/projects/esptool/en/latest/esp32/ + +The basic command for flashing is; + +``esptool.py --port COM4 write_flash 0x1000 firmware.bin`` + +In the /bin directory you will find 3 different firmware builds; + +* firmware.bin - This is the standard release build (prefered version) +* firmware-perf.bin - This version also submits performance data to an influx database with detailed execution times. +* firmware-debug.bin - Development build. Not recommended for normal use. + +In these versions all the html files are embedded in the binaries. The file system is currently only used for storing +the configuration file. + +If the software becomes so large the html files can be moved to the file system, but this is not enabled by default. This makes +installation much easier and ensure that html files and code is in sync. + + +Configuring WIFI +================ + +When the device is flashed it will need to have WIFI configuration in order to work. If this is not configured in the device it will create an wirless access point called `GravMon`. + +Connect to this AP and enter the SSID and password you want to use. If the web page dont open automatically you can enter the following adress in the browser: **http://192.168.4.1**