initial commit

This commit is contained in:
baldeau 2025-02-28 21:42:48 +01:00
commit ed8d117bd3
34 changed files with 7669 additions and 0 deletions

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store

4
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

5
Makefile Normal file
View File

@ -0,0 +1,5 @@
preview:
wrangler pages dev ./dist
deploy:
npx wrangler pages deploy dist

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# Pet Activity Monitor Docs
The documentation website for the `Pet Activity Monitor` project.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :---------------- | :------------------------------------------ |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build the production site to `./dist/` |
| `npm run preview` | Preview the build locally, before deploying |

30
astro.config.mjs Normal file
View File

@ -0,0 +1,30 @@
// @ts-check
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
// https://astro.build/config
export default defineConfig({
integrations: [
starlight({
title: 'Pet Activity Monitor',
social: {
"github": 'https://avoid.sh/PetActivityMonitor',
},
sidebar: [
{
label: 'Overview',
autogenerate: { directory: '0_overview' },
},
{
label: 'Record App',
autogenerate: { directory: '1_record_app' },
},
{
label: 'Analysis App',
autogenerate: { directory: '2_analysis' },
},
],
}),
],
});

6994
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "pet-activity-monitor-docs",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/starlight": "^0.32.1",
"astro": "^5.1.5",
"sharp": "^0.32.5",
"photoswipe": "^5.4.3"
}
}

1
public/favicon.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M81 36 64 0 47 36l-1 2-9-10a6 6 0 0 0-9 9l10 10h-2L0 64l36 17h2L28 91a6 6 0 1 0 9 9l9-10 1 2 17 36 17-36v-2l9 10a6 6 0 1 0 9-9l-9-9 2-1 36-17-36-17-2-1 9-9a6 6 0 1 0-9-9l-9 10v-2Zm-17 2-2 5c-4 8-11 15-19 19l-5 2 5 2c8 4 15 11 19 19l2 5 2-5c4-8 11-15 19-19l5-2-5-2c-8-4-15-11-19-19l-2-5Z" clip-rule="evenodd"/><path d="M118 19a6 6 0 0 0-9-9l-3 3a6 6 0 1 0 9 9l3-3Zm-96 4c-2 2-6 2-9 0l-3-3a6 6 0 1 1 9-9l3 3c3 2 3 6 0 9Zm0 82c-2-2-6-2-9 0l-3 3a6 6 0 1 0 9 9l3-3c3-2 3-6 0-9Zm96 4a6 6 0 0 1-9 9l-3-3a6 6 0 1 1 9-9l3 3Z"/><style>path{fill:#000}@media (prefers-color-scheme:dark){path{fill:#fff}}</style></svg>

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
src/assets/houston.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
src/assets/logo.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

BIN
src/assets/tinygo-logo.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

View File

@ -0,0 +1,59 @@
---
import type { ImageMetadata } from "astro";
import { Image, getImage } from "astro:assets";
interface Props {
imageFolder: string;
image: string;
}
const { imageFolder, image } = Astro.props;
const imagePath = `/src/assets/${imageFolder}/${image}`;
let imageImport = import.meta.glob<{ default: ImageMetadata }>(
"/src/assets/*/*"
);
let imageSrc = imageImport[imagePath]();
let optimizedImage = await getImage({
src: imageSrc,
width: 1920,
});
---
<div
id="gallery"
class="container mx-auto px-2 pb-2 grid grid-cols-2 md:grid-cols-3 gap-2"
>
{
(
<a
href={optimizedImage.src}
data-pswp-width={optimizedImage.attributes.width}
data-pswp-height={optimizedImage.attributes.height}
target="_blank"
class="overflow-hidden rounded-md border-[1px] border-primary hover:border-secondary"
>
<Image
src={imageSrc}
alt={"altText"}
height={450}
class={
"object-cover w-full grayscale-[80%] hover:grayscale-0 transition duration-300 ease-in-out aspect-[3/2]"
}
/>
</a>
)
}
</div>
<script>
import PhotoSwipeLightbox from "photoswipe/lightbox";
import "photoswipe/style.css";
const lightbox = new PhotoSwipeLightbox({
gallery: "#gallery",
children: "a",
pswpModule: () => import("photoswipe"),
});
lightbox.init();
</script>

View File

