Skip to content

Commit

Permalink
Push avenet42
Browse files Browse the repository at this point in the history
  • Loading branch information
aveao committed Jul 3, 2023
0 parents commit 28a087a
Show file tree
Hide file tree
Showing 30 changed files with 3,865 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
config.json
font*.xcf
Binary file added .repo_assets/avenet42.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 90 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
### warning

Be warned! This design is currently still evolving, and parts may be swapped around or added in the future.

### parts

dev boards:

- esp32 dev board, any will do, but ideally go for one with 38 pins. [berrybase link](https://www.berrybase.de/esp32-nodemcu-development-board).
- scd41 (co2 sensor). personally I've used the seeed studios breakout board. [berrybase link](https://www.berrybase.de/seeed-grove-co2-temperature-feuchtigkeits-sensor-scd41), [seeedstudio link](https://www.seeedstudio.com/Grove-CO2-Temperature-Humidity-Sensor-SCD41-p-5025.html). [adafruit's one will do too](https://www.adafruit.com/product/5190).
- Optional: bmp180 (pressure sensor). I don't like this sensor and I'll swap it later. If this is not found on the i2c chain it will automatically be disabled. [berrybase link](https://www.berrybase.de/bmp180-temperatur/luftdrucksensor-shield-fuer-d1-mini), [direnc.net link](https://www.direnc.net/bmp180-dijital-barometrik-sensor)
- Optional: waveshare 2.13in 250x122 e-ink display, not the raw display, but one with a built-in driver board. I've personally used the raspberry pi hat. Screen can be disabled in config. [waveshare link](https://www.waveshare.com/product/2.13inch-e-paper-hat.htm)

also, of course:

- 10k resistors. You'll use up to half a dozen of them. Get a size you're comfortable soldering.
- Optional, but useful: Capacitors, 10uF, ceramic, etc. I used one that was `10uF 25VDC 10% X7R 1210 SMD`.
- Optional: If you want a switch for bluetooth or wifi, get small latching switches (SPDT).

### example wiring

note: not all GPIOs are usable on an esp32, as some are https://randomnerdtutorials.com/esp32-pinout-reference-gpios/

G27 -> SCD41 SCL (yellow)
G26 -> SCD41 SDA (white)
SCD41 SCL -> BMP180 SCL (yellow)
SCD41 SDA -> BMP180 SDA (white)
G33 -> wifi switch middle (brown)
G25 -> bt switch middle (blue)

G23 -> screen DIN/MOSI (yellow)
G18 -> screen CLK/SCK (blue)
G19 -> screen CS (gray)
G21 -> screen DC (brown)
G22 -> screen BUSY (yellow)
G15 -> nothing (needed for nonexistent screen miso)

GND -> SCD41 GND (black)
GND -> wifi switch bottom (10k + black)
GND -> bt switch bottom (black)
GND -> screen GND (black)

3V3 -> SCD41 PWR (red)
3V3 -> wifi switch top (10k + red)
3V3 -> bt switch top (10k)
3V3 -> screen VCC (red)

Nothing -> screen RST

### installing stuff

- install latest stable micropython on your esp32
- install the libraries in [esp32/requirements.txt](esp32/requirements.txt), [see this link](https://docs.micropython.org/en/latest/reference/packages.html).
- manually apply the following changes to the ble library you've installed https://github.com/micropython/micropython-lib/pull/629 (if it is not yet merged).
- copy `esp32/config.json.template` to `esp32/config.json` and configure it to your liking.
- copy the files across:

```bash
pip3 install adafruit-ampy
cd esp32
ampy -p /dev/ttyUSB0 put main.py
ampy -p /dev/ttyUSB0 put config.json
ampy -p /dev/ttyUSB0 put helpers.py
ampy -p /dev/ttyUSB0 put influx_helpers.py
ampy -p /dev/ttyUSB0 put bmp180.py
ampy -p /dev/ttyUSB0 put scd41.py
ampy -p /dev/ttyUSB0 put comic_code_24.py
ampy -p /dev/ttyUSB0 put comic_code_24.bin
ampy -p /dev/ttyUSB0 put comic_code_48.py
ampy -p /dev/ttyUSB0 put comic_code_48.bin
ampy -p /dev/ttyUSB0 put waveshare213.py
ampy -p /dev/ttyUSB0 put waveshare_lut_full_update.bin
ampy -p /dev/ttyUSB0 mkdir lib
ampy -p /dev/ttyUSB0 mkdir logs
```

### fetching logs (if local logging is enabled)

```bash
ampy -p /dev/ttyUSB0 get logs/rh.log rh.log
ampy -p /dev/ttyUSB0 get logs/c.log c.log
ampy -p /dev/ttyUSB0 get logs/pressure.log pressure.log
ampy -p /dev/ttyUSB0 get logs/co2.log co2.log
ampy -p /dev/ttyUSB0 rm logs/rh.log
ampy -p /dev/ttyUSB0 rm logs/c.log
ampy -p /dev/ttyUSB0 rm logs/pressure.log
ampy -p /dev/ttyUSB0 rm logs/co2.log
```

can be viewed with `tools/logparser.py`: `python3 logparser.py /tmp/co2.log`
47 changes: 47 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
The MIT License (MIT)

Copyright (c) 2023 Ave Özkal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

This project includes partial code from https://github.com/micropython-IMU/micropython-bmp180, which also has the MIT license:

The MIT License (MIT)

Copyright (c) 2014 Sebastian Plamauer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## avenet42

An attempt to make a full-featured (similar to aranet4) while also being a bit more budget friendly.

![a picture of avenet42](.repo_assets/avenet42.jpg)

### features

- wifi: can upload data points to influxdb over wifi.
- bluetooth: can fetch data over bluetooth. a simple web ui using webbluetooth is available, see `web/` for more info.
- screen: supports grayscale waveshare e-ink displays (tested with 1.33in v2).
- local logging: optionally, the sensor data can be stored on flash to be fetched later, for example to save pressure data during a flight.

### building your own

See [BUILDING.md](BUILDING.md) for wiring and flashing instructions. I'll design a PCB eventually.

### general TODOs (will be moved to issues eventually)

- helper_convertfont: make an adj tool to generate text images from font files
- hw: battery
- hw: case
- web: service workers for UI to work offline
- web: better UI
- web: cleaner code
- web: account for losing focus
- web: fix disconnect button
- web: complex comms to read config
- micropython: complex comms to read config
103 changes: 103 additions & 0 deletions esp32/bmp180.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from helpers import _write_to_i2c
from machine import I2C
import struct


# based on https://github.com/adafruit/Adafruit_BMP085_Unified/blob/master/Adafruit_BMP085_U.cpp
# and https://github.com/micropython-IMU/micropython-bmp180
class BMP180:
i2c_address = 0x77

def __init__(self, i2c_instance: I2C):
self.i2c_instance = i2c_instance
self.calibration = {}

async def init(self):
registers = {
"AC1": [0xAA, ">h"],
"AC2": [0xAC, ">h"],
"AC3": [0xAE, ">h"],
"AC4": [0xB0, ">H"],
"AC5": [0xB2, ">H"],
"AC6": [0xB4, ">H"],
"VB1": [0xB6, ">h"],
"VB2": [0xB8, ">h"],
"MB": [0xBA, ">h"],
"MC": [0xBC, ">h"],
"MD": [0xBE, ">h"],
}

for register_name, register_data in registers.items():
i2c_response = await _write_to_i2c(
self.i2c_instance,
bytes([register_data[0]]),
i2c_device=self.i2c_address,
read_bytes=2,
)
self.calibration[register_name] = struct.unpack(
register_data[1], i2c_response
)[0]

def _compute_b5(self, temp_raw):
X1 = (temp_raw - self.calibration["AC6"]) * (self.calibration["AC5"]) >> 15
X2 = (self.calibration["MC"] << 11) / (X1 + self.calibration["MD"])
return X1 + X2

async def read_temperature(self) -> int:
await _write_to_i2c(
self.i2c_instance,
b"\xF4\x2E",
i2c_device=self.i2c_address,
command_wait_s=0.005,
)
temp_raw = await _write_to_i2c(
self.i2c_instance, b"\xF6", i2c_device=self.i2c_address, read_bytes=2
)
temp_raw = struct.unpack(">h", temp_raw)[0]

B5 = self._compute_b5(temp_raw)
t = int(B5 + 8) >> 4
t /= 10

return t

async def read_pressure(self, oversample_mode: int = 3) -> int:
temp = await self.read_temperature()
await _write_to_i2c(
self.i2c_instance,
bytes([0xF4, 0x34 + (0x40 * oversample_mode)]),
i2c_device=self.i2c_address,
command_wait_s=(0.007 * oversample_mode),
)
pressure_raw = await _write_to_i2c(
self.i2c_instance, b"\xF6", i2c_device=self.i2c_address, read_bytes=3
)
# TODO: improve this
B5_raw = (int(temp * 10) << 4) - 8
UP = ((pressure_raw[0] << 16) + (pressure_raw[1] << 8) + pressure_raw[2]) >> (
8 - oversample_mode
)
B6 = B5_raw - 4000
X1 = (self.calibration["VB2"] * (B6**2 / 2**12)) / 2**11
X2 = self.calibration["AC2"] * B6 / 2**11
X3 = X1 + X2
B3 = ((int((self.calibration["AC1"] * 4 + X3)) << oversample_mode) + 2) / 4
X1 = self.calibration["AC3"] * B6 / 2**13
X2 = (self.calibration["VB1"] * (B6**2 / 2**12)) / 2**16
X3 = ((X1 + X2) + 2) / 2**2
B4 = abs(self.calibration["AC4"]) * (X3 + 32768) / 2**15
B7 = (abs(UP) - B3) * (50000 >> oversample_mode)
if B7 < 0x80000000:
pascal = (B7 * 2) / B4
else:
pascal = (B7 / B4) * 2
X1 = (pascal / 2**8) ** 2
X1 = (X1 * 3038) / 2**16
X2 = (-7357 * pascal) / 2**16
return pascal + (X1 + X2 + 3791) / 2**4

def pressure_to_altitude(
self, atmospheric_mbar: float, sea_level_mbar: float = 1013.25
):
# https://github.com/adafruit/Adafruit_BMP085_Unified/blob/master/Adafruit_BMP085_U.cpp#L361
return 44330.0 * (1.0 - ((atmospheric_mbar / sea_level_mbar) ** 0.1903))
1 change: 1 addition & 0 deletions esp32/comic_code_24.bin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?�?���?����ǝ�?��������������?���������񏙏�g�������?���������������Ǐ�����{���Ǐ�������������������������������y����������'�������?�����������������{������������������?������������������Ǐ������χ�C��������'�������������������������c�����?����'���������������������s���������������c���?�����������s����?�����������#����������������s��������������������?��ǃ��������s�������������������������'�����s�����������������������������������s������������?�������?����<���LJ������s�������������?�������?����=��������s��������?��?��?�������������������?��?�?�?����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
4 changes: 4 additions & 0 deletions esp32/comic_code_24.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
width = 16
height = 36
chars = "CRHpm1234567890.°%$Є"
bin_filename = "comic_code_24.bin"
Binary file added esp32/comic_code_48.bin
Binary file not shown.
4 changes: 4 additions & 0 deletions esp32/comic_code_48.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
width = 32
height = 72
chars = "1234567890"
bin_filename = "comic_code_48.bin"
57 changes: 57 additions & 0 deletions esp32/config.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"debug": 1,
"lightsleep": false,
"screen": {
"enabled": true,
"refresh_rate": 4,
"refresh_rate_wlan": 4,
"debug": true,
"width": 122,
"height": 250
},
"pins": {
"i2c_scl": 27,
"i2c_sda": 26,
"wlan": 33,
"bt": 25,
"screen_cs": 19,
"screen_scl_clk": 18,
"screen_din_mosi": 23,
"screen_busy": 22,
"screen_dc": 21,
"screen_dummy": 15
},
"logs": [
"co2",
"c",
"rh",
"pressure"
],
"history_size": 50,
"wlan": {
"ssid": "SSIDGoesHere",
"password": "password-goes-here",
"connection_wait_s": 10
},
"bluetooth": {
"name": "avenet42",
"advertisement_freq_us": 250000
},
"scd41": {
"low_power": true,
"asc": true
},
"bmp180": {
"upper_pressure": 130000,
"lower_pressure": 70000,
"oversampling": 3,
"oversampling_wlan": 3
},
"influx": {
"host": "http://192.0.2.1:8086",
"bucket": "bucket-goes-here",
"username": "username-goes-here",
"password": "password-goes-here",
"datapoint": "cvhhc-scd41-portable"
}
}
Binary file added esp32/font_large.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added esp32/font_small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 28a087a

Please sign in to comment.