# Dog Activity Monitor Simon Nyberg (sn223rx) # Introduction This project introduces a device for measuring a dog's activity during walks or throughout the day. It utilizes a Raspberry Pi Pico, ADXL345 Accelerometer, HiveMQ MQTT Broker, Node-RED, InfluxDB, and Grafana. For someone familiar with similar projects, the device setup and coding might take approximately a week, including coffee breaks. # Objective The dog activity monitor is an evolution of my initial idea for a dog pedometer. The primary motivation behind this project is to monitor the activity levels of my parents aging dog. As he grow older, his exercise needs and patterns change, making it important to track his daily movement. The goal of making this device is: 1. Quantify the dog's daily activity levels 1. Provide insights into exercise patterns 1. Help in making informed decisions about the dog's care and exercise routine The data collected will offer valuable insights into: * Duration and intensity of daily activities * Periods of rest versus activity * Changes in activity patterns # Material Here's a list of the materials used in this project: | Component | Purpose | Source | Cost | | ---------------------- | -------------------------- | --------------------- | --------------------------- | | Pico WH | Main processing unit | Electrokit | 109 SEK | | Breadboard | Connect components | Electrokit | 69 SEK | | ADXL345 Accelerometer | Movement sensor | Electrokit | 345 SEK | | 7-Segment Display | Display simple data | Electrokit | 59 SEK | | 4.7k Ohm Resistor (x2) | Limit current to sensor | N/A (Repurposed) | Free | | Male-Male Cables (x24) | Connections | Electrokit / Homemade | 29 SEK | | Micro-USB Cable | Connect Pico W to computer | Electrokit | 28 SEK | | Powerbank | Provide power to device | N/A (Repurposed) | Free | | Dog | Gather data | ICAs parkinglot | Free if you are fast enough | # Computer Setup For this project, I've chosen to use Thonny as the Integrated Development Environment (IDE). Thonny offers excellent functionality for IoT development, particularly for MicroPython projects like this one. Thonny provides several advantages for this project: * Built-in support for MicroPython * Easy-to-use interface for beginners * Direct communication with the Raspberry Pi Pico * Integrated debugger for troubleshooting To set up the development environment: 1. Download and install [Thonny](https://thonny.org/) from the official website 1. Connect the Raspberry Pi Pico to your computer via USB 1. In Thonny, select 'MicroPython (Raspberry Pi Pico)' as the interpreter To use MicroPython on the Pico, you will need to flash new firmware to it: 1. Download the [MicroPython firmware](https://micropython.org/download/RPI_PICO_W/) 1. Connect the Micro-USB cable to the Pico 1. Before inserting the other end of the cable to your computer, hold the [BOOTSEL button](https://iotdesignpro.com/sites/default/files/inline-images/BOOTSEL-Button-on-Raspberry-Pi-Pico-W.jpg) 1. Go to your computers file system and you will see a new device connected named RPI-RP2 1. Drag and drop the micropython.uf2 file into RPI-RP2s storage, wait a couple seconds 1. Done To use MQTT with the Pico you will need to upload a external library to it, first you need to: 1. Download the [umqtt library](https://pypi.org/project/micropython-umqtt.simple/#files) 1. Open thonny and connect the Pico and select it as interpeter 1. Navigate to the downloaded folder umqtt in Thonnys file explorer 1. Right click the simple.py and click upload # Putting everything together To connect the SparkFun ADXL345 Accelerometer, i had 2 options provided in their [documents](https://learn.sparkfun.com/tutorials/adxl345-hookup-guide/all), and since i didnt have all the componetes for their first circut diagram, i naturially went with the [second option](https://cdn.sparkfun.com/assets/learn_tutorials/5/4/8/ADXL345Fix.png) The device consists of three main components connected to the Raspberry Pi Pico W: 1. ADXL345 Accelerometer: * Connected via I2C protocol * Uses 4 wires: VCC (3.3V), GND, SDA (GP0), and SCL (GP1) * Two 4.7k Ohm resistors are connected to SDA and SCL lines 2. 4-Digit 7-Segment Display: * Directly connected to GPIO pins * Uses 14 wires 3. Breadboard: * Used for organizing connections and mounting components ![image](https://hackmd.io/_uploads/B13h9RFL0.png) # Platform The chosen platforms all operate in the cloud, prioritizing independence and flexibility. This ensures consistent access and performance, regardless of local conditions, however each component can be run locally if required. All platforms offer free trials, which I took advantage of for this project. The key components of my cloud-based infrastructure stack include: **HiveMQ MQTT Broker** HiveMQ is an enterprise-ready MQTT broker that provides scalable and reliable IoT connectivity. It's used in this project to handle the MQTT communication between the dog activity monitor and the data processing pipeline. **Node-RED** Node-RED is a open-source flow-based development tool for visual programming. It's particularly useful for IoT projects as it allows for easy integration of various protocols and services. In this project, Node-RED is used to: * Receive data from the MQTT broker * Process and transform the accelerometer data * Send the processed data to InfluxDB **InfluxDB** InfluxDB is a time series database designed to handle high write and query loads. It's ideal for IoT applications due to its ability to efficiently store and query time-stamped data. **Grafana** Grafana is an open-source visualization and analytics platform, chosen for its superior flexibility and features compared to InfluxDB's built-in dashboards. Key advantages include: * Highly customizable dashboards with a wide range of visualization options * Advanced alerting system with multiple notification channels * User-friendly and visually appealing interfaces **For scaling this project, several options are available:** 1. Cloud Scaling: * Upgrade to paid tiers of the current cloud services for increased capacity and features. * Implement auto-scaling features in cloud platforms to handle varying loads. 2. Self-Hosted Alternative: * For complete control and potentially lower long-term costs, transition to self-hosted versions of these tools: * Replace HiveMQ with Mosquitto MQTT broker * Self-host Node-RED, InfluxDB, and Grafana on a dedicated server or cluster 3. Hybrid Approach: * Keep data-intensive components (InfluxDB, Grafana) in the cloud * Self-host Node-RED and MQTT broker for lower latency and more control Each approach offers different trade-offs between scalability, control, cost, and complexity. The choice depends on factors like data volume, privacy requirements, and available resources. # The code I dont have a specific core funtionality in my project, its more how so the different part of the code works togheter to bring the result. All of the code below is in the main loop of the program, split up to explain how it works togheter. ``` while True: try: x, y, z = read_accel_data() current_magnitude = calculate_acceleration_magnitude(x, y, z) # Normalize the magnitude by subtracting the baseline normalized_magnitude = max(0, current_magnitude - baseline) ``` The loop starts by reading the accelerometer data and calculating the magnitude of acceleration. Normalization is is done as it helps to isolate the dog's movement from the constant acceleration noise generated by the sensor. ``` update_activity_window(normalized_magnitude) avg_activity = get_average_activity() ``` The normalized magnitude is added to an activity window of recent activity levels. The average activity is then calculated from this window, this to smooth out short-term fluctuations. ``` # Calculate percentage change if last_sent_activity > 0: percent_change = abs(avg_activity - last_sent_activity) / last_sent_activity else: percent_change = 1 # Force an update if last_sent_activity is 0 ``` This calculates the percentage change in activity since the last update, which helps reduce unnecessary data transmissions. ``` # Only send an update if the activity level has changed significantly if percent_change > ACTIVITY_THRESHOLD: last_sent_activity = avg_activity publish(MQTT_TOPIC, round(avg_activity, 2), client) ``` An update is sent if the change in activity exceeds a predefined threshold. ``` print(f"Current activity level: {avg_activity:.2f}") time.sleep(0.1) # Short delay between readings ``` The current activity level is printed for monitoring, and a short delay is introduced to control the sampling rate. Since i also have a 7-Segment Display connected to my Pico, i have chosen to display statuscodes for the program. This device will be used remotly, Thus its very handy to be able to always see the status of the device. ``` except Exception as e: print(f"Error in main loop: {e}") update_state(3, 0) # Main loop error # Attempt to reconnect try: client = make_connections() update_state(1, 1) # WiFi connected update_state(2, 1) # MQTT connected update_state(3, 1) # All systems go except: update_state(1, 0) # WiFi disconnected update_state(2, 0) # MQTT disconnected time.sleep(5) # Wait before retrying ``` All the code above is within a try statement, and this section is in the except block running on the Pico's second thread in parallell. This allows to identify any failures related to these states when using the device. If an error occurs, the system will update the device's state accordingly. # Transmitting the data / connectivity Initially, I planned to send data directly from the Pico to InfluxDB and visualize it on Grafana. However, this setup proved too slow and inflexible. InfluxDB's lack of UDP support and the Pico's inability to multithread packet sending necessitated a more resilient solution. To address these limitations, I implemented an MQTT Broker and a flow handler. Node-RED was chosen for its versatility in handling various protocols and formats, significantly improving the system's efficiency and flexibility. Breakdown of the process: 1. Primary Wireless Protocol: WiFi and Mobile Hotspot (LTE) * The device connects to a local WiFi or LTE network using the network.WLAN module in MicroPython. ``` def wifi_connect(): wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(SSID, PASSWORD) while not wlan.isconnected(): print("Waiting for Wi-Fi connection...") time.sleep(1) print("Connected to Wi-Fi:", wlan.ifconfig()[0]) 1. Transport Protocol: MQTT (Message Queuing Telemetry Transport) * MQTT is used for sending data to the cloud, regardless of the underlying wireless connection. ``` def connectMQTT(): client = MQTTClient( client_id=MQTT_CLIENT_ID, server=MQTT_SERVER, port=MQTT_PORT, user=MQTT_USERNAME, password=MQTT_PASSWORD, keepalive=7200, ssl=True, ssl_params={'server_hostname': MQTT_SERVER} ) client.connect() return client 1. Data Flow: Device -> (WiFi/LTE) -> HiveMQ (MQTT Broker) -> Node-RED -> InfluxDB -> Grafana 1. Device to HiveMQ: MQTT over TCP/IP (WiFi or LTE) 2. HiveMQ to Node-RED: MQTT over WebSocket 3. Node-RED to InfluxDB: HTTP/HTTPS (InfluxDB HTTP API) 4. InfluxDB to Grafana: HTTP/HTTPS (InfluxDB Query API) * MQTT: Lightweight, ideal for IoT devices * WebSocket: Enables real-time, bidirectional communication * HTTP/HTTPS: Flexible, widely supported for server-side operations 3. Package Format: The data is sent as a string representation of a float value, representing the average activity level 4. Transmission Frequency: Data is sent only when there's a significant change in activity level (>15% change), with a max frequency of one every 1/10 second. ``` def publish(topic, value, client): print(topic) print(value) client.publish(topic, str(value)) print("publish done") ``` # Presenting the data The dashboard is very simple and intuitive, i plot a single chart of the dogs activity as the values im sending represent. The dashboard is built using Grafana, connected to InfluxDB as the data source. For data preservation, InfluxDB retains data for 30 days by default, which i have not changed due to not needing to, but this can be configured based on storage capacity and requirements. The data is saved in InfluxDB every time it's received from Node-RED, which occurs when there's a significant change in activity level (>15% change). Database Choice: InfluxDB was chosen for its: * Optimized time-series data storage * Efficient querying of time-based data * Seamless integration with Grafana * Ability to handle high write loads from IoT devices ![image](https://hackmd.io/_uploads/ryAmImn80.png) # Finalizing the design Overall, the project was a success, i have changed apporach numerous times along the way since the original idea wasnt really duable or i wasnt satisfied with the result it yielded. The final outcome surpassed my expectations. However, there's always room for improvement, particularly in the device's mounting solution. Currently, I've repurposed an old vest and secured the device and battery with duct tape—a makeshift solution that, unsurprisingly, isn't ideal. A more robust and professional approach would involve designing and 3D printing a custom mount. This would significantly enhance the stability and longevity of the device on the dog's back, addressing the limitations of the current tape-based attachment. Such an improvement would not only make the device more secure but also more comfortable for the dog to wear over extended periods. Overall, I'm very satisfied with the device's performance. While there are no critical areas requiring immediate improvement, there's always potential for enhancement. For a large-scale production or commercial version, upgrading the sensor and microprocessor could yield more accurate data and additional features. However, for the current scope and purpose of the project, the existing components provide a robust and effective solution. The balance between functionality and simplicity in the current design serves the intended purpose well. I have tried my best to showchase the diverse and accurate values the sensor outputs. as we can see the chart is set to 5min. i put the sensor on the dog and played fetch for a couple of minutes, and we can clearly see when he is running or moving, and/or standing/laying still. ![image](https://hackmd.io/_uploads/B1dtmQhU0.png) **Short video demonstrating the device on dog:** https://youtu.be/GtCDjgvOuuw **Some pictures with the device on dog** ![image](https://hackmd.io/_uploads/ryulZVh80.png) <div style="width:100%;height:0;padding-bottom:56%;position:relative;"><iframe src="https://giphy.com/embed/elhZf4ZuFTf8R64njC" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe></div><p><a href="https://giphy.com/gifs/elhZf4ZuFTf8R64njC">via GIPHY</a></p> ![IMG_0949](https://hackmd.io/_uploads/HkcOQ2C80.jpg)