@ -0,0 +1,61 @@
---
import type { ImageMetadata } from "astro";
import { Image, getImage } from "astro:assets";
interface Props {
imageFolder: string;
}
const { imageFolder } = Astro.props;
const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/*/*");
const imagePaths = Object.keys(images).filter((imagePath) => {
return imagePath.startsWith(`/src/assets/${imageFolder}/`);
});
---
<div
id="gallery"
class="container mx-auto px-2 pb-2 grid grid-cols-2 md:grid-cols-3 gap-2"
>
{
imagePaths.map(async (imagePath) => {
let image = images[imagePath]();
let optimizedImage = await getImage({
src: image,
width: 1920,
});
return (
<a
href={optimizedImage.src}
data-pswp-width={optimizedImage.attributes.width}
data-pswp-height={optimizedImage.attributes.height}
target="_blank"
class="overflow-hidden rounded-md border-[1px] border-primary hover:border-secondary"
>
<Image
src={image}
alt={"altText"}
height={350}
class={
"object-cover w-full grayscale-[80%] hover:grayscale-0 transition duration-300 ease-in-out aspect-[3/2]"
}
/>
</a>
);
})
}
</div>
<script>
import PhotoSwipeLightbox from "photoswipe/lightbox";
import "photoswipe/style.css";
const lightbox = new PhotoSwipeLightbox({
gallery: "#gallery",
children: "a",
pswpModule: () => import("photoswipe"),
});
lightbox.init();
</script>

7
src/content.config.ts Normal file
View File

@ -0,0 +1,7 @@
import { defineCollection } from 'astro:content';
import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
};

View File

@ -0,0 +1,8 @@
---
title: Introduction
description: An introduction for the project.
---
## Used Hardware
- [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html)

View File

@ -0,0 +1,129 @@
---
title: Requirements & Setup
description: A reference page in my new Starlight docs site.
---
import { Steps, Tabs, TabItem } from "@astrojs/starlight/components";
## Flutter Installation
<Tabs>
<TabItem label="Windows">
<Steps>
1. Flutter requires [git](https://git-scm.com) which can be installed at [https://git-scm.com/download/win](https://git-scm.com/download/win)
1. Install Puro with the following command:
```bash
Invoke-WebRequest -Uri "https://puro.dev/builds/1.4.8/windows-x64/puro.exe" -OutFile "$env:temp\puro.exe"; &"$env:temp\puro.exe" install-puro --promote
```
1. After installing Puro reload your shell and make sure the `puro` command is accessible.
1. Initialize Puro with the latest stable Flutter version:
```bash
puro flutter
```
1. Now the commands `flutter` and `dart` should be accessible in your shell. You are all set up with the latest stable Flutter and Dart version! For more infos check out [https://puro.dev/](https://puro.dev/).
</Steps>
</TabItem>
<TabItem label="macOS">
<Steps>
1. Flutter requires [git](https://git-scm.com) which can be installed with [Homebrew](https://brew.sh) for macOS:
```bash
brew install git
```
1. Install Puro with the following command:
```bash
curl -o- https://puro.dev/install.sh | PURO_VERSION="1.4.8" bash
```
1. After installing Puro reload your shell and make sure the `puro` command is accessible.
1. Initialize Puro with the latest stable Flutter version:
```bash
puro flutter
```
1. Now the commands `flutter` and `dart` should be accessible in your shell. You are all set up with the latest stable Flutter and Dart version! For more infos check out [https://puro.dev/](https://puro.dev/).
</Steps>
</TabItem>
<TabItem label="Linux">
<Steps>
1. Flutter requires [git](https://git-scm.com) which can be installed with most package managers e.g. apt:
```bash
sudo apt install git
```
1. Install Puro with the following command:
```bash
curl -o- https://puro.dev/install.sh | PURO_VERSION="1.4.8" bash
```
1. After installing Puro reload your shell and make sure the `puro` command is accessible.
1. Initialize Puro with the latest stable Flutter version:
```bash
puro flutter
```
1. Now the commands `flutter` and `dart` should be accessible in your shell. You are all set up with the latest stable Flutter and Dart version! For more infos check out [https://puro.dev/](https://puro.dev/).
</Steps>
</TabItem>
</Tabs>
## TinyGO Installation
<Tabs>
<TabItem label="Windows">
<Steps>
1. It is recommended to use [Scoop](https://scoop.sh) to install TinyGo and it's dependencies on Windows:
```bash
scoop install go
```
Followed by:
```bash
scoop install tinygo
```
</Steps>
</TabItem>
<TabItem label="macOS">
<Steps>
1. Use [Homebrew](https://brew.sh) to install TinyGo:
```bash
brew tap tinygo-org/tools
brew install tinygo
```
</Steps>
</TabItem>
<TabItem label="Linux">
<Steps>
1. The Linux installation can change depending on the latest TinyGo version and the used distro, check out the installation guide [here](https://tinygo.org/getting-started/install/linux/).
</Steps>
</TabItem>
</Tabs>

View File

@ -0,0 +1,58 @@
---
title: TinyGo Code
description: A reference page in my new Starlight docs site.
hero:
title: "TinyGo Code"
tagline: A Go Compiler For Small Places.
image:
alt: A glittering, brightly colored logo
file: ../../../assets/tinygo-logo.webp
---
[TinyGo](https://tinygo.org/) is a custom Go compiler for embedded systems and WebAssembly. It was used
to write the microcontroller code for recording the gyro data via Bluetooth.
## Setup
Grab the project files:
```bash
git clone https://avoid.sh/PetActivityMonitor/pet_activity_recorder_tinygo.git
```
And follow the information in the `README.md` file of the project.
## Usage
Only connect one microcontroller at the same time!
- Flash the code to the connected microcontroller.
```bash
make flash
```
- Flash the code in production mode (deactivated serial).
```bash
make production
```
- Flash the code in testing mode (enhanced optimisations that need more testing)
```bash
make testing
```
To set the microcontroller into a flashable state manually the project also includes a
`flashing_time.py` python script.
The script requires `pyserial`:
```bash
python -m pip install pyserial
```
When running the code with `./flashing_time` or `make prepare` (inside of the project directory) the microcontroller will be put in a flashable state.
This state can also be activated manually by tapping the reset button on the microcontroller twice in a short time.

View File

@ -0,0 +1,64 @@
---
title: Flutter Code
description: A reference page in my new Starlight docs site.
hero:
title: "Flutter Code"
tagline: Build apps for any screen.
image:
alt: A glittering, brightly colored logo
file: ../../../assets/come_to_the_dartside.webp
---
import { Steps } from "@astrojs/starlight/components";
The app for receiving and storing the data from the microcontroller was written in
[Flutter](https://flutter.dev/) with the [Dart](https://dart.dev/) programming language.
The app has support for:
- Windows
- macOS
- Linux
- Android
- iOS
## Setup
<Steps>
1. Grab the project files:
```bash
git clone https://avoid.sh/PetActivityMonitor/xiao_pet_tracker.git
```
2. Run `flutter pub get` to load the dependencies.
3. The project contains 3 flavors:
- development
- staging
- production
To run the desired flavor either use the launch configuration in VSCode/Android Studio or use the following commands:
```sh
# Development
$ flutter run --flavor development --target lib/main_development.dart
# Staging
$ flutter run --flavor staging --target lib/main_staging.dart
# Production
$ flutter run --flavor production --target lib/main_production.dart
```
The `development` flavor is used for developing, it includes Dart's Hot Reload feature where you
can make live changes to the code and immediately use these changes in the running app without restarting it.
When using the app the `production` flavor is recommended. This will compile the app natively with
much deeper optimizations.
The `staging` flavor is not needed to be used in the current state of the app.
</Steps>

View File

@ -0,0 +1,49 @@
---
title: App Usage
description: A reference on how to use the app.
---
import PhotoSwipe from "../../../components/PhotoSwipe.astro";
import { Steps } from "@astrojs/starlight/components";
Here's a short usage guide on the recording app. This uses the iOS version of the app, but it works similiar
for Android, Linux, macOS and Windows.
<Steps>
1. When you open the app you will be greeted with the `Xiao Connector` screen. Tap on `Connect` to connect to the microcontroller.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0377.PNG" />
2. To conserve power, the microcontroller enters a low-power mode upon Bluetooth connection, preventing automatic
acceleration data recording. To access a live feed, manually activate it by tapping on `Open Live Feed`.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0376.PNG" />
3. This is what the feed looks like when you are connected.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0378.PNG" />
A tap on `Sync Clocks` can be used to manually sync the clocks between the recording device and the microcontroller.
To start recording, enter a name and then tap on the start button at the bottom of the screen.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0379.PNG" />
To stop the recording, tap on the button at the bottom of the screen again.
4. Now you can switch to the `Recordings` screen by tapping on the `Recordings` icon in the navbar.
You'll see your newly created recording that was stored on your device.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0380.PNG" />
Tap on it to see the details of the recording and to access the `Export` functionality.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0381.PNG" />
5. The exported files will be stored in the documents of your device. Here we used an iPhone and we can
find the exported recording data as a CSV file in the app's folder in Files.
<PhotoSwipe imageFolder="xiao_app_screenshots" image="IMG_0382.PNG" />
</Steps>

View File

@ -0,0 +1,43 @@
---
title: Requirements & Setup
description: A reference page in my new Starlight docs site.
---
import { Steps, Tabs, TabItem } from "@astrojs/starlight/components";
## Rust Installation
If your using Windows, check out the guide [here](https://rustup.rs/#).
Otherwise:
<Steps>
1. Run the following in your terminal, then follow the onscreen instructions.
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
1. Get the `adafruit-nrfutil` from [here](https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/update-bootloader-use-command-line). Follow the installation guide on their website.
1. Install `arm-none-eabi-objcopy` on your device.
On macOS you can get it from Homebrew:
```bash
brew install arm-none-eabi-gcc
```
On Ubuntu install it with apt:
```bash
sudo apt install gcc-arm-none-eabi
```
Use scoop on Windows:
```bash
scoop install gcc-arm-none-eabi
```
</Steps>

View File

@ -0,0 +1,62 @@
---
title: Rust Code
description: A reference page in my new Starlight docs site.
hero:
title: "Seeed XIAO nRF52840 with Rust"
tagline: Blazingly fast on-device inference.
image:
alt: A glittering, brightly colored logo
file: ../../../assets/ferris_embedded.webp
---
import { Steps, Tabs, TabItem } from "@astrojs/starlight/components";
The analysis of the acceleration and rotation data on-device requires us to run a TinyML model on the microcontroller in an efficient manner.
TinyGo unfortunately does not have any support for running TinyML models at the moment
and we had to switch to Rust.
## Why Rust?
The decision to adopt Rust was driven by several key factors,
particularly its suitability for resource-constrained embedded environments.
- **[MicroFlow](https://github.com/matteocarnelos/microflow-rs) integration**: Developed by Matteo Carnelos, MicroFlow excels in deploying machine learning models on embedded systems. Its compiler-based architecture, consisting of the microflow-macros and microflow crates, allows for efficient model parsing, preprocessing, and runtime execution.
- **[Embassy](https://embassy.dev) for Asynchronous Programming**: Rust's embassy framework provided us with a robust and user-friendly solution for asynchronous programming. This was essential for managing concurrent tasks and optimizing performance on the microcontroller. Embassy greatly simplifies the development of responsive and efficient embedded applications.
- **Performance and Memory Efficiency**: Rust's focus on performance and memory safety aligns perfectly with the requirements of TinyML. Its zero-cost abstractions and control over memory management enable us to optimize our model execution for minimal resource consumption.
- **Memory Safety**: In embedded systems, memory errors can lead to unpredictable behavior and system crashes. Rust's strong memory safety guarantees, enforced at compile time, prevent common errors like buffer overflows, dangling pointers, and data races. This is crucial for ensuring the reliability and stability of our on-device TinyML implementation.
## Rust Support for the Xiao Seeed BLE
There was no full implementation for the Xiao Seeed BLE microcontroller available anywhere online in Rust. The embassy library has support for the `nrf52840` SoC, but we
had to write custom drivers to access the acceleration and rotation data from the `lsm6ds3tr` IMU.
These driver are available [here](https://avoid.sh/PetActivityMonitor/lsm6ds3tr).
## Usage
<Steps>
1. Get the Rust project files:
```bash
git clone https://avoid.sh/PetActivityMonitor/xiao_pet_tracker_rust.git
```
The project contains multiple Rust projects separated into folders.
1. The project contains a `build_and_flash.sh` script to easily build the project and flash it to the microcontroller. Put the microcontroller into DFU mode and run the script with the folder name of the project as secondary parameter.
```bash
# flash the lsm6ds3tr demo
./build_and_flash.sh lsm6ds3tr_demo
# flash the tflite demo
./build_and_flash.sh tflite_demo
```
Make sure to edit the `COM_PORT` variable accordingly to your connected controller. You can use `tinygo ports` from the commandline to check the ports.
</Steps>
## Issues
After flashing the microcontroller with the Rust project, the DFU mode can only be entered manually by clicking the reset button twice in a short time. It is currently not possible to send a signal to the device to enter the DFU mode.

7
src/content/docs/faq.md Normal file
View File

@ -0,0 +1,7 @@
---
title: FAQ
description: A guide in my new Starlight docs site.
---
Guides lead a user through a specific task they want to accomplish, often with a sequence of steps.
Writing a good guide requires thinking about what your users are trying to do.

View File

@ -0,0 +1,19 @@
---
title: Welcome to the Pet Activity Monitor Project!
description: Tracking pet activity with microcontrollers and machine learning.
template: splash
hero:
tagline: Tracking pet activity with microcontrollers and machine learning.
image:
file: ../../assets/logo.webp
actions:
- text: Let's go!
link: /0_overview/
icon: right-arrow
- text: Check out the source code.
link: https://avoid.sh/PetActivityMonitor
icon: external
variant: minimal
---
import { Card, CardGrid } from "@astrojs/starlight/components";

5
tsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}