Skip to content

Commit

Permalink
πŸŽ‰ Intial commit
Browse files Browse the repository at this point in the history
✨ Added library for tmf8805
βœ… Added tests for the library
🀑 Added mocked machine and utime modules for tests
πŸ“„ Added MIT license file
πŸ‘· Added github ci with ruff, black and pytest
  • Loading branch information
marcelkwaschny committed Mar 5, 2024
0 parents commit 2755dae
Show file tree
Hide file tree
Showing 14 changed files with 945 additions and 0 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Quality Assurance

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build:

runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.11

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff black pytest pytest-cov
- name: Run Ruff
run: |
ruff check
- name: Run Black
run: |
black --check .
- name: Run Pytest
run: |
pytest --cov=tmf8805 --cov-fail-under=80 tests
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.micropico
.vscode/
.venv/
venv/
.ruff_cache/
__pycache__/
.pytest_cache/
.coverage
coverage.xml
14 changes: 14 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.3
hooks:
- id: ruff
- repo: https://github.com/psf/black
rev: 22.10.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black", "--filter-files"]
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Marcel Kwaschny

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.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# RP2040 with TMF8805 using MicroPython

This code origins from the course [Embedded Systems](https://www.fh-muenster.de/eti/personen/professoren/gloesekoetter/embedded-systems.php) at [FH MΓΌnster – University of Applied Sciences](https://www.fh-muenster.de/). There a RP2040 with a TMF8805 programmed with MicroPython was used to measure the water level in a pipe with a swimmer.

## Development

To setup your local development environment install [Visual Studio Code](https://code.visualstudio.com/) and the [MicroPico](https://marketplace.visualstudio.com/items?itemName=paulober.pico-w-go) extension. After that connect the Raspberry Pi Pico using a USB cabel and run your code using MicroPico. To enforce a global style please install the [development requirements](./dev.requirements.txt) and after that the pre-commit hook using `pre-commit install`.

## Setup & upload project to Pico

- Download the latest firmware from https://micropython.org/download/RPI_PICO/ and flash the RP2040 via UF2 bootloader
- Follow the steps above to setup a local development environment
- Open the command pallete (```CTRL + SHIFT + P```)
- Search for ```MicroPico: Configure project``` and execute it
- Search for ```MicroPico: Upload project to Pico``` and execute it
- Switch to the ```main.py``` and run it!

## TMF8805

To create an instance of the `TMF8805` class you can use the following code snippet:

```python
tmf8805: TMF8805 = TMF8805(
enable=7,
sda=4,
scl=5,
i2c_frequency=100000,
debug=True
)
tmf8805.initialize()
distance: float = tmf8805.get_measurement()
print(f"Measured distance: {distance}mm")
```

or copy the contents from `main.py`
6 changes: 6 additions & 0 deletions dev.requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pre-commit
ruff
isort
black
pytest
pytest-cov
18 changes: 18 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import machine

from tmf8805.tmf8805 import TMF8805

if __name__ == "__main__":
tmf8805: TMF8805 = TMF8805(
enable=7,
sda=4,
scl=5,
i2c_frequency=100000,
debug=True,
wdt=machine.WDT(timeout=8000),
)

while True:
tmf8805.initialize()
distance: int = tmf8805.get_measurement()
print(f"Distance: {distance}mm")
Empty file added tests/__init__.py
Empty file.
30 changes: 30 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""This module contains general test configuration"""

import sys

import pytest

from tests import machine_mock, utime_mock

# Mocks the micropython machine module
sys.modules["machine"] = machine_mock

# Mocks the utime module
sys.modules["utime"] = utime_mock

from tmf8805.tmf8805 import TMF8805 # noqa: E402


@pytest.fixture
def tmf8805_instance() -> TMF8805:
"""Fixture for a tmf8805 instance
Returns:
TMF8805: The object of a tmf8805 instance
"""

tmf8805: TMF8805 = TMF8805(
enable=7, sda=4, scl=5, i2c_frequency=100000, debug=True, wdt=machine_mock.WDT()
)

return tmf8805
133 changes: 133 additions & 0 deletions tests/machine_mock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""This module mocks the machine library from micropython"""

import sys
from enum import Enum
from typing import List


class TMF8805MockConfiguration(Enum):
"""Holds the different mock configurations"""

CORRECT_MEASUREMENT = 0
PERFORM_CALIBRATION = 1
NOT_CONNECTED = 2
CPU_READY_TIMEOUT = 3
APPLICATION_READY_TIMEOUT = 4
UNKNOWN_STATUS = 5
DATA_AVAILABLE_TIMEOUT = 6


TMF8805_MOCK_CONFIGURATION: TMF8805MockConfiguration = (
TMF8805MockConfiguration.CORRECT_MEASUREMENT
)


class I2C:
def __init__(self, *args, **kwargs) -> None:
"""Mocks the constructor of the I2C class"""

pass

def scan(self) -> List:
if TMF8805_MOCK_CONFIGURATION == TMF8805MockConfiguration.NOT_CONNECTED:
return []

return [65]

def readfrom_mem(self, addr, memaddr, nbytes, *, addrsize=8) -> bytes:
if memaddr == 0: # REGISTER_APPID
if (
TMF8805_MOCK_CONFIGURATION
== TMF8805MockConfiguration.APPLICATION_READY_TIMEOUT
):
return int(0).to_bytes(2, sys.byteorder)

return int(192).to_bytes(2, sys.byteorder)

if memaddr == 14: # REGISTER_ENABLE_REG
return int(1).to_bytes(2, sys.byteorder)

if memaddr == 29: # REGISTER_STATUS
if TMF8805_MOCK_CONFIGURATION == TMF8805MockConfiguration.UNKNOWN_STATUS:
return int(9999).to_bytes(
2, sys.byteorder
) # Status that is not implemented

return int(39).to_bytes(2, sys.byteorder) # MISSING_FACTORY_CALIBRATION

if memaddr == 30: # REGISTER_REGISTER_CONTENTS
if (
TMF8805_MOCK_CONFIGURATION
== TMF8805MockConfiguration.PERFORM_CALIBRATION
):
return int(10).to_bytes(2, sys.byteorder)

if (
TMF8805_MOCK_CONFIGURATION
== TMF8805MockConfiguration.DATA_AVAILABLE_TIMEOUT
):
return int(0).to_bytes(2, sys.byteorder)

return int(85).to_bytes(2, sys.byteorder)

if memaddr == 32: # REGISTER_FACTORY_CALIB_0
return ("A" * nbytes).encode()

if memaddr == 33: # REGISTER_RESULT_INFO
return int(63).to_bytes(2, sys.byteorder) # Reliability = 63, Status = 0

if memaddr == 34: # REGISTER_DISTANCE_PEAK_0
return int(226).to_bytes(2, sys.byteorder)

if memaddr == 35: # REGISTER_DISTANCE_PEAK_1
return int(4).to_bytes(2, sys.byteorder)

if memaddr == 224: # REGISTER_ENABLE_REG
if TMF8805_MOCK_CONFIGURATION == TMF8805MockConfiguration.CPU_READY_TIMEOUT:
return int(0).to_bytes(2, sys.byteorder)

return int(64).to_bytes(2, sys.byteorder)

if memaddr == 225: # REGISTER_INT_STATUS
return int(1).to_bytes(2, sys.byteorder)

pass

def writeto_mem(self, addr, memaddr, buf, *, addrsize=8) -> None:

pass


class Pin:
"""Mocks the micropython Pin class"""

OUT: int = 1

def __init__(self, *args, **kwargs) -> None:
"""Mocks the constructor of the Pin class"""

pass

def high(self) -> None:
"""Mocks the high function of the Pin class"""

pass

def low(self) -> None:
"""Mocks the low function of the Pin class"""

pass


class WDT:
"""Mocks the micropython watchdog class"""

def __init__(self, *args, **kwargs) -> None:
"""Mocks the constructor of the watchdog class"""

pass

def feed(self, *args, **kwargs) -> None:
"""Mocks the feed function of the watchdog"""

pass
Loading

0 comments on commit 2755dae

Please sign in to comment.