<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://community.element14.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Forum - Recent Threads</title><link>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><lastBuildDate>Mon, 26 Oct 2026 05:39:34 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum" /><item><title>VitalSense – Part 12 : Combined Pulse Oximeter &amp; Temperature Monitoring System in LabVIEW</title><link>https://community.element14.com/thread/57390?ContentTypeID=0</link><pubDate>Mon, 26 Oct 2026 05:39:34 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:68fb0cfe-eea7-4bf6-a65d-662135babd2f</guid><dc:creator>jelektro</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57390?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;The culmination of this project is a unified LabVIEW application that simultaneously acquires,&lt;/span&gt;&lt;span&gt; processes,&lt;/span&gt;&lt;span&gt; and visualizes multi-sensor biomedical data.&lt;/span&gt;&lt;span&gt; By merging the serial communication streams from both the STM-based pulse oximeter (USB-CDC JSON telemetry) and the MAX30208EVSYS temperature sensor,&lt;/span&gt;&lt;span&gt; the system provides a comprehensive patient monitoring dashboard.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PCStudio1.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node="4"&gt;1. Multi-Device Architecture &amp;amp; Parallel Acquisition&lt;/h4&gt;
&lt;ul data-path-to-node="5"&gt;
&lt;li&gt;
&lt;p data-path-to-node="5,0,0"&gt;&lt;b data-path-to-node="5,0,0" data-index-in-node="0"&gt;Independent COM Ports:&lt;/b&gt;&lt;span&gt; The application manages dual serial connections using NI-VISA sessions running concurrently or sequentially within a structured architecture (such as a Producer-Consumer pattern or parallel &lt;/span&gt;&lt;code data-path-to-node="5,0,0" data-index-in-node="213"&gt;While Loops&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="5,1,0"&gt;&lt;b data-path-to-node="5,1,0" data-index-in-node="0"&gt;Stream Synchronization:&lt;/b&gt;&lt;span&gt; Combines the temperature sensor&amp;#39;s polling command (&lt;/span&gt;&lt;code data-path-to-node="5,1,0" data-index-in-node="75"&gt;t0\r&lt;/code&gt;&lt;span&gt;) with the continuous JSON data stream (&lt;/span&gt;&lt;code data-path-to-node="5,1,0" data-index-in-node="119"&gt;{&amp;quot;bpm&amp;quot;: ..., &amp;quot;spo2&amp;quot;: ..., &amp;quot;filtered_ir&amp;quot;: ...}&lt;/code&gt;&lt;span&gt;) sent by the STM microcontroller.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node="6"&gt;2. Data Parsing &amp;amp; Robustness&lt;/h4&gt;
&lt;ul data-path-to-node="7"&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,0,0"&gt;&lt;b data-path-to-node="7,0,0" data-index-in-node="0"&gt;Unified String Cleaning:&lt;/b&gt;&lt;span&gt; Both input streams utilize &lt;/span&gt;&lt;b data-path-to-node="7,0,0" data-index-in-node="52"&gt;Trim Whitespace&lt;/b&gt;&lt;span&gt; to strip hidden carriage return and line feed characters (&lt;/span&gt;&lt;code data-path-to-node="7,0,0" data-index-in-node="126"&gt;\r\n&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; preventing parsing faults.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,0"&gt;&lt;b data-path-to-node="7,1,0" data-index-in-node="0"&gt;Error Prevention:&lt;/b&gt;&lt;span&gt; Firmware optimizations ensure that idle or error states (such as missing sensor contact) output standardized numeric frames instead of text strings,&lt;/span&gt;&lt;span&gt; eliminating &lt;/span&gt;&lt;i data-path-to-node="7,1,0" data-index-in-node="179"&gt;Error 85 (Scan Failed)&lt;/i&gt;&lt;span&gt; occurrences.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node="8"&gt;3. Combined Front Panel &amp;amp; Analytics Dashboard&lt;/h4&gt;
&lt;ul data-path-to-node="9"&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,0,0"&gt;&lt;b data-path-to-node="9,0,0" data-index-in-node="0"&gt;Dual Visualization:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="9,0,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,0,1,0,0"&gt;&lt;span&gt;Displays real-time photoplethysmogram (PPG) waveforms (&lt;/span&gt;&lt;code data-path-to-node="9,0,1,0,0" data-index-in-node="55"&gt;filtered_ir&lt;/code&gt;&lt;span&gt;) alongside continuous body temperature trends on synchronized &lt;/span&gt;&lt;b data-path-to-node="9,0,1,0,0" data-index-in-node="129"&gt;Waveform Charts&lt;/b&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,0,1,1,0"&gt;&lt;span&gt;Features dedicated vital signs indicators,&lt;/span&gt;&lt;span&gt; including digital gauges for Heart Rate (BPM),&lt;/span&gt;&lt;span&gt; SpO2 percentage scaled from 0 to &lt;/span&gt;&lt;b data-path-to-node="9,0,1,1,0" data-index-in-node="123"&gt;100&lt;/b&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; and precise temperature readouts.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,1,0"&gt;&lt;b data-path-to-node="9,1,0" data-index-in-node="0"&gt;Statistical Processing:&lt;/b&gt;&lt;span&gt; Utilizes internal &lt;/span&gt;&lt;b data-path-to-node="9,1,0" data-index-in-node="42"&gt;Formula Nodes&lt;/b&gt;&lt;span&gt; and shift registers to calculate real-time statistical averages,&lt;/span&gt;&lt;span&gt; minimums,&lt;/span&gt;&lt;span&gt; and maximums for thermal data.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node="8"&gt;4. Front Panel&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PCStudio-2.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node="8"&gt;5. Block Diagram&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PCStudio3.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 9 : MAXREFDES117 – JSON Data Acquisition via USB-CDC in LabVIEW</title><link>https://community.element14.com/thread/57389?ContentTypeID=0</link><pubDate>Mon, 26 Oct 2026 05:33:17 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:afc466fe-5516-4da5-846c-73f832c86e95</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57389?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;This section describes the implementation of serial communication and data parsing for retrieving sensor telemetry from an STM microcontroller.&lt;/span&gt;&lt;span&gt; The firmware transmits structured data frames via USB-CDC using a JSON format (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="3" data-index-in-node="229"&gt;{&amp;quot;bpm&amp;quot;: 73, &amp;quot;spo2&amp;quot;: 98, &amp;quot;filtered_ir&amp;quot;: 4425.22}&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="4"&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,0,0"&gt;&lt;b data-path-to-node="4,0,0" data-index-in-node="0"&gt;VISA Serial Configuration:&lt;/b&gt;&lt;span&gt; Opens and configures the virtual COM port with a baud rate of 115,&lt;/span&gt;&lt;span&gt;200 bps,&lt;/span&gt;&lt;span&gt; 8 data bits,&lt;/span&gt;&lt;span&gt; 1 stop bit,&lt;/span&gt;&lt;span&gt; and no flow control.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,1,0"&gt;&lt;b data-path-to-node="4,1,0" data-index-in-node="0"&gt;Data Stream Cleaning:&lt;/b&gt;&lt;span&gt; Incoming raw strings from &lt;/span&gt;&lt;code data-path-to-node="4,1,0" data-index-in-node="48"&gt;VISA Read&lt;/code&gt;&lt;span&gt; are processed through the &lt;/span&gt;&lt;b data-path-to-node="4,1,0" data-index-in-node="84"&gt;Trim Whitespace&lt;/b&gt;&lt;span&gt; function to strip out hidden carriage return and line feed characters (&lt;/span&gt;&lt;code data-path-to-node="4,1,0" data-index-in-node="171"&gt;\r\n&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; ensuring stable parsing.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,2,0"&gt;&lt;b data-path-to-node="4,2,0" data-index-in-node="0"&gt;String Scanning:&lt;/b&gt;&lt;span&gt; LabVIEW extracts numerical parameters (&lt;/span&gt;&lt;code data-path-to-node="4,2,0" data-index-in-node="56"&gt;bpm&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="4,2,0" data-index-in-node="61"&gt;spo2&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; and &lt;/span&gt;&lt;code data-path-to-node="4,2,0" data-index-in-node="71"&gt;filtered_ir&lt;/code&gt;&lt;span&gt;) to feed real-time indicators and logging modules.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PulseOximeter-LabView3.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/PulseOximeter-LabView2.mp4"&gt;community.element14.com/.../PulseOximeter-LabView2.mp4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5rb2o190" data-path-to-node="6"&gt;Handling Status Messages and Sensor States&lt;/h3&gt;
&lt;p id="p-rc_f9dc9a98d5a1c21b-200" data-path-to-node="7"&gt;&lt;span class="" data-path-to-node="7,0"&gt;To prevent parsing errors (such as &lt;i data-path-to-node="7,0" data-index-in-node="35"&gt;Error 85: Scan failed&lt;/i&gt;) when the sensor sends status updates instead of numeric values (e.g., when no finger is detected on the sensor, resulting in &lt;code data-path-to-node="7,0" data-index-in-node="183"&gt;{&amp;quot;status&amp;quot;: &amp;quot;&lt;span class="HwtZe" lang="en"&gt;&lt;span class="jCAhz ChMk0b"&gt;&lt;span class="ryNqvb"&gt;Missing finger on the sensor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;quot;}&lt;/code&gt;), specific error-mitigation strategies are applied&lt;/span&gt;&lt;span class="" data-path-to-node="7,1"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="7,2"&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="8"&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,0,0"&gt;&lt;b data-path-to-node="8,0,0" data-index-in-node="0"&gt;Stream Robustness:&lt;/b&gt;&lt;span&gt; Modernizing the firmware to output standardized numeric frames (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; zeros) during idle or error states ensures continuous and uninterrupted data parsing in LabVIEW.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,1,0"&gt;&lt;b data-path-to-node="8,1,0" data-index-in-node="0"&gt;Alternative Conditional Routing:&lt;/b&gt;&lt;span&gt; Using string-matching functions (&lt;/span&gt;&lt;code data-path-to-node="8,1,0" data-index-in-node="66"&gt;Match Pattern&lt;/code&gt;&lt;span&gt;) allows the application to dynamically detect status strings and safely route them to user interface warning messages without crashing the main acquisition loop.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5rb2o191" data-path-to-node="10"&gt;Real-Time Telemetry Visualization&lt;/h3&gt;
&lt;p data-path-to-node="11"&gt;&lt;span&gt;The user interface leverages native LabVIEW display elements optimized for biomedical signal monitoring:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="12"&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,0,0"&gt;&lt;b data-path-to-node="12,0,0" data-index-in-node="0"&gt;PPG Waveform Monitoring:&lt;/b&gt;&lt;span&gt; The floating-point &lt;/span&gt;&lt;code data-path-to-node="12,0,0" data-index-in-node="44"&gt;filtered_ir&lt;/code&gt;&lt;span&gt; signal is routed directly into a &lt;/span&gt;Waveform Chart&lt;span&gt;,&lt;/span&gt;&lt;span&gt; providing a continuous,&lt;/span&gt;&lt;span&gt; scrolling historical plot of the photoplethysmogram (PPG) heart pulse wave.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,1,0"&gt;&lt;b data-path-to-node="12,1,0" data-index-in-node="0"&gt;Vital Signs Indicators:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="12,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,1,1,0,0"&gt;&lt;b data-path-to-node="12,1,1,0,0" data-index-in-node="0"&gt;Heart Rate (BPM):&lt;/b&gt;&lt;span&gt; Displayed via numeric indicators or custom gauge meters for immediate numerical feedback.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,1,1,1,0"&gt;&lt;b data-path-to-node="12,1,1,1,0" data-index-in-node="0"&gt;Blood Oxygen Saturation (SpO2):&lt;/b&gt;&lt;span&gt; Configured with a strict numerical range scaled from 0 to &lt;/span&gt;&lt;b data-path-to-node="12,1,1,1,0" data-index-in-node="90"&gt;100&lt;/b&gt;&lt;span&gt; (&lt;/span&gt;&lt;code data-path-to-node="12,1,1,1,0" data-index-in-node="95"&gt;Maximum = 100&lt;/code&gt;&lt;span&gt;) to accurately reflect standard percentage-based clinical boundaries.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PulseOximeter-LabView1.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PulseOximeter-LabView2.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitaRF - Part 9 - Sleep and Fall Detection</title><link>https://community.element14.com/thread/57388?ContentTypeID=0</link><pubDate>Mon, 26 Oct 2026 04:29:02 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:72f9e1c6-f0ec-4f01-a05d-e95e2ed83304</guid><dc:creator>arvindsa</dc:creator><slash:comments>4</slash:comments><comments>https://community.element14.com/thread/57388?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57388/vitarf---part-9---sleep-and-fall-detection/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt; VitaRF is a wireless vitals node (heart rate, SpO₂, temperature) that reports over BLE into Home Assistant, so someone can keep an eye on a loved one. It&amp;#39;s built in three phases: a development-kit bring-up, a custom nRF52832 PCB, and a Matter over Thread proof of concept.&lt;/p&gt;
&lt;p&gt;Past Posts&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57254/vitarf---part-1---the-plan" data-e14adj="t"&gt;VitaRF - Part 1 - The Plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57279/vitarf---part-2---interface-max30102-on-nrf52" data-e14adj="t"&gt;VitaRF - Part 2 - Interface MAX30102 on NRF52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57291/vitarf---part-3---interfacing-max30208-on-nrf52" data-e14adj="t"&gt;VitaRF - Part 3 - Interfacing MAX30208 on NRF52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57293/vitarf---part-4---sending-sensor-data-to-home-assistant-via-ble-on-nrf52" data-e14adj="t"&gt;VitaRF - Part 4 - Sending Sensor Data to Home Assistant via BLE on NRF52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57317/vitarf---part-5---matter-over-thread-on-nrf54l15-with-home-assistant" data-e14adj="t"&gt;VitaRF - Part 5 - Matter over Thread on nRF54L15 with Home Assistant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57331/vitarf---part-6---nrf52-based-heart-rate-temperature-wearable-pcb-for-home-assistant" data-e14adj="t"&gt;VitaRF - Part 6 - An nRF52-Based Heart-Rate &amp;amp; Temperature Wearable PCB for Home Assistant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57337/vitarf---part-7---adding-a-philips-wiz-smart-bulb-to-home-assistant" data-e14adj="t"&gt;VitaRF - Part 7 - Adding a Philips WiZ Smart Bulb to Home Assistant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/p/addpost/TODO-LINK-PART-8" data-e14adj="t"&gt;VitaRF - Part 8 - Assembling the PCB with Stencil, Paste and a Hot Plate&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Heart rate, SpO₂ and temperature tell you about someone&amp;#39;s body. The accelerometer tells you what they are doing. For someone living alone, two questions matter: did they fall, and are they sleeping normally? Both can be answered from the same 50 Hz stream of wrist acceleration.&lt;/p&gt;
&lt;p&gt;This post covers the whole chain: the LIS2DE12 driver, the sleep scoring, the fall detector, how they run together on the node, and what has and hasn&amp;#39;t been validated.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x720/__key/communityserver-discussions-components-files/458/fig_2D00_01_2D00_data_2D00_path.png" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r6k6pu0"&gt;Part A &amp;mdash; The LIS2DE12&lt;/h2&gt;
&lt;h3 id="mcetoc_1k5r6k6pu1"&gt;Wiring&lt;/h3&gt;
&lt;p&gt;The LIS2DE12 is a 2 &amp;times; 2 mm LGA-12 three-axis accelerometer that draws about 6 &amp;micro;A at 50 Hz. It is an 8-bit part. That&amp;#39;s enough for both jobs, as the sleep section shows.&lt;/p&gt;
&lt;p&gt;It sits on the shared I2C bus, which already carries the MAX30208, MAX30102, nPM1300 and DRV2605L. So it needs no extra pins, and 50 Hz &amp;times; 3 bytes is a small load for 400 kHz I2C.&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Connection&lt;/th&gt;
&lt;th&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VDD / VDD_IO&lt;/td&gt;
&lt;td&gt;+3V3 (nPM1300 BUCK2, always on)&lt;/td&gt;
&lt;td&gt;Same rail as the I2C pull-ups, so it can&amp;#39;t be back-powered through the bus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDA / SCL&lt;/td&gt;
&lt;td&gt;Shared I2C bus&lt;/td&gt;
&lt;td&gt;Address &lt;strong&gt;0x19&lt;/strong&gt; (SA0 tied high)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CS&lt;/td&gt;
&lt;td&gt;Tied &lt;strong&gt;high&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Selects I2C mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INT1&lt;/td&gt;
&lt;td&gt;P0.12&lt;/td&gt;
&lt;td&gt;Free-fall engine, push-pull, active high&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INT2&lt;/td&gt;
&lt;td&gt;P0.13&lt;/td&gt;
&lt;td&gt;Motion engine, push-pull, active high&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The chip has two independent interrupt engines, and the two jobs need different logic. Free-fall is an &lt;strong&gt;AND&lt;/strong&gt; of all three axes being near 0 g. Motion, such as rolling over in bed, is an &lt;strong&gt;OR&lt;/strong&gt; of any axis passing a threshold. Each engine gets its own pin.&lt;/p&gt;
&lt;p&gt;TODO-PHOTO: close-up of U2 (LIS2DE12) on the assembled board&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6k6pu2"&gt;Driver init&lt;/h3&gt;
&lt;p&gt;The driver (&lt;code&gt;firmware/lib/lis2de12.c&lt;/code&gt;, nRF5 SDK 17.1.0) checks &lt;code&gt;WHO_AM_I&lt;/code&gt; and then writes every control register explicitly, rather than trusting reset values. A warm re-init always lands in the same state:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;bool lis2de12_init(lis2de12_odr_t odr, lis2de12_fs_t fs)
{
    uint8_t id;
    if (rd(REG_WHO_AM_I, &amp;amp;id) != NRF_SUCCESS || id != WHO_AM_I_VALUE)   /* 0x33 */
    {
        return false;
    }
    ...
    if (wr(REG_CTRL1, CTRL1_LPEN | CTRL1_XYZ_EN) != NRF_SUCCESS || /* ODR = power-down */
        wr(REG_CTRL2, 0x00) != NRF_SUCCESS ||                       /* high-pass off everywhere */
        wr(REG_CTRL3, 0x00) != NRF_SUCCESS ||                       /* INT1 pin: nothing routed */
        wr(REG_CTRL4, (uint8_t)(CTRL4_BDU | ((uint8_t)fs &amp;lt;&amp;lt; 4))) != NRF_SUCCESS ||
        wr(REG_CTRL5, CTRL5_LIR_INT1 | CTRL5_LIR_INT2) != NRF_SUCCESS || /* latched */
        wr(REG_CTRL6, 0x00) != NRF_SUCCESS ||                       /* INT2 pin: nothing routed, active-high */
        wr(REG_FIFO_CTRL, 0x00) != NRF_SUCCESS ||                   /* FIFO bypass */
        ...)
    {
        return false;
    }
    return lis2de12_set_odr(odr) == NRF_SUCCESS;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;A few datasheet points the driver depends on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CTRL_REG1.LPen&lt;/code&gt; must be &lt;strong&gt;1&lt;/strong&gt; for correct operation, even though this part has no low-power/high-resolution split.&lt;/li&gt;
&lt;li&gt;The output steps (15.6 / 31.2 / 62.5 mg per LSB) and the interrupt threshold steps (16 / 32 / 62 / 186 mg) are different numbers, so the driver converts thresholds with its own table.&lt;/li&gt;
&lt;li&gt;Boot completes within 5 ms of power-up, so the BOOT bit isn&amp;#39;t needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5r6lecb3"&gt;Reading samples&lt;/h3&gt;
&lt;p&gt;The data is 8-bit, but the register map keeps the 16-bit layout of the bigger parts. A six-byte burst from 0x28 returns X, Y and Z, with the value in the odd bytes (&lt;code&gt;OUT_X_H&lt;/code&gt;, &lt;code&gt;OUT_Y_H&lt;/code&gt;, &lt;code&gt;OUT_Z_H&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;ret_code_t lis2de12_read_raw(lis2de12_raw_t *out)
{
    uint8_t buf[6];
    TRY(i2c_bus_read_reg(s_dev, REG_FIFO_READ | AUTO_INC, buf, sizeof(buf)));
    out-&amp;gt;x = (int8_t)buf[1];
    out-&amp;gt;y = (int8_t)buf[3];
    out-&amp;gt;z = (int8_t)buf[5];
    return NRF_SUCCESS;
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6ma244"&gt;The FIFO&lt;/h3&gt;
&lt;p&gt;Waking the CPU 50 times a second to read 3 bytes would waste power. The LIS2DE12 has a 32-sample FIFO. In stream mode it keeps the newest 32 samples, which at 50 Hz is 640 ms of history. The node reads it every &lt;strong&gt;400 ms&lt;/strong&gt; in one I2C burst of up to 192 bytes.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;FIFO_SRC&lt;/code&gt; count field is one less than the number of unread samples. So 31 means 32 are stored, and EMPTY clear with a count of 0 means one sample is waiting. The driver handles it like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/* FSS is one less than the number of unread sample sets (31 when full,
 * 32 stored; 0 with EMPTY clear when exactly one is waiting). EMPTY says
 * there is nothing at all. */
uint8_t n = (src &amp;amp; FIFO_SRC_EMPTY) ? 0 : (uint8_t)((src &amp;amp; FIFO_SRC_FSS_MASK) + 1);
...
uint8_t raw[FIFO_DEPTH * 6];
TRY(i2c_bus_read_reg(s_dev, REG_FIFO_READ | AUTO_INC, raw, (uint8_t)(n * 6)));
for (uint8_t i = 0; i &amp;lt; n; i++)
{
    buf[i].x = (int8_t)raw[i * 6 + 1];
    buf[i].y = (int8_t)raw[i * 6 + 3];
    buf[i].z = (int8_t)raw[i * 6 + 5];
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;On the board, the FIFO gives 15 samples after 300 ms, a full 32 with the overrun flag after one second, and no loss when read every 400 ms.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6n3sm5"&gt;Interrupts&lt;/h3&gt;
&lt;p&gt;Both interrupt engines run in latched mode. The pin stays high until the matching &lt;code&gt;INTx_SRC&lt;/code&gt; register is read, so an event can&amp;#39;t be lost while the CPU is busy. The GPIOTE handler only sets a flag. All I2C traffic happens later, in normal context:&amp;#39;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    if (pin == s_pin1) __atomic_fetch_or(&amp;amp;s_flags, FLAG_INT1, __ATOMIC_ACQ_REL);
    if (pin == s_pin2) __atomic_fetch_or(&amp;amp;s_flags, FLAG_INT2, __ATOMIC_ACQ_REL);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;A latched pin that is already high at start-up gives no further edge, so &lt;code&gt;lis2de12_irq_init()&lt;/code&gt; also reads the pin level once when the driver starts.&lt;/p&gt;
&lt;p&gt;Two details matter for the thresholds. The high-pass motion flag (ZH) compares the absolute value, so it catches movement in both directions. And &lt;code&gt;INTx_SRC&lt;/code&gt; reports flags for every axis, whether or not that axis is enabled, so the driver masks them with &lt;code&gt;INTx_CFG&lt;/code&gt; before acting.&lt;/p&gt;
&lt;p&gt;The node&amp;#39;s boot test uses the chip&amp;#39;s built-in self-test, which applies a test force and checks the output shift against the datasheet window. The hardware free-fall interrupt (350 mg, 30 ms) is also configured.&lt;/p&gt;
&lt;p&gt;For now the firmware drains the FIFO on a 400 ms timer and runs both algorithms in software. The interrupt pins are wired and supported by the driver. Using INT1 and INT2 to wake the MCU from deeper sleep is the next power optimisation.&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r6nvv26"&gt;Part B &amp;mdash; Sleep quality&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:800px;max-width:400px;"  src="https://community.element14.com/resized-image/__size/800x1600/__key/communityserver-discussions-components-files/458/fig_2D00_02_2D00_sleep_2D00_pipeline.png" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6p8kr7"&gt;The approach&lt;/h3&gt;
&lt;p&gt;Sleep tracking from a wrist sensor is called actigraphy, and sleep researchers have used it since the 1990s. Commercial watches add heart rate and proprietary models to stage light, deep and REM sleep. I used the published and Open route:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;raw acceleration &amp;rarr; activity counts &amp;rarr; sleep/wake per minute &amp;rarr; night summary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every step has a published method and a reference implementation to test against. It tells sleep from wake, not sleep stages. For a caregiver, &amp;quot;slept about seven hours, woke up three times&amp;quot; is the useful part.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6p8kr8"&gt;Step 1 &amp;mdash; Activity counts&lt;/h3&gt;
&lt;p&gt;Sleep-scoring algorithms were designed on ActiGraph &amp;quot;activity counts&amp;quot;, a per-minute number that ActiGraph devices have produced for decades. Their thresholds only mean something on those numbers. In 2022 ActiGraph published the counting algorithm (Neishabouri et al., &lt;em&gt;Scientific Reports&lt;/em&gt; 12:11958). Per axis, the pipeline is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Resample to 30 Hz. The LIS2DE12 runs at 50 Hz, so the signal is upsampled by 3, low-pass filtered, and every fifth sample kept.&lt;/li&gt;
&lt;li&gt;A fixed 0.29&amp;ndash;1.63 Hz IIR band-pass. This keeps human movement and removes gravity and vibration.&lt;/li&gt;
&lt;li&gt;Scale, then a dead-band (anything below 4 becomes 0) and a clip at 128.&lt;/li&gt;
&lt;li&gt;Average groups of three (30 Hz &amp;rarr; 10 Hz) and sum over the minute.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The code is a streaming C library (&lt;code&gt;firmware/lib/actcounts.c&lt;/code&gt;). It keeps only the filter state, so memory use stays fixed however long it runs. The core is the band-pass:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/* Band-pass filter, published constants (Neishabouri et al. 2022). The
 * filter is specified at 30 Hz; everything is resampled to 30 Hz first. */
static const actcounts_real_t k_b[8] = {
    -0.009341062898525, -0.025470289659360, -0.004235264826105,  0.044152415456420,
     0.036493718347760, -0.011893961934740, -0.022917390623150, -0.006788163862310,
};
/* Feedback taps a1..a7 (a0 = 1). */
static const actcounts_real_t k_a[7] = {
    -3.63367395910957, 5.03689812757486, -3.09612247819666, 0.50620507633883,
     0.32421701566682, -0.15685485875559, 0.01949130205890,
};&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;followed by the dead-band and clip:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;actcounts_real_t v = fabs(bpf_step(ac, x) * GAIN);
if (v &amp;gt; CLIP)          v = CLIP;      /* 128 */
else if (v &amp;lt; DEADBAND) v = 0.0;       /* 4 */
else                   v = floor(v);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Checking against ActiGraph.&lt;/strong&gt; ActiGraph&amp;#39;s reference repository includes recordings with the counts its ActiLife software produced for them. I ran the C code on those recordings and compared it epoch by epoch:&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;30 Hz and 40 Hz recordings, 3 axes, 3000 epochs each&lt;/td&gt;
&lt;td&gt;Exact, except one epoch per recording, off by 1 count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50 Hz path (the node&amp;#39;s rate; no reference data at 50 Hz) vs. a transcription of the reference&lt;/td&gt;
&lt;td&gt;299 of 300 epochs exact, one off by 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The off-by-one cases come from floating-point summation order on a rounding boundary. The filter runs in &lt;code&gt;double&lt;/code&gt;. In single precision about 40 % of epochs differed from ActiLife, by up to 5 counts, because IIR filters with poles this close to the unit circle are sensitive to precision. The nRF52832 FPU is single-precision, so &lt;code&gt;double&lt;/code&gt; runs in software. At 50 samples per second per axis, the cost is estimated at about 0.2 % of CPU. That estimate isn&amp;#39;t measured yet.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6qond9"&gt;Why 8 bits is enough&lt;/h3&gt;
&lt;p&gt;ActiGraph devices use a 12-bit accelerometer. The LIS2DE12 has 31 mg per step at &amp;plusmn;4 g. To check whether that coarseness matters, I fed a 1 Hz sine of different amplitudes through the counts algorithm at each resolution (counts per minute):&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Movement amplitude&lt;/th&gt;
&lt;th&gt;Ideal sensor&lt;/th&gt;
&lt;th&gt;&amp;plusmn;2 g (15.6 mg/LSB)&lt;/th&gt;
&lt;th&gt;&amp;plusmn;4 g (31.2 mg/LSB)&lt;/th&gt;
&lt;th&gt;&amp;plusmn;8 g (62.5 mg/LSB)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;50 mg&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75 mg&lt;/td&gt;
&lt;td&gt;360&lt;/td&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100 mg&lt;/td&gt;
&lt;td&gt;1200&lt;/td&gt;
&lt;td&gt;1200&lt;/td&gt;
&lt;td&gt;1140&lt;/td&gt;
&lt;td&gt;1440&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;200 mg&lt;/td&gt;
&lt;td&gt;3720&lt;/td&gt;
&lt;td&gt;3720&lt;/td&gt;
&lt;td&gt;3600&lt;/td&gt;
&lt;td&gt;3600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400 mg&lt;/td&gt;
&lt;td&gt;8160&lt;/td&gt;
&lt;td&gt;8160&lt;/td&gt;
&lt;td&gt;8160&lt;/td&gt;
&lt;td&gt;7920&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The counts algorithm already reports zero for movements below about 60&amp;ndash;75 mg, even with a perfect sensor. The LIS2DE12&amp;#39;s step size sits at that same floor, so the resolution costs little for sleep. One range, &amp;plusmn;4 g, serves both sleep and falls. Falls need headroom above 2 g for the impact, and there&amp;#39;s no need to switch ranges.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6qonda"&gt;Step 2 &amp;mdash; Sleep or wake, minute by minute&lt;/h3&gt;
&lt;p&gt;Scoring uses &lt;strong&gt;Cole&amp;ndash;Kripke&lt;/strong&gt; (Cole et al., &lt;em&gt;Sleep&lt;/em&gt; 15(5), 1992). It looks at a 7-minute window around each minute and takes a weighted sum of the activity:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;SI = 0.001 &amp;#215; (106&amp;#183;A₋₄ + 54&amp;#183;A₋₃ + 58&amp;#183;A₋₂ + 76&amp;#183;A₋₁ + 230&amp;#183;A₀ + 74&amp;#183;A₊₁ + 67&amp;#183;A₊₂)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Here A is the minute&amp;#39;s count &amp;divide; 100, capped at 300. A minute is **asleep if SI &amp;lt; 1**. The current minute carries the most weight, and the minutes before it count more than the ones after.&lt;/p&gt;
&lt;p&gt;I chose Cole&amp;ndash;Kripke over Sadeh for three reasons. It was developed on wrist actigraphy in adults, which is this use case. It&amp;#39;s a fixed seven-tap filter that is cheap and easy to check by hand. And there&amp;#39;s a clear open-source reference (the `actigraph.sleepr` R package) to compare against.&lt;/p&gt;
&lt;p&gt;On the MCU the comparison needs no floating point. Multiply both sides by 100 000, and it becomes integer arithmetic:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/* Counts are divided by 100 and capped at 300, i.e. capped at 30000 before the
 * (exact) division. SI &amp;lt; 1  &amp;lt;=&amp;gt;  sum(w * min(c, 30000)) &amp;lt; 100000. */
static const uint16_t k_ck_weight[7] = { 106, 54, 58, 76, 230, 74, 67 };

bool sleepq_cole_kripke_asleep(const uint16_t *counts, uint16_t n, uint16_t i)
{
    uint32_t sum = 0;
    for (int8_t k = 0; k &amp;lt; 7; k++)
    {
        int32_t idx = (int32_t)i - 4 + k;
        if (idx &amp;lt; 0 || idx &amp;gt;= (int32_t)n)
        {
            continue; /* zero padding */
        }
        uint32_t c = counts[idx];
        if (c &amp;gt; 30000UL)
        {
            c = 30000UL;
        }
        sum += (uint32_t)k_ck_weight[k] * c;
    }
    return sum &amp;lt; 100000UL;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Against the published formula in floating point, on 15 000 random minutes, the integer version gives identical results.&lt;/p&gt;
&lt;p&gt;Each minute needs the two minutes after it, so the live sleep/wake decision trails real time by two minutes. For sleep, that doesn&amp;#39;t matter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which axis?&lt;/strong&gt; ActiGraph scores the axis along the forearm. How the node sits on the wrist depends on the strap and the person, so the node uses the &lt;strong&gt;vector magnitude&lt;/strong&gt; of the three per-axis counts. It doesn&amp;#39;t depend on orientation, but it reads slightly higher than one axis, so it leans a little towards scoring wake.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6sf27b"&gt;Step 3 &amp;mdash; The night summary&lt;/h3&gt;
&lt;p&gt;Per-minute sleep/wake is noisy on its own, so the night summary turns a bed-time window into the standard actigraphy numbers:&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time in bed&lt;/td&gt;
&lt;td&gt;Bed mark &amp;rarr; up mark&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sleep onset latency&lt;/td&gt;
&lt;td&gt;Bed &amp;rarr; the first run of 10 consecutive sleep minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total sleep time&lt;/td&gt;
&lt;td&gt;Sleep minutes between onset and the final awakening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WASO&lt;/td&gt;
&lt;td&gt;&amp;quot;Wake after sleep onset&amp;quot;: awake minutes between onset and final awakening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Awakenings&lt;/td&gt;
&lt;td&gt;Wake runs of 5 minutes or longer after onset&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sleep efficiency&lt;/td&gt;
&lt;td&gt;Total sleep &amp;divide; time in bed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The 10- and 5-minute run lengths are compile-time constants in &lt;code&gt;sleepq.h&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How does the node know when you went to bed?&lt;/strong&gt; It doesn&amp;#39;t, and the algorithm can&amp;#39;t reliably tell either. Lying on the sofa watching TV looks like sleep to an accelerometer. So the wearer marks it. A &lt;strong&gt;double press&lt;/strong&gt; on the button marks bed time, and the LED flashes cyan. The next double press marks getting up. That press scores the remaining minutes, builds the summary, writes it to the flash log, and sends the sleep minutes to Home Assistant.&lt;/p&gt;
&lt;p&gt;The pipeline runs all the time. Home Assistant also receives a live activity count and an asleep/awake flag every minute. The node keeps 12 hours of minutes: 720 &amp;times; 2 bytes of counts, plus one bit per minute for the decision, about 1.5 KB. If the buffer fills during the day it starts over. At bed time it starts fresh if less than 10 hours of room is left, so a night never runs out of space.&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r6sf27c"&gt;Part C &amp;mdash; Fall detection&lt;/h2&gt;
&lt;h3 id="mcetoc_1k5r6sf27d"&gt;The approach&lt;/h3&gt;
&lt;p&gt;A fall seen from an accelerometer has a typical shape, and most fall-detection work (Bourke et al. 2007, Kangas et al. 2008, the SisFall dataset by Sucerquia et al. 2017) uses a version of it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Free-fall:&lt;/strong&gt; while the body drops, the sensor reads less than 1 g.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact:&lt;/strong&gt; a sharp spike when the body hits the floor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aftermath:&lt;/strong&gt; the person lies still.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Everything is measured on the &lt;strong&gt;signal vector magnitude&lt;/strong&gt;, SVM = &amp;radic;(x&amp;sup2; + y&amp;sup2; + z&amp;sup2;), which reads about 1000 mg at rest in any orientation. I used a threshold detector rather than a trained classifier. It fits in a few hundred bytes, every decision can be explained, and its failure modes are known. A classifier would need a labelled set of wrist falls, which doesn&amp;#39;t exist yet.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x720/__key/communityserver-discussions-components-files/458/fig_2D00_03_2D00_fall_2D00_state_2D00_machine.png" /&gt;&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free-fall threshold&lt;/td&gt;
&lt;td&gt;SVM &amp;lt; &lt;strong&gt;400 mg&lt;/strong&gt; for &amp;ge; 60 ms&lt;/td&gt;
&lt;td&gt;Set for the wrist (see below)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Impact&lt;/td&gt;
&lt;td&gt;SVM &amp;ge; &lt;strong&gt;2000 mg&lt;/strong&gt; within 1 s of the free-fall ending&lt;/td&gt;
&lt;td&gt;Above what ordinary arm movement reaches without a free-fall before it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Settle&lt;/td&gt;
&lt;td&gt;1 s ignored after the impact&lt;/td&gt;
&lt;td&gt;Bounces and rolling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stillness&lt;/td&gt;
&lt;td&gt;&amp;ge; 90 % of the next 3 s within &amp;plusmn;250 mg of 1 g&lt;/td&gt;
&lt;td&gt;The person is lying down, not walking away&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orientation change&lt;/td&gt;
&lt;td&gt;Off (optional, e.g. &amp;ge; 30&amp;deg;)&lt;/td&gt;
&lt;td&gt;Can reject jumps, at the cost of missing some falls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cooldown&lt;/td&gt;
&lt;td&gt;10 s after a confirmed fall&lt;/td&gt;
&lt;td&gt;One fall, one alert&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The detector is O(1) per sample and uses integer arithmetic (an integer square root for SVM). Every threshold lives in a &lt;code&gt;fall_cfg_t&lt;/code&gt; struct, so it can be tuned without touching the logic. Free-fall is tracked in every state, so the record of the last free-fall is current when an impact arrives:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;fall_event_t fall_detect_feed(fall_detect_t *fd, int16_t x_mg, int16_t y_mg, int16_t z_mg)
{
    const int32_t v[3] = { x_mg, y_mg, z_mg };
    const uint32_t sq  = (uint32_t)(v[0] * v[0]) + (uint32_t)(v[1] * v[1]) + (uint32_t)(v[2] * v[2]);
    const uint16_t svm = fall_detect_isqrt(sq);
    ...
    /* Free-fall tracking runs in every state, so the memory is fresh when an impact arrives. */
    if (svm &amp;lt; fd-&amp;gt;cfg.freefall_mg)
    {
        ...
        fd-&amp;gt;ff_run++;
    }
    else
    {
        if (fd-&amp;gt;ff_run &amp;gt;= fd-&amp;gt;ff_min_n)
        {
            fd-&amp;gt;ff_last_len  = fd-&amp;gt;ff_run;
            fd-&amp;gt;since_ff_end = 0;
        }
        ...
        fd-&amp;gt;ff_run = 0;
    }

    switch (fd-&amp;gt;state)
    {
        case FD_IDLE:
            if (svm &amp;gt;= fd-&amp;gt;cfg.impact_mg)
            {
                bool had_freefall = fd-&amp;gt;ff_last_len != 0 &amp;amp;&amp;amp; fd-&amp;gt;since_ff_end &amp;lt;= fd-&amp;gt;lookback_n;
                if (!fd-&amp;gt;cfg.require_freefall || had_freefall)
                {
                    ...
                    fd-&amp;gt;ff_last_len = 0; /* one free-fall can explain only one impact */
                    fd-&amp;gt;state = FD_SETTLE;
                    return FALL_EVENT_CANDIDATE;
                }
            }
            break;
        ...&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6ut6ae"&gt;Why 400 mg on the wrist&lt;/h3&gt;
&lt;p&gt;Most published fall thresholds come from sensors worn on the waist or chest. On the wrist, arm swing alone pulls SVM down to about 0.4&amp;ndash;0.6 g at the end of each swing. A 600 mg free-fall threshold fires on ordinary walking, so the threshold is set to 400 mg. The chip&amp;#39;s hardware free-fall at 350 mg is a sensible gate for the same reason.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6ut6af"&gt;Test results&lt;/h3&gt;
&lt;p&gt;The host tests (&lt;code&gt;firmware/tests/test_fall_detect.c&lt;/code&gt;) run synthetic 50 Hz traces through the detector on the PC:&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fall: 400 ms free-fall, 3.3 g impact, lying still&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Confirmed&lt;/strong&gt;, 400 ms free-fall, 3.27 g peak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same, with the orientation check on (&amp;ge; 30&amp;deg;)&lt;/td&gt;
&lt;td&gt;Confirmed, 80&amp;deg; change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fall, then vigorous movement&lt;/td&gt;
&lt;td&gt;Rejected (the stillness check costs some real falls)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60 s of walking with 2.3 g heel strikes&lt;/td&gt;
&lt;td&gt;No candidate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sitting down hard (2.6 g), then still&lt;/td&gt;
&lt;td&gt;Ignored. Becomes a false alarm if free-fall isn&amp;#39;t required, which is why it&amp;#39;s on by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Table slam with continued arm movement&lt;/td&gt;
&lt;td&gt;Ignored&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jump on the spot, then standing still&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;False alarm&lt;/strong&gt; with defaults; rejected with the orientation check on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40 ms free-fall before a hard impact&lt;/td&gt;
&lt;td&gt;Ignored (too short)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two falls 5 s apart&lt;/td&gt;
&lt;td&gt;Only the first reported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The 72-hour run below also feeds every sample through the fall detector. It raised &lt;strong&gt;no candidates&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r6ut6ag"&gt;After a confirmed fall&lt;/h3&gt;
&lt;p&gt;A wrist-worn fall detector will produce some false alarms, so nothing goes to Home Assistant until the wearer has had a chance to cancel:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x720/__key/communityserver-discussions-components-files/458/fig_2D00_04_2D00_fall_2D00_alert_2D00_flow.png" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;15 s countdown:&lt;/strong&gt; the red LED blinks, the DRV2605L haptic motor buzzes and the piezo beeps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One press of SW1&lt;/strong&gt; cancels it. A &amp;quot;fall cancelled&amp;quot; record goes to the log.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Otherwise the alert latches:&lt;/strong&gt; the BTHome &lt;em&gt;Problem&lt;/em&gt; binary sensor turns on, and adverts speed up to every 100 ms for 30 s so Home Assistant sees it quickly. A &amp;quot;fall&amp;quot; record goes to flash with the peak g, the free-fall length and the stillness percentage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Another press of SW1&lt;/strong&gt; clears it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Home Assistant turns the alert into light. The automation below switches the bedroom WiZ bulb to full cool white when the Problem sensor turns on, and back to dim warm yellow when it clears:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x900/__key/communityserver-discussions-components-files/458/fig_2D00_05_2D00_ha_2D00_fall_2D00_alert_2D00_automation.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/20261026_5F00_005149.mp4"&gt;community.element14.com/.../20261026_5F00_005149.mp4&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r728tah"&gt;Running both on the node&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;app_motion.c&lt;/code&gt; ties it together. Every 400 ms it drains the FIFO, converts the samples to mg, and feeds each one to both detectors:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void app_motion_service(void)
{
    lis2de12_raw_t raw[FIFO_MAX];
    uint8_t count = 0;
    bool overrun = false;
    if (lis2de12_fifo_read(raw, FIFO_MAX, &amp;amp;count, &amp;amp;overrun) != NRF_SUCCESS)
    {
        return;
    }
    for (uint8_t i = 0; i &amp;lt; count; i++)
    {
        lis2de12_mg_t mg;
        lis2de12_raw_to_mg(&amp;amp;raw[i], &amp;amp;mg);
        feed(&amp;amp;mg);
    }
}

static void feed(const lis2de12_mg_t *mg)
{
    fall_event_t fe = fall_detect_feed(&amp;amp;s_fall, mg-&amp;gt;x, mg-&amp;gt;y, mg-&amp;gt;z);
    if (fe == FALL_EVENT_CONFIRMED &amp;amp;&amp;amp; s_countdown_ticks == 0 &amp;amp;&amp;amp; !g_app.fall_alert)
    {
        start_countdown();
    }

    if (!sleepq_feed(&amp;amp;s_sleep, mg-&amp;gt;x, mg-&amp;gt;y, mg-&amp;gt;z))
    {
        return;
    }

    /* A minute closed. */
    uint16_t n = sleepq_epoch_count(&amp;amp;s_sleep);
    g_app.activity = sleepq_epoch_activity(&amp;amp;s_sleep, (uint16_t)(n - 1));
    uint16_t scored = sleepq_scored_count(&amp;amp;s_sleep);
    if (scored &amp;gt; s_reported)
    {
        g_app.asleep = sleepq_epoch_is_asleep(&amp;amp;s_sleep, (uint16_t)(scored - 1));
        s_reported   = scored;
    }
    app_ble_update();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The button goes through the nPM1300&amp;#39;s SHPHLD pin. A single press cancels or clears a fall alert. A double press marks bed time or getting up.&lt;/p&gt;
&lt;p&gt;In Home Assistant everything arrives over BTHome v2:&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;BTHome object&lt;/th&gt;
&lt;th&gt;Shows in HA as&lt;/th&gt;
&lt;th&gt;Is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0x26 Problem&lt;/td&gt;
&lt;td&gt;Binary sensor&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fall alert&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x3D Count (1st)&lt;/td&gt;
&lt;td&gt;Count&lt;/td&gt;
&lt;td&gt;Activity count, last minute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x0F Generic binary&lt;/td&gt;
&lt;td&gt;Binary sensor&lt;/td&gt;
&lt;td&gt;Asleep (last scored minute)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x3D Count (2nd)&lt;/td&gt;
&lt;td&gt;Count&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;Sleep minutes, last nigh&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/fig_2D00_06_2D00_ha_2D00_node_2D00_entities.png" /&gt;&lt;/p&gt;
&lt;p&gt;Home Assistant labels the SpO₂ value as Humidity. BTHome has no SpO₂ type, so the node sends SpO₂ as a percentage in the humidity object.&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r74pe9i"&gt;The 72-hour run&lt;/h2&gt;
&lt;p&gt;To see how the sleep and fall code behaves over several days, I ran 72 hours of wrist data through the same logic the firmware uses. It is 50 Hz wrist acceleration from the LIS2DE12 at &amp;plusmn;4 g, covering an ordinary routine: walking, desk work, meals, an evening on the sofa, bed at 23:00, and a few posture changes and twitches through the night. The data passes through the same code and the same bed and up logic as the firmware, fall detector included.&lt;/p&gt;
&lt;p&gt;This time I had a very special guest who helped me track the signals. My Grandmother who is the old schools and believes good sleep is essential for health.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x900/__key/communityserver-discussions-components-files/458/fig_2D00_07_2D00_three_2D00_day_2D00_run.png" /&gt;&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Night&lt;/th&gt;
&lt;th&gt;In bed&lt;/th&gt;
&lt;th&gt;Asleep&lt;/th&gt;
&lt;th&gt;Efficiency&lt;/th&gt;
&lt;th&gt;Fell asleep after&lt;/th&gt;
&lt;th&gt;WASO&lt;/th&gt;
&lt;th&gt;Awakenings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;480 min&lt;/td&gt;
&lt;td&gt;468 min&lt;/td&gt;
&lt;td&gt;97 %&lt;/td&gt;
&lt;td&gt;9 min&lt;/td&gt;
&lt;td&gt;3 min&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;480 min&lt;/td&gt;
&lt;td&gt;465 min&lt;/td&gt;
&lt;td&gt;96 %&lt;/td&gt;
&lt;td&gt;11 min&lt;/td&gt;
&lt;td&gt;4 min&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;480 min&lt;/td&gt;
&lt;td&gt;464 min&lt;/td&gt;
&lt;td&gt;96 %&lt;/td&gt;
&lt;td&gt;7 min&lt;/td&gt;
&lt;td&gt;2 min&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;Time in bed was between 420 and 480 minutes across the three nights. To compare the nights in minutes rather than percentages, the table scales each night to a 480-minute window. Onset latency is 7&amp;ndash;11 minutes. The night-time posture changes show as spikes, and Cole&amp;ndash;Kripke rides through them, as designed. The fall detector raised no candidates in the 72 hours.&lt;/p&gt;
&lt;p&gt;The chart also shows the main limitation. From about 20:15 the evening on the sofa scores as asleep, and so do scattered quiet minutes at the desk: 502 of the 2868 daytime minutes. Cole&amp;ndash;Kripke measures stillness, not sleep. That&amp;#39;s why the night summary only uses the window between the two button presses, and why the live asleep flag shouldn&amp;#39;t be trusted on its own during the day.&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r775oej"&gt;Limits and next steps&lt;/h2&gt;
&lt;p&gt;These are the parts not yet validated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sleep:&lt;/strong&gt; the algorithm is good at detecting sleep and weaker at detecting quiet wakefulness. Lying awake still will count as sleep, so expect it to overestimate sleep somewhat.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Falls:&lt;/strong&gt; the thresholds come from the literature and the wrist adjustments above. They haven&amp;#39;t been tuned on real falls with a person. The known weak spots are a jump followed by standing still, which looks like a fall, and a faller who gets up straight away, which is missed by the stillness check. The next step is labelled falls onto a mat, plus a day of ordinary wear, to tune on.&lt;/li&gt;
&lt;li&gt;The cancel countdown exists because of these limits. The alert should not be connected to an emergency service without it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1k5r775oek"&gt;Final notes&lt;/h2&gt;
&lt;p&gt;The LIS2DE12 does both jobs from one 50 Hz stream. The sleep counts follow ActiGraph&amp;#39;s published method and match its reference data. Sleep scoring runs in integer arithmetic on the MCU. The fall detector runs on a 400 mg free-fall threshold, tuned for the wrist. Every fall goes through a 15 s countdown before anyone is told.&lt;/p&gt;
&lt;p&gt;All the code is in the repository: the driver in &lt;code&gt;firmware/lib/lis2de12.[ch]&lt;/code&gt;, the algorithms in &lt;code&gt;firmware/lib/actcounts.[ch]&lt;/code&gt;, &lt;code&gt;sleepq.[ch]&lt;/code&gt; and &lt;code&gt;fall_detect.[ch]&lt;/code&gt;, the node integration in &lt;code&gt;firmware/vitarf_node/app_motion.c&lt;/code&gt;, and the host tests and the 72-hour run in &lt;code&gt;firmware/tests&lt;/code&gt; (&lt;code&gt;make test&lt;/code&gt;, &lt;code&gt;make three-day&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Repo Link:&amp;nbsp;&lt;a href="https://gitlab.com/arvindsa/vitarf-e14" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://gitlab.com/arvindsa/vitarf-e14&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r77pmll"&gt;Thank You&lt;/h2&gt;
&lt;p&gt;A Huge thank you for my Grandma for assisting with data collection and a Huge thanks to my Friend Ayush Who helped me with coding in of the Aceelerometer &amp;amp; Sleep Algorithms,&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neishabouri A. et al., &amp;quot;Quantification of acceleration as activity counts in ActiGraph wearable&amp;quot;, &lt;em&gt;Scientific Reports&lt;/em&gt; 12, 11958 (2022). &lt;a class="url" href="https://doi.org/10.1038/s41598-022-16003-x" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://doi.org/10.1038/s41598-022-16003-x&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cole R.J., Kripke D.F., Gruen W., Mullaney D.J., Gillin J.C., &amp;quot;Automatic sleep/wake identification from wrist activity&amp;quot;, &lt;em&gt;Sleep&lt;/em&gt; 15(5):461&amp;ndash;469 (1992)&lt;/li&gt;
&lt;li&gt;Bourke A.K., O&amp;#39;Brien J.V., Lyons G.M., &amp;quot;Evaluation of a threshold-based tri-axial accelerometer fall detection algorithm&amp;quot;, &lt;em&gt;Gait &amp;amp; Posture&lt;/em&gt; 26(2):194&amp;ndash;199 (2007)&lt;/li&gt;
&lt;li&gt;Kangas M. et al., &amp;quot;Comparison of low-complexity fall detection algorithms for body attached accelerometers&amp;quot;, &lt;em&gt;Gait &amp;amp; Posture&lt;/em&gt; 28(2):285&amp;ndash;291 (2008)&lt;/li&gt;
&lt;li&gt;Sucerquia A., L&amp;oacute;pez J.D., Vargas-Bonilla J.F., &amp;quot;SisFall: A Fall and Movement Dataset&amp;quot;, &lt;em&gt;Sensors&lt;/em&gt; 17(1):198 (2017)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;actigraph/agcounts&lt;/code&gt; (reference counts implementation) and the &lt;code&gt;actigraph.sleepr&lt;/code&gt; R package (Cole&amp;ndash;Kripke reference)&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt</title><link>https://community.element14.com/thread/57386?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 23:26:38 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:d36b2af3-dcd4-4171-8886-f2913eb68dae</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57386?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p data-path-to-node="2"&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="2"&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id="p-rc_496d65b345f9f6f1-136" data-path-to-node="2"&gt;&lt;span class="" data-path-to-node="2,0"&gt;In this comprehensive blog post, we will explore how to design and implement a robust, multi-threaded cross-platform desktop application using &lt;b data-path-to-node="2,0" data-index-in-node="143"&gt;C++&lt;/b&gt; and &lt;b data-path-to-node="2,0" data-index-in-node="151"&gt;Qt 6&lt;/b&gt;. This application manages &lt;b data-path-to-node="2,0" data-index-in-node="182"&gt;two independent serial ports simultaneously&lt;/b&gt;, parses real-time JSON payloads, implements the authentic MAX30208 command-line protocol&lt;/span&gt;&lt;span class="" data-path-to-node="2,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="2,2"&gt;, and renders responsive, live multi-parameter charts.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="2"&gt;&lt;span data-path-to-node="2,2"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/DualSensor-GUI-1.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="2"&gt;&lt;span data-path-to-node="2,2"&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/DualSensor-GUI.mp4"&gt;community.element14.com/.../DualSensor-GUI.mp4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="1"&gt;&lt;span&gt; A prime example of this engineering feat is a robust,&lt;/span&gt;&lt;span&gt; cross-platform desktop application developed in C++ and Qt 6 designed to simultaneously monitor,&lt;/span&gt;&lt;span&gt; parse,&lt;/span&gt;&lt;span&gt; and visualize telemetry data from two independent hardware sensor modules over separate serial ports.&lt;/span&gt;&lt;/p&gt;
&lt;p id="p-rc_72d725c80407277b-129" data-path-to-node="2"&gt;&lt;span class="" data-path-to-node="2,0"&gt;At the core of this system lies a sophisticated &lt;b data-path-to-node="2,0" data-index-in-node="48"&gt;Dual-Port Asynchronous Architecture&lt;/b&gt;. The STM32 / MAXREFDES117 stream operates asynchronously on the main GUI thread via &lt;code data-path-to-node="2,0" data-index-in-node="168"&gt;QSerialPort::readyRead&lt;/code&gt;, continuously capturing and parsing high-frequency JSON packets containing Heart Rate (&lt;code data-path-to-node="2,0" data-index-in-node="278"&gt;bpm&lt;/code&gt;), Blood Oxygen (&lt;code data-path-to-node="2,0" data-index-in-node="298"&gt;spo2&lt;/code&gt;), and Filtered Infrared (&lt;code data-path-to-node="2,0" data-index-in-node="328"&gt;filtered_ir&lt;/code&gt;) signals. In parallel, the MAX30208EVSYS protocol link is managed inside a dedicated background &lt;code data-path-to-node="2,0" data-index-in-node="436"&gt;QThread&lt;/code&gt; using a thread-safe &lt;code data-path-to-node="2,0" data-index-in-node="464"&gt;SerialWorker&lt;/code&gt; class&lt;/span&gt;&lt;span class="" data-path-to-node="2,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,2"&gt;. This module communicates via a command-based protocol (&lt;code data-path-to-node="2,2" data-index-in-node="57"&gt;s&lt;/code&gt;, &lt;code data-path-to-node="2,2" data-index-in-node="60"&gt;t&lt;/code&gt;, &lt;code data-path-to-node="2,2" data-index-in-node="63"&gt;r&lt;/code&gt;, &lt;code data-path-to-node="2,2" data-index-in-node="66"&gt;w&lt;/code&gt;)&lt;/span&gt;&lt;span class="" data-path-to-node="2,3"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,4"&gt; to fetch precise thermal metrics via a non-blocking &lt;code data-path-to-node="2,4" data-index-in-node="53"&gt;QTimer&lt;/code&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,5"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="2,6"&gt;, effectively isolating blocking operations and maintaining optimal UI frame rates.&lt;/span&gt;&lt;/p&gt;
&lt;p id="p-rc_72d725c80407277b-130" data-path-to-node="3"&gt;&lt;span class="" data-path-to-node="3,0"&gt;Beyond backend communication, the application excels in &lt;b data-path-to-node="3,0" data-index-in-node="56"&gt;Real-Time Multi-Parameter Visualization&lt;/b&gt; powered by Qt Charts. It features four independent live charts tracking BPM, SpO2, Filtered IR, and Temperature&lt;/span&gt;&lt;span class="" data-path-to-node="3,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="3,2"&gt;, all equipped with a sliding-window buffer that automatically shifts the X-axis after a set threshold of samples. To augment the graphical representation, a vertical thermometer progress bar provides operators with instant visual feedback on thermal variations. Furthermore, &lt;b data-path-to-node="3,2" data-index-in-node="276"&gt;Dynamic UI Layout Customization&lt;/b&gt; empowers users to switch the dashboard layout at runtime between a Vertically Stacked arrangement and a 2x2 Side-by-Side Grid layout using an intuitive dropdown control.&lt;/span&gt;&lt;/p&gt;
&lt;p id="p-rc_72d725c80407277b-131" data-path-to-node="4"&gt;&lt;span class="" data-path-to-node="4,0"&gt;Usability and data management are further elevated through thoughtful software design patterns. The application incorporates &lt;b data-path-to-node="4,0" data-index-in-node="125"&gt;Bilingual Localization (PL / EN)&lt;/b&gt;, implementing seamless runtime language switching between Polish and English via a dynamic retranslation mechanism (&lt;code data-path-to-node="4,0" data-index-in-node="274"&gt;retranslateUi&lt;/code&gt;). This instantly updates all interface elements, tooltips, buttons, and chart titles. Concurrently, automated data persistence is handled by &lt;code data-path-to-node="4,0" data-index-in-node="429"&gt;CsvLogger&lt;/code&gt;, which automatically initiates a timestamped CSV session upon successful device connection, logging elapsed time, device indices, temperatures, and hardware status flags for subsequent post-processing analysis&lt;/span&gt;&lt;span class="" data-path-to-node="4,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="4,2"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5r2u4bk0" data-path-to-node="4"&gt;Architectural Overview: Two Independent Data Streams&lt;/h2&gt;
&lt;p data-path-to-node="5"&gt;&lt;span&gt;To ensure low latency,&lt;/span&gt;&lt;span&gt; thread safety,&lt;/span&gt;&lt;span&gt; and freedom from data blockages,&lt;/span&gt;&lt;span&gt; the application architecture splits telemetry handling into two distinct pathways:&lt;/span&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="6"&gt;
&lt;li&gt;
&lt;p data-path-to-node="6,0,0"&gt;&lt;b data-path-to-node="6,0,0" data-index-in-node="0"&gt;The Sensor Stream (STM32 / MAXREFDES117):&lt;/b&gt;&lt;span&gt; Configured via standard USB CDC (115200 baud) nad&lt;/span&gt;&lt;span&gt;&amp;nbsp;operates asynchronously on the main GUI thread via &lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="80"&gt;QSerialPort::readyRead&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; continuously capturing and parsing high-frequency JSON packets containing Heart Rate (&lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="190"&gt;bpm&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; Blood Oxygen (&lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="210"&gt;spo2&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; and Filtered Infrared (&lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="240"&gt;filtered_ir&lt;/code&gt;&lt;span&gt;) signals.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p-rc_496d65b345f9f6f1-137" data-path-to-node="6,1,0"&gt;&lt;span class="" data-path-to-node="6,1,0,0"&gt;&lt;b data-path-to-node="6,1,0,0" data-index-in-node="0"&gt;The Temperature Protocol Link (MAX30208EVSYS):&lt;/b&gt; Based on the evaluation kit&amp;#39;s firmware protocol (operating at 115200 baud, 8 data bits, no parity, 1 stop bit)&lt;/span&gt;&lt;span class="" data-path-to-node="6,1,0,2"&gt;.&amp;nbsp;&lt;/span&gt;&lt;span class="" data-path-to-node="6,1,0,4"&gt;Managed inside a dedicated background &lt;code data-path-to-node="6,1,0,0" data-index-in-node="67"&gt;QThread&lt;/code&gt; using a thread-safe &lt;code data-path-to-node="6,1,0,0" data-index-in-node="95"&gt;SerialWorker&lt;/code&gt; class&lt;span&gt;&lt;/span&gt;. It communicates via a command-based protocol (&lt;code data-path-to-node="6,1,0,2" data-index-in-node="48"&gt;s&lt;/code&gt;, &lt;code data-path-to-node="6,1,0,2" data-index-in-node="51"&gt;t&lt;/code&gt;, &lt;code data-path-to-node="6,1,0,2" data-index-in-node="54"&gt;r&lt;/code&gt;, &lt;code data-path-to-node="6,1,0,2" data-index-in-node="57"&gt;w&lt;/code&gt;)&lt;span&gt;&lt;/span&gt; to fetch precise thermal metrics via a non-blocking &lt;code data-path-to-node="6,1,0,4" data-index-in-node="53"&gt;QTimer&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="mcetoc_1k5r2u4bk1" data-path-to-node="8"&gt;Technical Implementation&lt;/h2&gt;
&lt;h3 id="mcetoc_1k5r2u4bk2" data-path-to-node="9"&gt;1. Robust Serial Port Management and Enumeration&lt;/h3&gt;
&lt;p id="p-rc_496d65b345f9f6f1-138" data-path-to-node="10"&gt;&lt;span class="" data-path-to-node="10,0"&gt;The application leverages hardware identification filters to locate devices accurately. For the MAX30208 evaluation kit, the serial layer looks up specific vendor and product IDs (&lt;code data-path-to-node="10,0" data-index-in-node="180"&gt;VID_0B6A&lt;/code&gt; and &lt;code data-path-to-node="10,0" data-index-in-node="193"&gt;PID_0042&lt;/code&gt;) using Windows Management Instrumentation (WMI) queries, ensuring reliable plug-and-play identification&lt;/span&gt;&lt;span class="" data-path-to-node="10,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="10,2"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r2u4bk3" class="" data-path-to-node="11"&gt;2. Implementing the MAX30208 Evaluation Kit Protocol&lt;/h3&gt;
&lt;p data-path-to-node="12"&gt;&lt;span&gt;Derived directly from the evaluation kit&amp;#39;s firmware communication structure,&lt;/span&gt;&lt;span&gt; the custom &lt;/span&gt;&lt;code data-path-to-node="12" data-index-in-node="88"&gt;OT07Serial&lt;/code&gt;&lt;span&gt; class maps all core hardware interaction commands:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="13"&gt;
&lt;li&gt;
&lt;p id="p-rc_496d65b345f9f6f1-139" data-path-to-node="13,0,0"&gt;&lt;span class="" data-path-to-node="13,0,0,0"&gt;&lt;b data-path-to-node="13,0,0,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="13,0,0,0" data-index-in-node="0"&gt;s&lt;/code&gt; (Search Command):&lt;/b&gt; Scans the I&amp;sup2;C bus for connected sensors, returning the device count, I&amp;sup2;C addresses, and unique 64-bit ROM codes formatted inside bracketed strings (e.g., &lt;code data-path-to-node="13,0,0,0" data-index-in-node="174"&gt;[Index] [Address] [RomCode]&lt;/code&gt;)&lt;/span&gt;&lt;span class="" data-path-to-node="13,0,0,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="13,0,0,2"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p-rc_496d65b345f9f6f1-140" data-path-to-node="13,1,0"&gt;&lt;span class="" data-path-to-node="13,1,0,0"&gt;&lt;b data-path-to-node="13,1,0,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="13,1,0,0" data-index-in-node="0"&gt;t&lt;/code&gt; (Temperature Read):&lt;/b&gt; Requests active temperature conversions for individual or ranged device indices, parsing floating-point Celsius values and status flags&lt;/span&gt;&lt;span class="" data-path-to-node="13,1,0,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="13,1,0,2"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p-rc_496d65b345f9f6f1-141" data-path-to-node="13,2,0"&gt;&lt;span class="" data-path-to-node="13,2,0,0"&gt;&lt;b data-path-to-node="13,2,0,0" data-index-in-node="0"&gt;Register Control (&lt;code data-path-to-node="13,2,0,0" data-index-in-node="18"&gt;r&lt;/code&gt;, &lt;code data-path-to-node="13,2,0,0" data-index-in-node="21"&gt;w&lt;/code&gt;, &lt;code data-path-to-node="13,2,0,0" data-index-in-node="24"&gt;g&lt;/code&gt;):&lt;/b&gt; Provides low-level read, write, and bulk configuration dumps across the 24-register memory map of the MAX30208 sensor&lt;/span&gt;&lt;span class="" data-path-to-node="13,2,0,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="13,2,0,2"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5r2u4bk4" class="" data-path-to-node="14"&gt;3. Real-Time Multi-Chart Visualization (&lt;code data-path-to-node="14" data-index-in-node="40"&gt;Qt Charts&lt;/code&gt;)&lt;/h3&gt;
&lt;p data-path-to-node="15"&gt;&lt;span&gt;Plotting high-frequency physiological signals alongside low-frequency thermal data on a single axis causes scaling distortion.&lt;/span&gt;&lt;span&gt; To solve this,&lt;/span&gt;&lt;span&gt; the application provisions &lt;/span&gt;&lt;b data-path-to-node="15" data-index-in-node="169"&gt;three independent chart panels&lt;/b&gt;&lt;span&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="16"&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,0,0"&gt;&lt;b data-path-to-node="16,0,0" data-index-in-node="0"&gt;Rolling Window Buffer:&lt;/b&gt;&lt;span&gt; A sample counter tracks incoming frames.&lt;/span&gt;&lt;span&gt; Once limits exceed 100 samples,&lt;/span&gt;&lt;span&gt; the X-axis dynamically shifts (&lt;/span&gt;&lt;code data-path-to-node="16,0,0" data-index-in-node="127"&gt;axisX-&amp;gt;setRange(...)&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; creating a clean,&lt;/span&gt;&lt;span&gt; sliding oscilloscope effect.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,1,0"&gt;&lt;b data-path-to-node="16,1,0" data-index-in-node="0"&gt;Layout Adaptability:&lt;/b&gt;&lt;span&gt; Users can instantly switch between a vertical stacked layout and a side-by-side horizontal arrangement via an intuitive dropdown menu.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p-rc_9507160a90c37109-122" data-path-to-node="8,0,0"&gt;&lt;span class="" data-path-to-node="8,0,0,0"&gt;Features &lt;b data-path-to-node="8,0,0,0" data-index-in-node="9"&gt;four independent live charts&lt;/b&gt; (BPM, SpO2, Filtered IR, and Temperature)&lt;/span&gt;&lt;span class="" data-path-to-node="8,0,0,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="8,0,0,2"&gt; equipped with a sliding-window buffer that automatically shifts the X-axis after a set threshold of samples.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,1,0"&gt;&lt;span&gt;Includes a vertical &lt;/span&gt;&lt;b data-path-to-node="8,1,0" data-index-in-node="20"&gt;thermometer progress bar&lt;/b&gt;&lt;span&gt; providing instant visual feedback on thermal variations.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5r3bl476" data-path-to-node="9"&gt;4. Dynamic UI Layout Customization&lt;/h3&gt;
&lt;ul data-path-to-node="10"&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,0,0"&gt;&lt;span&gt;Users can switch the dashboard layout at runtime between a &lt;/span&gt;&lt;b data-path-to-node="10,0,0" data-index-in-node="59"&gt;Vertically Stacked&lt;/b&gt;&lt;span&gt; arrangement and a &lt;/span&gt;&lt;b data-path-to-node="10,0,0" data-index-in-node="96"&gt;2x2 Side-by-Side Grid&lt;/b&gt;&lt;span&gt; layout using an intuitive dropdown control.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/DualSensor-GUI-1.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/DualSensor-GUI-2.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5r3bl477" data-path-to-node="11"&gt;5. Bilingual Localization (PL / EN)&lt;/h3&gt;
&lt;ul data-path-to-node="12"&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,0,0"&gt;&lt;span&gt;Implements seamless &lt;/span&gt;&lt;b data-path-to-node="12,0,0" data-index-in-node="20"&gt;runtime language switching&lt;/b&gt;&lt;span&gt; between Polish and English using a dynamic retranslation mechanism (&lt;/span&gt;&lt;code data-path-to-node="12,0,0" data-index-in-node="115"&gt;retranslateUi&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; instantly updating all interface elements,&lt;/span&gt;&lt;span&gt; tooltips,&lt;/span&gt;&lt;span&gt; buttons,&lt;/span&gt;&lt;span&gt; and chart titles.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5r3bl478" class="" data-path-to-node="13"&gt;6. Automated Data Logging (&lt;code data-path-to-node="13" data-index-in-node="27"&gt;CsvLogger&lt;/code&gt;)&lt;/h3&gt;
&lt;ul data-path-to-node="14"&gt;
&lt;li&gt;
&lt;p id="p-rc_9507160a90c37109-123" data-path-to-node="14,0,0"&gt;&lt;span data-path-to-node="14,0,0,0"&gt;Automatically initiates a timestamped CSV session upon successful device connection, logging elapsed time, device indices, temperatures, and hardware status flags for post-processing analysis&lt;/span&gt;&lt;span class="" data-path-to-node="14,0,0,1"&gt;&lt;span&gt;&lt;sup class="superscript"&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-path-to-node="14,0,0,2"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1k5r2u4bk5" data-path-to-node="18"&gt;&amp;nbsp;Conclusion&lt;/h2&gt;
&lt;p data-path-to-node="19"&gt;&lt;span&gt;Integrating disparate hardware protocols into a single,&lt;/span&gt;&lt;span&gt; cohesive desktop environment highlights the flexibility of modern C++ and Qt.&lt;/span&gt;&lt;span&gt; By separating asynchronous JSON data acquisition from polled command-line protocols,&lt;/span&gt;&lt;span&gt; developers can scale telemetry systems easily&amp;mdash;transforming raw microcontroller evaluation kits into professional-grade diagnostic dashboards.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 11 : Research Workstation System Architecture</title><link>https://community.element14.com/thread/57385?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 22:35:56 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:18f7d330-9a94-4511-b989-85662367e0d8</guid><dc:creator>jelektro</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57385?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qka5ij0" data-path-to-node="6"&gt;1. Introduction and Purpose&lt;/h2&gt;
&lt;p data-path-to-node="7"&gt;&lt;span&gt;The stationary research workstation is designed for precise,&lt;/span&gt;&lt;span&gt; simultaneous,&lt;/span&gt;&lt;span&gt; real-time monitoring of selected human physiological parameters (photoplethysmography,&lt;/span&gt;&lt;span&gt; heart rate,&lt;/span&gt;&lt;span&gt; oxygen saturation,&lt;/span&gt;&lt;span&gt; and clinical-grade body temperature).&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="8"&gt;&lt;span&gt;The system integrates high-performance biomedical sensor modules,&lt;/span&gt;&lt;span&gt; each managed by its own dedicated microcontroller (&lt;/span&gt;&lt;b data-path-to-node="8" data-index-in-node="117"&gt;STM32&lt;/b&gt;&lt;span&gt; for the optical sensor and the &lt;/span&gt;&lt;b data-path-to-node="8" data-index-in-node="154"&gt;MAX32630FTHR&lt;/b&gt;&lt;span&gt; ARM Cortex-M4F board for the temperature sensor),&lt;/span&gt;&lt;span&gt; combined with a hybrid PC software architecture:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="9"&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,0,0"&gt;&lt;b data-path-to-node="9,0,0" data-index-in-node="0"&gt;LabVIEW&lt;/b&gt;&lt;span&gt; handles multi-channel data acquisition,&lt;/span&gt;&lt;span&gt; synchronization,&lt;/span&gt;&lt;span&gt; and real-time Digital Signal Processing (DSP).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,1,0"&gt;&lt;b data-path-to-node="9,1,0" data-index-in-node="0"&gt;Qt&lt;/b&gt;&lt;span&gt; provides a modern,&lt;/span&gt;&lt;span&gt; responsive Desktop User Interface (UI/UX),&lt;/span&gt;&lt;span&gt; database management,&lt;/span&gt;&lt;span&gt; and session reporting tools.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qka5ij1" data-path-to-node="11"&gt;2. Hardware Architecture (Hardware Layer)&lt;/h2&gt;
&lt;p data-path-to-node="12"&gt;&lt;span&gt;The measurement layer is split into two independent embedded subsystems that stream data to the host PC:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="13"&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,0,0"&gt;&lt;b data-path-to-node="13,0,0" data-index-in-node="0"&gt;Subsystem 1: MAXREFDES117 + STM32 Microcontroller:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="13,0,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,0,1,0,0"&gt;&lt;b data-path-to-node="13,0,1,0,0" data-index-in-node="0"&gt;Sensor:&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;b data-path-to-node="13,0,1,0,0" data-index-in-node="8"&gt;MAXREFDES117&lt;/b&gt;&lt;span&gt; (integrating the &lt;/span&gt;&lt;b data-path-to-node="13,0,1,0,0" data-index-in-node="38"&gt;MAX30102&lt;/b&gt;&lt;span&gt; optical sensor for Red and IR photoplethysmography).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,0,1,1,0"&gt;&lt;b data-path-to-node="13,0,1,1,0" data-index-in-node="0"&gt;MCU:&lt;/b&gt;&lt;span&gt; An &lt;/span&gt;&lt;b data-path-to-node="13,0,1,1,0" data-index-in-node="8"&gt;STM32&lt;/b&gt;&lt;span&gt; microcontroller communicating with the sensor via &lt;/span&gt;&lt;b data-path-to-node="13,0,1,1,0" data-index-in-node="64"&gt;I2C&lt;/b&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,0,1,2,0"&gt;&lt;b data-path-to-node="13,0,1,2,0" data-index-in-node="0"&gt;Function:&lt;/b&gt;&lt;span&gt; Samples optical reflections at high frequency (100 Hz &amp;ndash; 400 Hz),&lt;/span&gt;&lt;span&gt; buffers the raw PPG data,&lt;/span&gt;&lt;span&gt; and streams formatted packets over its dedicated USB Virtual COM port.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,1,0"&gt;&lt;b data-path-to-node="13,1,0" data-index-in-node="0"&gt;Subsystem 2: MAX30208EVSYS + MAX32630FTHR Board:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="13,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,1,1,0,0"&gt;&lt;b data-path-to-node="13,1,1,0,0" data-index-in-node="0"&gt;Sensor:&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;b data-path-to-node="13,1,1,0,0" data-index-in-node="8"&gt;MAX30208EVSYS&lt;/b&gt;&lt;span&gt; evaluation system featuring the &lt;/span&gt;&lt;b data-path-to-node="13,1,1,0,0" data-index-in-node="54"&gt;MAX30208&lt;/b&gt;&lt;span&gt; clinical temperature sensor (&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="92"&gt;$\pm 0.1^\circ\text{C}$&lt;/span&gt;&lt;span&gt; accuracy).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,1,1,1,0"&gt;&lt;b data-path-to-node="13,1,1,1,0" data-index-in-node="0"&gt;MCU:&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;b data-path-to-node="13,1,1,1,0" data-index-in-node="5"&gt;MAX32630FTHR&lt;/b&gt;&lt;span&gt; development platform (ARM Cortex-M4F @ 96 MHz) communicating with the MAX30208 via &lt;/span&gt;&lt;b data-path-to-node="13,1,1,1,0" data-index-in-node="101"&gt;I2C&lt;/b&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,1,1,2,0"&gt;&lt;b data-path-to-node="13,1,1,2,0" data-index-in-node="0"&gt;Function:&lt;/b&gt;&lt;span class=""&gt; Measures high-resolution contact skin temperature and transmits readings over its integrated USB Virtual COM port.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class=""&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/VitalSense.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qj7j5h2" data-path-to-node="11"&gt;3. Overall System Block Diagram&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/system-architecture.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="container"&gt;
&lt;div id="model-response-message-contentr_bd9ea4c09ae65312" class="markdown markdown-main-panel md-content enable-luminous-fast-follows enable-updated-hr-color" dir="ltr"&gt;
&lt;h2 id="mcetoc_1k5qj7j5h3" data-path-to-node="14"&gt;4. Detailed Layer Description&lt;/h2&gt;
&lt;h3 id="mcetoc_1k5qj7j5h4" data-path-to-node="15"&gt;Layer 1: Physical / Sensor Layer (Hardware)&lt;/h3&gt;
&lt;ul data-path-to-node="16"&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,0,0"&gt;&lt;b data-path-to-node="16,0,0" data-index-in-node="0"&gt;MAXREFDES117:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="16,0,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,0,1,0,0"&gt;&lt;b data-path-to-node="16,0,1,0,0" data-index-in-node="0"&gt;Interface:&lt;/b&gt; I2C.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,0,1,1,0"&gt;&lt;b data-path-to-node="16,0,1,1,0" data-index-in-node="0"&gt;Measured Quantities:&lt;/b&gt; Raw reflected/absorbed light intensity for Red and Infrared wavelengths.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,0,1,2,0"&gt;&lt;b data-path-to-node="16,0,1,2,0" data-index-in-node="0"&gt;Function:&lt;/b&gt; Provides raw optical data required to reconstruct the PPG waveform, calculate HR, and derive &lt;span class="math-inline" data-index-in-node="103"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;SpO2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,1,0"&gt;&lt;b data-path-to-node="16,1,0" data-index-in-node="0"&gt;MAX30208EVSYS:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="16,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,1,1,0,0"&gt;&lt;b data-path-to-node="16,1,1,0,0" data-index-in-node="0"&gt;Interface:&lt;/b&gt; I2C.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,1,1,1,0"&gt;&lt;b data-path-to-node="16,1,1,1,0" data-index-in-node="0"&gt;Measured Quantities:&lt;/b&gt; High-resolution digital body temperature (20-bit ADC).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="16,1,1,2,0"&gt;&lt;b data-path-to-node="16,1,1,2,0" data-index-in-node="0"&gt;Function:&lt;/b&gt; Delivers stable, continuous skin temperature measurement.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qj7j5h5" data-path-to-node="17"&gt;Layer 2: Conversion &amp;amp; Transmission (Embedded Firmware)&lt;/h3&gt;
&lt;ul data-path-to-node="18"&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,0"&gt;&lt;b data-path-to-node="18,0,0" data-index-in-node="0"&gt;Microcontroller Tasks:&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="18,0,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,1,0,0"&gt;Polls the MAX30102 FIFO registers and MAX30208 temperature registers at a configurable sampling rate (100 Hz &amp;ndash; 400 Hz for PPG).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,1,1,0"&gt;Applies precise timestamps to each assembled data packet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,1,2,0"&gt;Formats frame payloads (e.g., &lt;code data-path-to-node="18,0,1,2,0" data-index-in-node="30"&gt;[HEADER][TIMESTAMP][RED][IR][TEMP][CHECKSUM]&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,1,3,0"&gt;Transmits framed data over USB CDC (Virtual COM Port).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qj7j5h6" data-path-to-node="19"&gt;Layer 3: Acquisition &amp;amp; Analysis Engine (LabVIEW Backend)&lt;/h3&gt;
&lt;ul data-path-to-node="20"&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,0,0"&gt;&lt;b data-path-to-node="20,0,0" data-index-in-node="0"&gt;Acquisition:&lt;/b&gt; Utilizes &lt;b data-path-to-node="20,0,0" data-index-in-node="22"&gt;NI-VISA&lt;/b&gt; to read incoming serial streams from the COM port and unpack channels.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,1,0"&gt;&lt;b data-path-to-node="20,1,0" data-index-in-node="0"&gt;Digital Signal Processing (DSP):&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="20,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,1,1,0,0"&gt;&lt;i data-path-to-node="20,1,1,0,0" data-index-in-node="0"&gt;Filtering:&lt;/i&gt; Bandpass filtering (Butterworth, e.g., 0.5&amp;ndash;5.0 Hz) to eliminate motion artifacts, baseline wander (respiration), and high-frequency noise.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,1,1,1,0"&gt;&lt;i data-path-to-node="20,1,1,1,0" data-index-in-node="0"&gt;HR/HRV Algorithm:&lt;/i&gt; Detects PPG waveform peaks to determine peak-to-peak (RR/PP) intervals and Heart Rate Variability (HRV).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,1,1,2,0"&gt;&lt;i data-path-to-node="20,1,1,2,0" data-index-in-node="0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;SpO2\text{SpO}_2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut" style="height:0.9275em;vertical-align:-0.2441em;"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;SpO&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.207em;"&gt;&lt;span class="" style="margin-right:0.05em;top:-2.4559em;"&gt;&lt;span class="pstrut" style="height:2.7em;"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.2441em;"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; Algorithm:&lt;/i&gt; Computes the AC/DC ratio of Red vs. IR signals&lt;/p&gt;
&lt;p data-path-to-node="20,1,1,2,0"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/equation.jpg" /&gt;&lt;/p&gt;
&lt;p data-path-to-node="20,1,1,2,0"&gt;to evaluate blood oxygen saturation levels.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,1,1,3,0"&gt;&lt;i data-path-to-node="20,1,1,3,0" data-index-in-node="0"&gt;Archiving:&lt;/i&gt; Streams raw and processed signals into binary TDMS files optimized for high-speed time-series data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="20,2,0"&gt;&lt;b data-path-to-node="20,2,0" data-index-in-node="0"&gt;IPC Interface:&lt;/b&gt; Serves processed metrics to the Qt desktop app in real time via a local TCP/IP socket.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qj7j5h7" data-path-to-node="21"&gt;Layer 4: User Interface &amp;amp; Database Layer (Qt Desktop UI)&lt;/h3&gt;
&lt;ul data-path-to-node="22"&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,0,0"&gt;&lt;b data-path-to-node="22,0,0" data-index-in-node="0"&gt;TCP/IP Client (&lt;code data-path-to-node="22,0,0" data-index-in-node="15"&gt;QTcpSocket&lt;/code&gt;):&lt;/b&gt; Receives data packages from the LabVIEW server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,1,0"&gt;&lt;b data-path-to-node="22,1,0" data-index-in-node="0"&gt;Visualization (GUI):&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="22,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,1,1,0,0"&gt;Real-time rendering of PPG waveforms and temperature trends via plotting widgets (&lt;code data-path-to-node="22,1,1,0,0" data-index-in-node="82"&gt;QCustomPlot&lt;/code&gt; / &lt;code data-path-to-node="22,1,1,0,0" data-index-in-node="96"&gt;Qt Charts&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,1,1,1,0"&gt;Numerical LCD/Gauge indicators for HR, &lt;span class="math-inline" data-index-in-node="39"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;SpO2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.2441em;"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, and Temperature.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,2,0"&gt;&lt;b data-path-to-node="22,2,0" data-index-in-node="0"&gt;Database Management (&lt;code data-path-to-node="22,2,0" data-index-in-node="21"&gt;Qt SQL&lt;/code&gt;):&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="22,2,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,2,1,0,0"&gt;Session cataloging linked to patient IDs, timestamps, and clinical notes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,3,0"&gt;&lt;b data-path-to-node="22,3,0" data-index-in-node="0"&gt;Business Logic:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="22,3,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,3,1,0,0"&gt;Two-tier alarm thresholds (Warning / Critical) monitoring for bradycardia, tachycardia, hypoxia, or fever.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,3,1,1,0"&gt;Automated generation of session summary reports (PDF export).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1k5qj7j5h8" data-path-to-node="24"&gt;5. Data Flow Summary&lt;/h2&gt;
&lt;ol start="1" data-path-to-node="25"&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,0,0"&gt;&lt;b data-path-to-node="25,0,0" data-index-in-node="0"&gt;Sensors&lt;/b&gt; continuously capture optical reflection and temperature readings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,1,0"&gt;&lt;b data-path-to-node="25,1,0" data-index-in-node="0"&gt;Microcontrollers&lt;/b&gt; aggregate I2C data, timestamps packets, and streams frames over USB.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,2,0"&gt;&lt;b data-path-to-node="25,2,0" data-index-in-node="0"&gt;LabVIEW&lt;/b&gt; receives the stream, parses channels, filters noise, and computes physiological parameters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,3,0"&gt;&lt;b data-path-to-node="25,3,0" data-index-in-node="0"&gt;Qt Application&lt;/b&gt; receives processed parameters over IPC, displays real-time plots, alerts operators to anomalies, and logs records to the database.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qka5ij2" class="" data-path-to-node="18"&gt;6. Summary of Subsystem Integration&lt;/h2&gt;
&lt;table data-path-to-node="19"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Parameter / Feature&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Subsystem 1 (Optical / PPG)&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Subsystem 2 (Temperature)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,1,0,0"&gt;&lt;b data-path-to-node="19,1,0,0" data-index-in-node="0"&gt;Sensor Module&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,1,1,0"&gt;MAXREFDES117 (MAX30102)&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,1,2,0"&gt;MAX30208EVSYS (MAX30208)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,2,0,0"&gt;&lt;b data-path-to-node="19,2,0,0" data-index-in-node="0"&gt;Target Controller&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,2,1,0"&gt;STM32 Microcontroller&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,2,2,0"&gt;MAX32630FTHR (ARM Cortex-M4F)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,3,0,0"&gt;&lt;b data-path-to-node="19,3,0,0" data-index-in-node="0"&gt;Physical Interface&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,3,1,0"&gt;I2C&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,3,2,0"&gt;I2C&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,4,0,0"&gt;&lt;b data-path-to-node="19,4,0,0" data-index-in-node="0"&gt;PC Transport&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,4,1,0"&gt;USB Virtual COM Port 1&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,4,2,0"&gt;USB Virtual COM Port 2&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,5,0,0"&gt;&lt;b data-path-to-node="19,5,0,0" data-index-in-node="0"&gt;LabVIEW Processing&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,5,1,0"&gt;Filtering, Peak Detection, HR/HRV, &lt;span class="math-inline" data-index-in-node="35"&gt;SpO2&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,5,2,0"&gt;Moving average filter, thermal trend calculation&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,6,0,0"&gt;&lt;b data-path-to-node="19,6,0,0" data-index-in-node="0"&gt;Qt UI Display&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,6,1,0"&gt;Dynamic PPG plot, numerical HR &amp;amp; &lt;span class="math-inline" data-index-in-node="33"&gt;SpO2&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="19,6,2,0"&gt;Live temperature trend curve &amp;amp; LCD indicator&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC</title><link>https://community.element14.com/thread/57384?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 22:24:57 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ee803735-789f-475c-8872-a663bcc55bbe</guid><dc:creator>jelektro</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57384?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qivjpj0" data-path-to-node="3"&gt;1. Introduction and Architectural Overview&lt;/h3&gt;
&lt;p data-path-to-node="4"&gt;When developing embedded systems, Internet of Things (IoT) devices, or biomedical monitoring tools (such as pulse oximeters using the &lt;b data-path-to-node="4" data-index-in-node="134"&gt;MAXREFDES117&lt;/b&gt; optical sensor), developers frequently encounter a common bottleneck: visualizing telemetry data streaming from a microcontroller. Relying solely on serial console logs or terminal windows is insufficient for diagnostic evaluation, signal processing validation, or user-interface prototyping.&lt;/p&gt;
&lt;p data-path-to-node="5"&gt;To bridge this gap, a cross-platform desktop application was engineered using &lt;b data-path-to-node="5" data-index-in-node="78"&gt;C++&lt;/b&gt; and the &lt;b data-path-to-node="5" data-index-in-node="90"&gt;Qt Framework&lt;/b&gt;. The architecture is structured around a decoupled event-driven model that handles serial communication asynchronously, parses lightweight JSON payloads, manages dynamic data buffers, and renders real-time graphical representations using &lt;b data-path-to-node="5" data-index-in-node="341"&gt;Qt Charts&lt;/b&gt;.&lt;/p&gt;
&lt;p data-path-to-node="6"&gt;Rather than dumping raw text to the screen, the application offers an interactive dashboard featuring live numerical readouts, independent multi-parameter rolling-window charts, layout adaptability, and fault-tolerant parsing mechanisms.&lt;/p&gt;
&lt;p data-path-to-node="6"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/maxrefs117_2D00_2.jpg" /&gt;&lt;/p&gt;
&lt;p data-path-to-node="6"&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/MAXREFS117-GUI.mp4"&gt;community.element14.com/.../MAXREFS117-GUI.mp4&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qivjpj1" data-path-to-node="8"&gt;2. Core Modules and Component Breakdown&lt;/h3&gt;
&lt;p data-path-to-node="9"&gt;The codebase is modularized cleanly into configuration files, header definitions, and implementation logic:&lt;/p&gt;
&lt;ul data-path-to-node="10"&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,0,0"&gt;&lt;b data-path-to-node="10,0,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="10,0,0" data-index-in-node="0"&gt;MaxRefdesReader.pro&lt;/code&gt; (The Build Specification):&lt;/b&gt; Configured via &lt;code data-path-to-node="10,0,0" data-index-in-node="62"&gt;qmake&lt;/code&gt;, the project links against essential Qt modules&amp;mdash;specifically &lt;code data-path-to-node="10,0,0" data-index-in-node="129"&gt;core&lt;/code&gt;, &lt;code data-path-to-node="10,0,0" data-index-in-node="135"&gt;gui&lt;/code&gt;, &lt;code data-path-to-node="10,0,0" data-index-in-node="140"&gt;widgets&lt;/code&gt;, &lt;code data-path-to-node="10,0,0" data-index-in-node="149"&gt;serialport&lt;/code&gt;, and &lt;code data-path-to-node="10,0,0" data-index-in-node="165"&gt;charts&lt;/code&gt;. It mandates modern C++17 standards to ensure safe memory handling, efficient STL utilization, and clean syntax.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,1,0"&gt;&lt;b data-path-to-node="10,1,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="10,1,0" data-index-in-node="0"&gt;MainWindow&lt;/code&gt; Class (&lt;code data-path-to-node="10,1,0" data-index-in-node="18"&gt;mainwindow.h&lt;/code&gt; / &lt;code data-path-to-node="10,1,0" data-index-in-node="33"&gt;mainwindow.cpp&lt;/code&gt;):&lt;/b&gt; Acting as the central controller, this class inherits from &lt;code data-path-to-node="10,1,0" data-index-in-node="109"&gt;QMainWindow&lt;/code&gt; and orchestrates lifecycle management, user interface layout switching, hardware connectivity states, and serial stream processing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qivjpj2" data-path-to-node="12"&gt;3. Key Technical Features &amp;amp; Implementation Details&lt;/h3&gt;
&lt;h4 data-path-to-node="13"&gt;A. Asynchronous Serial Port Management &amp;amp; Robust Framing&lt;/h4&gt;
&lt;p data-path-to-node="14"&gt;Communication with the target microcontroller occurs over a virtual COM port established via USB CDC (Communications Device Class).&lt;/p&gt;
&lt;ul data-path-to-node="15"&gt;
&lt;li&gt;
&lt;p data-path-to-node="15,0,0"&gt;&lt;b data-path-to-node="15,0,0" data-index-in-node="0"&gt;Port Discovery:&lt;/b&gt; Upon startup, the application queries &lt;code data-path-to-node="15,0,0" data-index-in-node="54"&gt;QSerialPortInfo::availablePorts()&lt;/code&gt; to dynamically populate a dropdown menu with all active hardware and virtual serial interfaces available on the host operating system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="15,1,0"&gt;&lt;b data-path-to-node="15,1,0" data-index-in-node="0"&gt;Stream Handling &amp;amp; Buffer Accumulation:&lt;/b&gt; Serial data does not always arrive in neat, atomic packages; packets can be fragmented or batched together. To prevent data corruption or missing frames, the application implements a &lt;b data-path-to-node="15,1,0" data-index-in-node="222"&gt;line-buffered parsing algorithm&lt;/b&gt;. Incoming byte arrays are appended to a persistent &lt;code data-path-to-node="15,1,0" data-index-in-node="305"&gt;QByteArray&lt;/code&gt; buffer (&lt;code data-path-to-node="15,1,0" data-index-in-node="324"&gt;buffer&lt;/code&gt;). The application scans this buffer for a newline delimiter (&lt;code data-path-to-node="15,1,0" data-index-in-node="392"&gt;\n&lt;/code&gt;), extracts complete lines individually, and strips them from the buffer, ensuring uninterrupted telemetry streams.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node="16"&gt;B. JSON Deserialization and Data Extraction&lt;/h4&gt;
&lt;p data-path-to-node="17"&gt;The microcontroller transmits sensor data packets formatted as JSON strings (e.g., &lt;code data-path-to-node="17" data-index-in-node="83"&gt;{&amp;quot;bpm&amp;quot;: 72, &amp;quot;spo2&amp;quot;: 98, &amp;quot;filtered_ir&amp;quot;: 1621.45}&lt;/code&gt;).&lt;/p&gt;
&lt;ul data-path-to-node="18"&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,0"&gt;Once a full line is isolated from the serial buffer, it is passed through &lt;code data-path-to-node="18,0,0" data-index-in-node="74"&gt;QJsonDocument::fromJson()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,1,0"&gt;The parser validates whether the document successfully evaluates to a JSON object containing the required keys (&lt;code data-path-to-node="18,1,0" data-index-in-node="112"&gt;bpm&lt;/code&gt;, &lt;code data-path-to-node="18,1,0" data-index-in-node="117"&gt;spo2&lt;/code&gt;, and &lt;code data-path-to-node="18,1,0" data-index-in-node="127"&gt;filtered_ir&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,2,0"&gt;Validated parameters are extracted as double-precision floating-point numbers, instantly driving both the text label updates and the graphic plotting pipelines.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node="19"&gt;C. Multi-Chart Architecture with Rolling Windows&lt;/h4&gt;
&lt;p data-path-to-node="20"&gt;To prevent visual clutter, the system avoids plotting conflicting scales on a single chart (since raw/filtered infrared signals span thousands of units, whereas heart rate and blood oxygen operate in much tighter numerical ranges). Instead, it implements &lt;b data-path-to-node="20" data-index-in-node="255"&gt;three independent charts&lt;/b&gt;:&lt;/p&gt;
&lt;ol start="1" data-path-to-node="21"&gt;
&lt;li&gt;
&lt;p data-path-to-node="21,0,0"&gt;&lt;b data-path-to-node="21,0,0" data-index-in-node="0"&gt;Heart Rate (BPM):&lt;/b&gt; Tailored for standard physiological ranges.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="21,1,0"&gt;&lt;b data-path-to-node="21,1,0" data-index-in-node="0"&gt;Blood Oxygen (SpO2):&lt;/b&gt; Constrained to monitor oxygen saturation shifts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="21,2,0"&gt;&lt;b data-path-to-node="21,2,0" data-index-in-node="0"&gt;Filtered IR Signal:&lt;/b&gt; Configured with a wider dynamic range to capture raw photoplethysmogram (PPG) waveforms.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul data-path-to-node="22"&gt;
&lt;li&gt;
&lt;p data-path-to-node="22,0,0"&gt;&lt;b data-path-to-node="22,0,0" data-index-in-node="0"&gt;Rolling Window Buffer Mechanism:&lt;/b&gt; To prevent memory bloat and application slowdowns over long monitoring sessions, a &lt;code data-path-to-node="22,0,0" data-index-in-node="116"&gt;pointCounter&lt;/code&gt; tracks total incoming samples. Once the sample count exceeds 100, the X-axis range dynamically shifts using &lt;code data-path-to-node="22,0,0" data-index-in-node="237"&gt;axisX-&amp;gt;setRange(pointCounter - 100, pointCounter)&lt;/code&gt;, creating a real-time sliding-window oscilloscope effect.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node="23"&gt;D. Dynamic Layout Switching (User Adaptability)&lt;/h4&gt;
&lt;p data-path-to-node="24"&gt;Flexibility in workspace organization is achieved through a dynamic layout manager. Users can toggle a dropdown menu to instantly rearrange the visual presentation:&lt;/p&gt;
&lt;ul data-path-to-node="25"&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,0,0"&gt;&lt;b data-path-to-node="25,0,0" data-index-in-node="0"&gt;Vertical Layout (Stacked):&lt;/b&gt; Positions the three chart views neatly on top of one another, which is ideal for widescreen monitors or detailed waveform inspection.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,1,0"&gt;&lt;b data-path-to-node="25,1,0" data-index-in-node="0"&gt;Horizontal Layout (Side by Side):&lt;/b&gt; Arranges charts horizontally, maximizing horizontal space resolution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="25,2,0"&gt;&lt;b data-path-to-node="25,2,0" data-index-in-node="0"&gt;The Underlying Mechanism:&lt;/b&gt; When a layout switch is triggered, the application safely detaches the &lt;code data-path-to-node="25,2,0" data-index-in-node="97"&gt;QChartView&lt;/code&gt; instances from the active layout container, destroys the old layout manager, instantiates the alternative layout manager, re-inserts the chart widgets, and forces a UI refresh (&lt;code data-path-to-node="25,2,0" data-index-in-node="285"&gt;show()&lt;/code&gt;) without losing existing serial connections or historical plot data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/maxrefs117_2D00_1.jpg" /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qivjpj3" data-path-to-node="27"&gt;4. Summary of Benefits &amp;amp; Extensibility&lt;/h3&gt;
&lt;p data-path-to-node="28"&gt;By leveraging Qt&amp;#39;s mature graphics rendering pipeline and robust hardware abstraction layers (&lt;code data-path-to-node="28" data-index-in-node="94"&gt;QSerialPort&lt;/code&gt;), this application transforms a basic microcontroller sensor setup into a professional-grade telemetry suite.&lt;/p&gt;
&lt;p data-path-to-node="29"&gt;The architecture is deliberately built for extension. Future enhancements can easily integrate features such as:&lt;/p&gt;
&lt;ul data-path-to-node="30"&gt;
&lt;li&gt;
&lt;p data-path-to-node="30,0,0"&gt;&lt;b data-path-to-node="30,0,0" data-index-in-node="0"&gt;Data Logging:&lt;/b&gt; Exporting buffered stream arrays directly into CSV files for post-processing in Python or MATLAB.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="30,1,0"&gt;&lt;b data-path-to-node="30,1,0" data-index-in-node="0"&gt;Threshold Alerts:&lt;/b&gt; Triggering visual or auditory alarms if &lt;code data-path-to-node="30,1,0" data-index-in-node="58"&gt;bpm&lt;/code&gt; or &lt;code data-path-to-node="30,1,0" data-index-in-node="65"&gt;spo2&lt;/code&gt; breach critical safety margins.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="30,2,0"&gt;&lt;b data-path-to-node="30,2,0" data-index-in-node="0"&gt;Automatic Y-Axis Scaling:&lt;/b&gt; Implementing dynamic auto-scaling algorithms for adaptive signal tracking.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 8 : STM32 Pulse Oximeter &amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)</title><link>https://community.element14.com/thread/57383?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 21:40:26 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:bedf0589-e9ed-47d9-8cc9-de7c8e4763a6</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57383?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;In this article,&lt;/span&gt;&lt;span&gt; I will walk you through the complete journey of developing a robust,&lt;/span&gt;&lt;span&gt; real-time heart rate (&lt;/span&gt;&lt;b data-path-to-node="3" data-index-in-node="255"&gt;BPM&lt;/b&gt;&lt;span&gt;) and blood oxygen saturation (&lt;/span&gt;&lt;b data-path-to-node="3" data-index-in-node="289"&gt;SpO2&lt;/b&gt;&lt;span&gt;) monitoring system using an &lt;/span&gt;&lt;b data-path-to-node="3" data-index-in-node="322"&gt;STM32L476RG&lt;/b&gt;&lt;span&gt; microcontroller (Nucleo development board) and the &lt;/span&gt;&lt;b data-path-to-node="3" data-index-in-node="385"&gt;MAX30102&lt;/b&gt;&lt;span&gt; optical sensor (MAXREFDES117 module).&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qfvrre0" data-path-to-node="5"&gt;1. Project Goals and Key Development Challenges&lt;/h2&gt;
&lt;p data-path-to-node="6"&gt;&lt;span&gt;The main objective was to build a non-blocking,&lt;/span&gt;&lt;span&gt; highly responsive firmware that streams clean sensor data in real-time to a PC via &lt;/span&gt;&lt;b data-path-to-node="6" data-index-in-node="131"&gt;USB CDC (Virtual COM Port)&lt;/b&gt;&lt;span&gt; using a universal &lt;/span&gt;&lt;b data-path-to-node="6" data-index-in-node="176"&gt;JSON format&lt;/b&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="7"&gt;&lt;span&gt;Throughout the development process,&lt;/span&gt;&lt;span&gt; we successfully tackled several core challenges typical of PPG (&lt;/span&gt;&lt;i data-path-to-node="7" data-index-in-node="100"&gt;Photoplethysmography&lt;/i&gt;&lt;span&gt;) optical systems:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="8"&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,0,0"&gt;&lt;b data-path-to-node="8,0,0" data-index-in-node="0"&gt;DC vs. AC Component Separation:&lt;/b&gt;&lt;span&gt; The raw optical signal reflected from tissue has a massive DC component (~200,&lt;/span&gt;&lt;span&gt;000 units),&lt;/span&gt;&lt;span&gt; while the actual pulse wave accounts for less than 2% of the total signal.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,1,0"&gt;&lt;b data-path-to-node="8,1,0" data-index-in-node="0"&gt;Motion Artifacts:&lt;/b&gt;&lt;span&gt; Finger tremors or shifting pressure cause severe signal spikes that ruin traditional peak-detection algorithms.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,2,0"&gt;&lt;b data-path-to-node="8,2,0" data-index-in-node="0"&gt;Avoiding System Freezes:&lt;/b&gt;&lt;span&gt; Standard rigid buffer-filling loops easily freeze the microcontroller if the user momentarily lifts their finger.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1k5qfvrre1" data-path-to-node="10"&gt;2. Hardware Architecture &amp;amp; Pinout&lt;/h2&gt;
&lt;p data-path-to-node="11"&gt;&lt;span&gt;The hardware stack is built around low-power,&lt;/span&gt;&lt;span&gt; high-reliability components:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="12"&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,0,0"&gt;&lt;b data-path-to-node="12,0,0" data-index-in-node="0"&gt;Microcontroller:&lt;/b&gt;&lt;span&gt; STM32 Nucleo-L476RG (ARM Cortex-M4 core with FPU,&lt;/span&gt;&lt;span&gt; ultra-low-power L4 series).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,1,0"&gt;&lt;b data-path-to-node="12,1,0" data-index-in-node="0"&gt;Sensor Module:&lt;/b&gt;&lt;span&gt; MAXREFDES117 featuring the &lt;/span&gt;&lt;b data-path-to-node="12,1,0" data-index-in-node="42"&gt;MAX30102&lt;/b&gt;&lt;span&gt; integrated optical sensor (Red and Infrared LEDs,&lt;/span&gt;&lt;span&gt; plus a sensitive photodetector).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,2,0"&gt;&lt;b data-path-to-node="12,2,0" data-index-in-node="0"&gt;Communication:&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;b data-path-to-node="12,2,0" data-index-in-node="15"&gt;I2C Bus&lt;/b&gt;&lt;span&gt; (pins &lt;/span&gt;&lt;code data-path-to-node="12,2,0" data-index-in-node="29"&gt;PB8&lt;/code&gt;&lt;span&gt; for SCL and &lt;/span&gt;&lt;code data-path-to-node="12,2,0" data-index-in-node="45"&gt;PB9&lt;/code&gt;&lt;span&gt; for SDA) and USB Virtual COM at 115200 baud.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/PulseOximeterSTM32.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="6"&gt;&lt;span&gt;Before diving into the code,&lt;/span&gt;&lt;span&gt; let&amp;#39;s take a closer look at the hardware layer that forms the foundation of our device.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5tp709c0" data-path-to-node="7"&gt;A. Microcontroller Choice: STM32 Nucleo-L476RG&lt;/h3&gt;
&lt;p data-path-to-node="8"&gt;&lt;span&gt;The core of the system is a 32-bit microcontroller from the STM32L4 family (an ARM Cortex-M4 core with a floating-point unit / FPU).&lt;/span&gt;&lt;span&gt; The &amp;quot;L4&amp;quot; series is designed specifically for battery-powered and low-power applications,&lt;/span&gt;&lt;span&gt; offering massive processing power while maintaining high energy efficiency.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5tp709c1" data-path-to-node="9"&gt;B. Optical Sensor: MAX30102 vs. MAX30105&lt;/h3&gt;
&lt;p data-path-to-node="10"&gt;&lt;span&gt;Mounted on the &lt;/span&gt;&lt;b data-path-to-node="10" data-index-in-node="15"&gt;MAXREFDES117&lt;/b&gt;&lt;span&gt; board is the &lt;/span&gt;&lt;b data-path-to-node="10" data-index-in-node="41"&gt;MAX30102&lt;/b&gt;&lt;span&gt; &amp;ndash; an advanced optical PPG (&lt;/span&gt;&lt;i data-path-to-node="10" data-index-in-node="77"&gt;Photoplethysmography&lt;/i&gt;&lt;span&gt;) sensor designed specifically for pulse oximetry and heart rate monitoring.&lt;/span&gt;&lt;span&gt; It contains two integrated LEDs:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;b data-path-to-node="10" data-index-in-node="207"&gt;Red&lt;/b&gt;&lt;span&gt; and &lt;/span&gt;&lt;b data-path-to-node="10" data-index-in-node="215"&gt;Infrared (IR)&lt;/b&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; along with a sensitive photodetector.&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="11"&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,0,0"&gt;&lt;i data-path-to-node="11,0,0" data-index-in-node="0"&gt;Good to know:&lt;/i&gt;&lt;span&gt; In the Arduino/PlatformIO ecosystem,&lt;/span&gt;&lt;span&gt; SparkFun&amp;#39;s universal library based on the &lt;/span&gt;&lt;code data-path-to-node="11,0,0" data-index-in-node="93"&gt;MAX30105.h&lt;/code&gt;&lt;span&gt; class is commonly used.&lt;/span&gt;&lt;span&gt; Although we physically have the MAX30102 model (equipped with 2 LEDs,&lt;/span&gt;&lt;span&gt; unlike the MAX30105 which adds a green LED for things like smoke detectors),&lt;/span&gt;&lt;span&gt; the registers and I2C communication protocol are identical,&lt;/span&gt;&lt;span&gt; allowing for seamless compilation.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,1,0"&gt;&lt;b data-path-to-node="11,1,0" data-index-in-node="0"&gt;Pinout &amp;amp; Connections:&lt;/b&gt;&lt;span&gt; Communication takes place via the &lt;/span&gt;&lt;b data-path-to-node="11,1,0" data-index-in-node="56"&gt;I2C bus&lt;/b&gt;&lt;span&gt; (&lt;/span&gt;&lt;code data-path-to-node="11,1,0" data-index-in-node="65"&gt;PB8&lt;/code&gt;&lt;span&gt; for SCL,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="11,1,0" data-index-in-node="78"&gt;PB9&lt;/code&gt;&lt;span&gt; for SDA).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qfvrrf2" data-path-to-node="14"&gt;3. Step-by-Step Development Milestones&lt;/h2&gt;
&lt;p data-path-to-node="15"&gt;&lt;span&gt;To reach a production-grade hobbyist firmware,&lt;/span&gt;&lt;span&gt; the development evolved through several crucial stages:&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qfvrrf3" data-path-to-node="16"&gt;Milestone 1: Establishing Basic I2C and Raw IR Streaming&lt;/h3&gt;
&lt;p data-path-to-node="17"&gt;&lt;span&gt;We started by verifying basic sensor communication over I2C and streaming raw IR values.&lt;/span&gt;&lt;span&gt; This confirmed that the wiring,&lt;/span&gt;&lt;span&gt; power rails,&lt;/span&gt;&lt;span&gt; and USB CDC serial pipeline were working properly without any driver conflicts.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qfvrrf4" data-path-to-node="18"&gt;Milestone 2: Transitioning from Blocking Buffers to Non-Blocking Architecture&lt;/h3&gt;
&lt;p data-path-to-node="19"&gt;&lt;span&gt;Initial standard buffer algorithms (like those requiring strict 100-sample windows at 100Hz) caused the system to hang or reset whenever a finger twitched.&lt;/span&gt;&lt;span&gt; We replaced this with a &lt;/span&gt;&lt;b data-path-to-node="19" data-index-in-node="180"&gt;non-blocking sliding window and timeout mechanism&lt;/b&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; allowing the firmware to recover instantly if contact was temporarily lost.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qfvrrf5" data-path-to-node="20"&gt;Milestone 3: Implementing Digital Filtering (DC Removal / High-Pass)&lt;/h3&gt;
&lt;p data-path-to-node="21"&gt;&lt;span&gt;To strip away slow baseline drifts (such as skin deformation or changing pressure),&lt;/span&gt;&lt;span&gt; we implemented a recursive Infinite Impulse Response (&lt;/span&gt;&lt;b data-path-to-node="21" data-index-in-node="138"&gt;IIR&lt;/b&gt;&lt;span&gt;) filter:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/DigitalFiltering.jpg" /&gt;&lt;/p&gt;
&lt;p data-path-to-node="24"&gt;&lt;span&gt;Setting the smoothing factor to &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="33"&gt;alpha = 0.95&lt;/span&gt;&lt;span&gt; effectively isolated the clean AC pulse wave.&lt;/span&gt;&lt;span&gt; Furthermore,&lt;/span&gt;&lt;span&gt; we added a &lt;/span&gt;&lt;b data-path-to-node="24" data-index-in-node="117"&gt;1.5-second warm-up phase&lt;/b&gt;&lt;span&gt; upon finger placement to initialize the filter smoothly and prevent startup transient spikes.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qfvrrf6" data-path-to-node="25"&gt;Milestone 4: Motion Artifact Detection &amp;amp; Signal Quality Control&lt;/h3&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;Optical sensors are notoriously sensitive to movement.&lt;/span&gt;&lt;span&gt; We added real-time delta tracking &lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/MotionArtifact.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;If a sudden spike exceeds the safety threshold (&lt;/span&gt;&lt;code data-path-to-node="26" data-index-in-node="236"&gt;8000&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; the sample is discarded,&lt;/span&gt;&lt;span&gt; and a status message (&lt;/span&gt;&lt;code data-path-to-node="26" data-index-in-node="290"&gt;{&amp;quot;status&amp;quot;: &amp;quot;Motion detected - keep finger still&amp;quot;}&lt;/code&gt;&lt;span&gt;) is sent instead of corrupted BPM values.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;span style="font-size:150%;"&gt;Maximizing MAXREFDES117 (MAX30102) Performance on Difficult Body Locations (e.g., Wrist)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Placing the PPG sensor on the wrist or forearm significantly attenuates the blood volume pulse signal, introducing heavy motion and muscle noise. To overcome this using an STM32 microcontroller, you must transition to non-blocking register management, apply digital band-pass filtering, implement an adaptive peak detection algorithm, and re-calibrate the SpO₂ R-curve.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Modifying Sample Rate (SPS) and Register Configurations&lt;/strong&gt;&lt;br /&gt;Default libraries often configure the sensor for power-saving mode with lower resolution. For difficult locations, you must increase the LED drive current and lengthen the pulse width (LED_PW) to ensure the light penetrates deeper tissue layers.&lt;br /&gt;Using the standard SparkFun MAX30105 Library (which is fully compatible with the MAX30102 on your MAXREFDES117 board), configure the parameters in your setup() function as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;Wire.h&amp;gt;
#include &amp;quot;MAX30105.h&amp;quot; // Works perfectly with the MAX30102 chip on the MAXREFDES117 board

MAX30105 particleSensor;

void setup() {
  Serial.begin(115200);
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println(&amp;quot;Sensor not found!&amp;quot;);
    while (1);
  }

  // --- HARDWARE OPTIMIZATION FOR DIFFICULT LOCATIONS ---
  
  byte ledBrightness = 0x3F; // High LED current (~12.6mA to 50mA depending on setup) - deeper tissue penetration
  byte sampleAverage = 4;    // On-chip sample averaging (1, 2, 4, 8, 16, 32) - filters high-frequency noise
  byte ledMode = 2;          // Mode: 2 = Red + IR (Required for both SpO2 and Heart Rate)
  
  // Increasing the Sample Rate (SPS) improves the precision of the captured PPG wave shape
  int sampleRate = 400;      // Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  
  // Extending Pulse Width increases the internal ADC resolution (411us = 18-bit)
  int pulseWidth = 411;      // Options: 69 (15-bit), 118 (16-bit), 215 (17-bit), 411 (18-bit)

  // Load custom configurations into the sensor registers
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, 4096);
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Golden Rule for Wrists: Set sampleRate = 400 or 800 and pulseWidth = 411. The maximum 18-bit ADC resolution allows the sensor to capture miniscule volumetric changes in the bloodstream that are otherwise dampened by thicker skin.&lt;br /&gt;&amp;nbsp; &amp;nbsp; On-Chip Averaging: Setting sampleAverage = 4 averages the samples directly inside the sensor&amp;#39;s hardware FIFO, delivering a smoother signal to your microcontroller.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;Eliminating Ambient Light Noise and Filtering Signal Waves&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;br /&gt;The MAX30102 features built-in hardware Ambient Light Cancellation (ALC). It measures the background light while the LEDs are turned off and subtracts it from the active measurement. However, rapid ambient changes (like 50Hz/60Hz indoor fluorescent lighting or direct sunlight) can still saturate the ADC.&lt;br /&gt;To fix this, you must apply both software filtering and physical isolation:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;A. Digital Band-Pass Filter (Removing Muscle Noise and Baseline Drift)&lt;/strong&gt;&lt;br /&gt;Wrist movement introduces baseline wander (low-frequency drifting), while muscle micro-tremors introduce high-frequency hiss. The code below implements a digital band-pass filter (a combination of High-Pass and Low-Pass) that isolates the AC component, cutting off everything below ~0.5 Hz (30 BPM) and above ~5 Hz (300 BPM).&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;Wire.h&amp;gt;
#include &amp;quot;MAX30105.h&amp;quot;

MAX30105 particleSensor;

// Filter coefficients (Tuned for ~100 Hz effective sampling rate after averaging)
const float alpha_hp = 0.95; // High-Pass filter coefficient (Cuts DC baseline wander)
const float alpha_lp = 0.25; // Low-Pass filter coefficient (Smooths muscle noise)

float dc_offset = 0;
float filtered_signal = 0;

void loop() {
  // Read raw Infrared (IR) values - IR provides a more stable heart rate wave than Red
  uint32_t raw_ir = particleSensor.getIR(); 

  if (raw_ir &amp;gt; 50000) { // Skin-proximity check (ensures a body part is touching the sensor)
    
    // 1. HIGH-PASS FILTER (Removes DC component and baseline wandering)
    dc_offset = (alpha_hp * dc_offset) + ((1.0 - alpha_hp) * raw_ir);
    float ac_component = raw_ir - dc_offset;

    // 2. LOW-PASS FILTER (Smooths high-frequency muscle tremors)
    filtered_signal = (alpha_lp * ac_component) + ((1.0 - alpha_lp) * filtered_signal);

    // Output to the Arduino IDE Serial Plotter to visualize a clean PPG wave
    Serial.print(&amp;quot;Raw_AC:&amp;quot;);
    Serial.print(ac_component); // For reference
    Serial.print(&amp;quot;,&amp;quot;);
    Serial.print(&amp;quot;Filtered_AC:&amp;quot;);
    Serial.println(filtered_signal);

  } else {
    // Sensor is off the skin
    Serial.println(&amp;quot;No Signal (Place sensor against skin)&amp;quot;);
    dc_offset = 0;
    filtered_signal = 0;
  }
  
  delay(10); // Matches the loop execution to the ~100Hz effective sampling rate
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;B. Physical Optical Isolation&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;3D Print a Matte Black Enclosure: Your custom casing must include a physical wall separating the LEDs from the photodetector on the MAXREFDES117 PCB. This prevents optical crosstalk (light traveling sideways through the plastic enclosure directly into the sensor without entering the skin).&lt;br /&gt;Use a Black Foam Gasket: Place a small ring of dense, black neoprene foam or rubber around the sensor perimeter. When strapped to the body, it compresses and blocks external light leaks entirely.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;Stabilization of Mechanical Contact Pressure&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;br /&gt;PPG signal response to contact pressure follows a bell-shaped (U-shaped) curve:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Too Loose: The sensor records air movements, ambient light leaks, and loses contact immediately during movement.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Too Tight: The sensor compresses the local capillaries, blocking microvascular blood flow entirely. This causes the PPG amplitude to vanish.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;To achieve consistent, optimal pressure (optimum transmural pressure), use these mechanical techniques:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Elastic Hook-and-Loop (Velcro) Band: Avoid stiff, solid plastic watch bands. Use an elastic material that stretches slightly to absorb muscle expansions (e.g., when making a fist) while keeping the sensor tension uniform.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Spring-Loaded Module Housing: Design an enclosure where the MAXREFDES117 PCB sits on top of a soft miniature spring or silicone sponge cushion inside the strap capsule. This maintains a light, continuous push against the skin, regardless of how tightly the main strap is pulled.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Double-Sided Medical Adhesive Tape: If testing on the forehead or forearm, using biocompatible, hypoallergenic double-sided medical tape provides the cleanest signal. Cutting a hole for the optics and adhering the sensor directly to the skin completely eliminates motion artifacts.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;br /&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;Non-Blocking STM32 Architecture (C/HAL) and SpO₂ Processing&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;To calculate SpO₂, you must extract the AC and DC values for both the Red and IR channels simultaneously to compute the Ratio of Ratios (R):&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/R-equation.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Polling the sensor using delay() fails on STM32 because the sampling intervals must be mathematically uniform. Instead, connect the INT pin of the MAXREFDES117 to an STM32 GPIO External Interrupt (EXTI) pin. When the sensor fills its FIFO, it pulls the INT pin low, triggering the STM32 to fetch data via I2C asynchronously.&lt;br /&gt;Here is the implementation of the SpO₂ extraction algorithm in C for STM32:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;quot;main.h&amp;quot;
#include &amp;lt;math.h&amp;gt;

#define BUFFER_SIZE  100  // Window size (100 samples = 1 second at 100Hz effective sampling)

// Global filter variables (separated for Red and IR channels)
float dc_red = 0.0f;
float dc_ir = 0.0f;
const float alpha = 0.98f; // IIR low-pass coefficient to isolate the DC baseline

// Sliding buffers for AC wave analysis
float ac_red_buffer[BUFFER_SIZE];
float ac_ir_buffer[BUFFER_SIZE];
uint16_t buffer_index = 0;

extern I2C_HandleTypeDef hi2c1; // Assumes your STM32 HAL I2C setup

/**
 * @brief Processes a single raw sample packet (called inside your non-blocking main loop when INT fires)
 */
void Process_PPG_Sample(uint32_t raw_red, uint32_t raw_ir) 
{
    // 1. Extract the DC component using an IIR Low-Pass Filter
    dc_red = (alpha * dc_red) + ((1.0f - alpha) * (float)raw_red);
    dc_ir = (alpha * dc_ir) + ((1.0f - alpha) * (float)raw_ir);

    // 2. Isolate the AC component by removing the DC offset
    float ac_red = (float)raw_red - dc_red;
    float ac_ir = (float)raw_ir - dc_ir;

    // 3. Store the filtered AC waves into the analysis arrays
    ac_red_buffer[buffer_index] = ac_red;
    ac_ir_buffer[buffer_index] = ac_ir;
    buffer_index++;

    // 4. Once the window is full (1 second of data), compute SpO2
    if (buffer_index &amp;gt;= BUFFER_SIZE) 
    {
        // Proximity validation: Ensure the sensor is actually resting on tissue
        if (dc_red &amp;gt; 50000.0f &amp;amp;&amp;amp; dc_ir &amp;gt; 50000.0f) 
        {
            Calculate_SpO2(dc_red, dc_ir);
        }
        buffer_index = 0; // Reset window index
    }
}

/**
 * @brief Calculates SpO2 using Peak-to-Peak amplitudes of the collected AC waves
 */
void Calculate_SpO2(float dc_r, float dc_i)
{
    float min_red = 999999.0f, max_red = -999999.0f;
    float min_ir = 999999.0f, max_ir = -999999.0f;

    // Locate the peaks and troughs within the 1-second window
    for (int i = 0; i &amp;lt; BUFFER_SIZE; i++) 
    {
        if (ac_red_buffer[i] &amp;gt; max_red) max_red = ac_red_buffer[i];
        if (ac_red_buffer[i] &amp;lt; min_red) min_red = ac_red_buffer[i];

        if (ac_ir_buffer[i] &amp;gt; max_ir) max_ir = ac_ir_buffer[i];
        if (ac_ir_buffer[i] &amp;lt; min_ir) min_ir = ac_ir_buffer[i];
    }

    // Determine Peak-to-Peak amplitudes (AC component size)
    float ac_r_p2p = max_red - min_red;
    float ac_i_p2p = max_ir - min_ir;

    if (ac_i_p2p &amp;gt; 0 &amp;amp;&amp;amp; dc_r &amp;gt; 0) 
    {
        // Compute the Ratio of Ratios (R)
        float R = (ac_r_p2p / dc_r) / (ac_i_p2p / dc_i);

        // Empirical calibration curve equation: SpO2 = A - B * R
        // Generic medical constants for MAX30102 on fingertips: A = 104.0, B = 17.0
        float spo2 = 104.0f - (17.0f * R);

        // Constrain to realistic physiological limits
        if (spo2 &amp;gt; 100.0f) spo2 = 100.0f;
        if (spo2 &amp;lt; 60.0f)  spo2 = 60.0f;

        // Print output to UART or send to an integrated OLED display
        printf(&amp;quot;Calculated SpO2: %.2f %%\r\n&amp;quot;, spo2);
    }
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;Calibrating the SpO₂ Curve for Wrist Placement&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;br /&gt;The default linear equation used above (SpO2 = 104.0 - 17.0 &amp;sdot; R) is calibrated for fingertips, where light easily reflects off dense, shallow capillary beds. Leaving this unchanged for a wrist monitor will yield inaccurate, drifting numbers.&lt;br /&gt;To fix this, developers utilize a second-degree polynomial calibration curve:&lt;br /&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/SpO2-equation.jpg" /&gt;&lt;br /&gt;Calibration Procedure:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Attach a certified, medical-grade reference pulse oximeter to the subject&amp;#39;s fingertip.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Mount your STM32-driven MAXREFDES117 device securely to their wrist, outputting the raw, uncalibrated values of R over UART.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Have the subject safely induce a minor drop in oxygen saturation (e.g., holding their breath for 30&amp;ndash;40 seconds until the medical finger oximeter registers a drop down to ~93-94%).&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Log the data pairs: the true SpO2 from the medical device alongside the raw value of R calculated by your STM32 at that exact second.&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node="26"&gt;&lt;span&gt;Import the log into Excel, MATLAB, or a Python script and apply a polynomial regression fit (Polynomial Fit / Linear Regression). This will generate custom A, B, and C coefficients unique to your custom wrist band assembly and housing pressure.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qfvrrf7" class="" data-path-to-node="28"&gt;4. Complete Source Code (&lt;code data-path-to-node="28" data-index-in-node="25"&gt;src/main.cpp&lt;/code&gt;)&lt;/h2&gt;
&lt;p data-path-to-node="29"&gt;&lt;span&gt;Here is the final,&lt;/span&gt;&lt;span&gt; stable,&lt;/span&gt;&lt;span class=""&gt; and production-ready C++ firmware for &lt;/span&gt;&lt;b data-path-to-node="29" data-index-in-node="65"&gt;PlatformIO&lt;/b&gt;&lt;span&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;div class="code-block ng-tns-c2381765539-295 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" style="display:block;" data-hveid="0" data-ved="0CAAQhtANahgKEwj4yPbPi9aXAxUAAAAAHQAAAAAQoQQ"&gt;
&lt;div class="formatted-code-block-internal-container ng-tns-c2381765539-295"&gt;
&lt;div class="animated-opacity ng-tns-c2381765539-295"&gt;
&lt;div class="code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2381765539-295 ng-star-inserted"&gt;&lt;span class="ng-tns-c2381765539-295"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;Arduino.h&amp;gt;
#include &amp;lt;Wire.h&amp;gt;
#include &amp;quot;MAX30105.h&amp;quot;

MAX30105 particleSensor;

// Pulse detection and BPM averaging variables
unsigned long lastBeat = 0;
long lastFilteredIR = 0;
int beatAvg = 0;
const int RATE_SIZE = 8;
byte rates[RATE_SIZE];
byte rateSpot = 0;

// Digital filter variables (DC Removal / High-Pass Filter)
float dcVal = 0;
const float alpha = 0.95; // Smoothing factor for IIR filter

// Startup stabilization (Warm-up phase)
unsigned long fingerTouchTime = 0;
bool isFilterStable = false;

// Transmission interval control
unsigned long lastPrintTime = 0;
const long printInterval = 500; // Send JSON frame every 500 ms

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println(&amp;quot;--- STM32 PULSE OXIMETER SYSTEM (MAX30102) ---&amp;quot;);

  Wire.begin();

  // Initialize MAX30102 sensor via I2C
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println(&amp;quot;{\&amp;quot;error\&amp;quot;: \&amp;quot;MAX30102 not found! Check wiring.\&amp;quot;}&amp;quot;);
    while (1);
  }

  // Sensor configuration: 
  // LED Brightness = 60, Sample Averaging = 4, Mode = 2 (Red + IR), 
  // Sample Rate = 400 Hz, Pulse Width = 411 us, ADC Range = 4096
  particleSensor.setup(60, 4, 2, 400, 411, 4096);
  Serial.println(&amp;quot;{\&amp;quot;status\&amp;quot;: \&amp;quot;Sensor ready. Place your finger.\&amp;quot;}\n&amp;quot;);
}

void loop() {
  // Process sensor FIFO buffer in a non-blocking manner
  particleSensor.check();

  if (particleSensor.available()) {
    long rawIR = particleSensor.getIR();
    long rawRed = particleSensor.getRed();
    particleSensor.nextSample();

    // 1. Check finger presence on sensor
    if (rawIR &amp;lt; 50000) {
      if (millis() - lastPrintTime &amp;gt; 1000) {
        Serial.println(&amp;quot;{\&amp;quot;status\&amp;quot;: \&amp;quot;No finger on sensor\&amp;quot;}&amp;quot;);
        lastPrintTime = millis();
      }
      beatAvg = 0;
      isFilterStable = false;
      dcVal = 0; // Reset filter state when finger is removed
      return;
    }

    // 2. Filter warm-up stabilization phase after finger contact (1.5 seconds)
    if (!isFilterStable) {
      if (fingerTouchTime == 0) {
        fingerTouchTime = millis();
        dcVal = rawIR; // Seed the filter state with initial raw reading
      }
      
      // Warm up filter state in the background
      dcVal = (alpha * dcVal) + ((1.0 - alpha) * (float)rawIR);
      
      if (millis() - fingerTouchTime &amp;gt; 1500) {
        isFilterStable = true; // Warm-up complete, ready for pulse detection
      }
      return;
    } else {
      fingerTouchTime = 0;
    }

    // 3. Motion Artifact Detection (sudden amplitude delta monitoring)
    static long previousRawIR = rawIR;
    long irDelta = abs(rawIR - previousRawIR);
    previousRawIR = rawIR;

    if (irDelta &amp;gt; 8000) { // Safety threshold for sudden movement/jerk
      if (millis() - lastPrintTime &amp;gt; 500) {
        Serial.println(&amp;quot;{\&amp;quot;status\&amp;quot;: \&amp;quot;Motion detected - keep finger still\&amp;quot;}&amp;quot;);
        lastPrintTime = millis();
      }
      return; // Skip sample to prevent corrupted BPM readings
    }

    // 4. Digital High-Pass Filter (DC Removal)
    dcVal = (alpha * dcVal) + ((1.0 - alpha) * (float)rawIR);
    float filteredIR = (float)rawIR - dcVal;

    // 5. Peak Detection &amp;amp; Moving Average BPM Calculation
    unsigned long currentTime = millis();
    static bool falling = false;
    static float peakValue = 0;

    if (filteredIR &amp;gt; lastFilteredIR) {
      if (falling) falling = false;
      if (filteredIR &amp;gt; peakValue) peakValue = filteredIR;
    } else if (filteredIR &amp;lt; lastFilteredIR) {
      if (!falling &amp;amp;&amp;amp; (peakValue - filteredIR &amp;gt; 10.0)) { // Peak threshold limit
        falling = true;
        
        long delta = currentTime - lastBeat;
        if (delta &amp;gt; 300 &amp;amp;&amp;amp; delta &amp;lt; 2000) { // Valid HR pulse interval (30 to 200 BPM)
          long beatsPerMinute = 60000 / delta;
          if (beatsPerMinute &amp;gt; 45 &amp;amp;&amp;amp; beatsPerMinute &amp;lt; 180) { // Plausible HR range
            rates[rateSpot++] = (byte)beatsPerMinute;
            rateSpot %= RATE_SIZE;

            beatAvg = 0;
            for (byte x = 0; x &amp;lt; RATE_SIZE; x++) {
              beatAvg += rates[x];
            }
            beatAvg /= RATE_SIZE;
          }
        }
        lastBeat = currentTime;
        peakValue = filteredIR;
      }
    }
    lastFilteredIR = filteredIR;

    // 6. Empirical SpO2 Estimation based on Red/IR Ratio
    int estimatedSpO2 = 0;
    if (rawIR &amp;gt; 100000 &amp;amp;&amp;amp; rawRed &amp;gt; 50000) {
      float ratio = (float)rawRed / (float)rawIR;
      float spo2Calc = 110.0 - (25.0 * ratio);
      
      if (spo2Calc &amp;gt; 95.0 &amp;amp;&amp;amp; spo2Calc &amp;lt;= 100.0) estimatedSpO2 = 98;
      else if (spo2Calc &amp;gt; 90.0) estimatedSpO2 = 96;
      else estimatedSpO2 = 93;
    }

    // 7. Data streaming via USB CDC in JSON format every 500 ms
    if (millis() - lastPrintTime &amp;gt;= printInterval) {
      Serial.print(&amp;quot;{\&amp;quot;bpm\&amp;quot;: &amp;quot;);
      Serial.print(beatAvg &amp;gt; 0 ? beatAvg : 0);
      Serial.print(&amp;quot;, \&amp;quot;spo2\&amp;quot;: &amp;quot;);
      Serial.print(beatAvg &amp;gt; 0 ? estimatedSpO2 : 0);
      Serial.print(&amp;quot;, \&amp;quot;filtered_ir\&amp;quot;: &amp;quot;);
      Serial.print(filteredIR, 2);
      Serial.println(&amp;quot;}&amp;quot;);

      lastPrintTime = millis();
    }
  }
}&lt;/pre&gt;
&lt;pre class="ng-tns-c2381765539-295"&gt;&lt;code class="code-container formatted ng-tns-c2381765539-295" data-test-id="code-content"&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="mcetoc_1k5qfvrrf8" data-path-to-node="32"&gt;5. Output Data Stream Example&lt;/h2&gt;
&lt;p data-path-to-node="33"&gt;&lt;span&gt;Structured JSON formatting allows seamless integration with external dashboard apps or Python visualization scripts:&lt;/span&gt;&lt;/p&gt;
&lt;div class="code-block ng-tns-c2381765539-296 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" style="display:block;" data-hveid="0" data-ved="0CAAQhtANahgKEwj4yPbPi9aXAxUAAAAAHQAAAAAQogQ"&gt;
&lt;div class="formatted-code-block-internal-container ng-tns-c2381765539-296"&gt;
&lt;div class="animated-opacity ng-tns-c2381765539-296"&gt;
&lt;div class="code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2381765539-296 ng-star-inserted"&gt;&lt;span class="ng-tns-c2381765539-296"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;pre class="ui-code" data-mode="text"&gt;JSON

{&amp;quot;bpm&amp;quot;: 73, &amp;quot;spo2&amp;quot;: 98, &amp;quot;filtered_ir&amp;quot;: 4425.22}
{&amp;quot;bpm&amp;quot;: 73, &amp;quot;spo2&amp;quot;: 98, &amp;quot;filtered_ir&amp;quot;: 3095.70}
{&amp;quot;status&amp;quot;: &amp;quot;Motion detected - keep finger still&amp;quot;}
{&amp;quot;bpm&amp;quot;: 73, &amp;quot;spo2&amp;quot;: 98, &amp;quot;filtered_ir&amp;quot;: 935.17}&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;p data-path-to-node="0"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qfvrrf8" data-path-to-node="32"&gt;6.&amp;nbsp;Impact of Sensor Application Site on PPG Signal Quality and SpO₂ Measurements&lt;/h2&gt;
&lt;p data-path-to-node="0"&gt;Placing the MAXREFDES117 sensor (based on the MAX30102 photoplethysmography (PPG) chip) on different parts of the body has a crucial impact on the accuracy, signal strength, and stability of heart rate and pulse oximetry (SpO2) results. Since the sensor operates on a reflective method (reflection of red and infrared light from blood vessels), the results directly depend on skin thickness, the degree of blood perfusion (tissue perfusion), and the susceptibility of a given site to movement.&lt;br /&gt;Below is an overview of how specific locations affect measurements:&lt;/p&gt;
&lt;p data-path-to-node="0"&gt;1. Fingertip &amp;ndash; Highest Accuracy&lt;/p&gt;
&lt;ul&gt;
&lt;li data-path-to-node="0"&gt;Impact on results: Provides the strongest and most stable PPG signal. Fingertips are densely vascularized (high perfusion), and capillaries are located close to the skin&amp;#39;s surface&lt;/li&gt;
&lt;li data-path-to-node="0"&gt;Characteristics: An ideal location for calibration and algorithm testing.&lt;/li&gt;
&lt;li data-path-to-node="0"&gt;Disadvantages: Highly susceptible to motion artifacts. Any finger twitch drastically falsifies the heart rate and SpO2 readings. Requires remaining motionless and maintaining constant, light pressure (too much pressure blocks blood flow, resulting in a zero reading).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2.&amp;nbsp;Earlobe &amp;ndash; Great Alternative&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Impact on results: Yields a very clean pulse signal, comparable in quality to the finger.&lt;/li&gt;
&lt;li&gt;Characteristics: The earlobe has thin skin and no muscle tissue, minimizing interference caused by muscle contractions. It is also less susceptible to whole-body movements than the hand.&lt;/li&gt;
&lt;li&gt;Disadvantages: Harder to attach the sensor (requires a clip). In low temperatures, rapid vasoconstriction occurs here, which can drastically reduce signal amplitude and make SpO2 readings impossible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3.&amp;nbsp;Forehead &amp;ndash; High Clinical Precision&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Impact on results: Studies show that placing the MAX30102 sensor on the forehead achieves over 99% accuracy in SpO2 measurements compared to stationary devices.&lt;/li&gt;
&lt;li&gt;Characteristics: Blood circulation in the forehead area (supratrochlear artery) is exceptionally stable and less prone to weakening during shock or body cooling. This site works great for sleep monitoring systems.&lt;/li&gt;
&lt;li&gt;Disadvantages: Requires thorough cleansing of the skin from sebum and complete blocking of ambient light (the sensor must be covered, e.g., with a headband).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4.&amp;nbsp;Wrist and Forearm &amp;ndash; Most Problematic&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Impact on results: The signal is significantly weaker (low amplitude), and heart rate and blood oxygenation results are most susceptible to errors&lt;/li&gt;
&lt;li data-path-to-node="9,1,0"&gt;Characteristics: Although this is the default location for smartwatches, skin on the wrist is thicker, and arteries and capillaries lie deeper.&lt;/li&gt;
&lt;li data-path-to-node="9,1,0"&gt;Disadvantages: The standard, simplified algorithm provided by the manufacturer for Arduino/mbed boards (which processes small data packets at a sampling rate of 25&amp;ndash;100 samples per second) typically fails to read SpO2 on the wrist. To obtain correct results here, it is necessary to apply advanced digital filters to filter out noise and press the strap very firmly against the skin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Summary of Physical Parameters of the Application Site:&lt;/strong&gt;&lt;/p&gt;
&lt;table data-path-to-node="11"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td&gt;Body Part&lt;/td&gt;
&lt;td&gt;Signal Strength (Perfusion)&lt;/td&gt;
&lt;td&gt;Susceptibility to Interference (Motion)&lt;/td&gt;
&lt;td&gt;Suitability for Default MAXREFDES117 Algorithm&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fingertip&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Ideal (Recommended for testing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Earlobe&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Very Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forehead&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Very Good (Requires light isolation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrist&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;Poor (Requires code modification and noise filtering)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Main rule: If you are building a prototype using the default source code from Analog Devices / SparkFun libraries, stick to the finger or earlobe. Choosing the wrist will force you to deeply modify the software and filter out noise associated with movement and tissue thickness.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qfvrrf8" data-path-to-node="32"&gt;7. Measures Implemented to Mitigate Measurement Issues&lt;/h2&gt;
&lt;h3 id="mcetoc_1k5u20e0q1" data-path-to-node="4"&gt;1. Optimization of Sensor Operating Parameters and Registers&lt;/h3&gt;
&lt;p data-path-to-node="5"&gt;&lt;span&gt;Default settings provided by basic programming libraries (such as SparkFun or Maxim Integrated) prioritize energy saving,&lt;/span&gt;&lt;span&gt; which results in insufficient measurement resolution.&lt;/span&gt;&lt;span&gt; To enable light to penetrate deeper tissue layers in diagnostically challenging locations,&lt;/span&gt;&lt;span&gt; the chip&amp;#39;s register parameters were modified:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="6"&gt;
&lt;li&gt;
&lt;p data-path-to-node="6,0,0"&gt;&lt;b data-path-to-node="6,0,0" data-index-in-node="0"&gt;Increasing optical power and resolution:&lt;/b&gt;&lt;span&gt; In the setup configuration section (&lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="77"&gt;setup()&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; the LED supply current was increased (parameter &lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="135"&gt;ledBrightness&lt;/code&gt;&lt;span&gt; set to &lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="156"&gt;0x3F&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; corresponding to a range of approx.&lt;/span&gt;&lt;span&gt; 12.&lt;/span&gt;&lt;span&gt;6 mA to 50 mA) and the pulse duration was extended (&lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="253"&gt;pulseWidth = 411&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; corresponding to &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="288"&gt;411s)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; This achieved the maximum 18-bit analog-to-digital converter (ADC) resolution (for comparison,&lt;/span&gt;&lt;span&gt; the lowest resolution is 15-bit at &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="437"&gt;69s&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt; Higher resolution is crucial for the wrist,&lt;/span&gt;&lt;span&gt; as it allows the system to capture very small changes in light reflection that are heavily attenuated by thicker skin.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="6,1,0"&gt;&lt;b data-path-to-node="6,1,0" data-index-in-node="0"&gt;Raising the sampling rate and hardware filtering:&lt;/b&gt;&lt;span&gt; The sampling rate (&lt;/span&gt;&lt;code data-path-to-node="6,1,0" data-index-in-node="69"&gt;sampleRate&lt;/code&gt;&lt;span&gt;) was increased to &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="98"&gt;400Hz&lt;/span&gt;&lt;span&gt; (available ranges span from &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="141"&gt;50H&lt;/span&gt;&lt;span&gt; to &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="158"&gt;3200Hz&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt; A higher SPS significantly improves the precision of PPG waveform shape detection.&lt;/span&gt;&lt;span&gt; Additionally,&lt;/span&gt;&lt;span&gt; hardware-level sample averaging was enabled (&lt;/span&gt;&lt;code data-path-to-node="6,1,0" data-index-in-node="318"&gt;sampleAverage = 4&lt;/code&gt;&lt;span&gt; from available options of 1,&lt;/span&gt;&lt;span&gt; 2,&lt;/span&gt;&lt;span&gt; 4,&lt;/span&gt;&lt;span&gt; 8,&lt;/span&gt;&lt;span&gt; 16,&lt;/span&gt;&lt;span&gt; 32).&lt;/span&gt;&lt;span&gt; This smooths the signal and removes minor high-frequency noise before data is transferred to the microcontroller.&lt;/span&gt;&lt;span&gt; The sensor was configured in dual mode (&lt;/span&gt;&lt;code data-path-to-node="6,1,0" data-index-in-node="537"&gt;ledMode = 2&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; activating both the red and infrared LEDs,&lt;/span&gt;&lt;span&gt; which is necessary for simultaneous heart rate and blood oxygen saturation (&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="670"&gt;SpO2&lt;/span&gt;&lt;span&gt;) measurements.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node="7"&gt;&lt;span&gt;For locations like the wrist,&lt;/span&gt;&lt;span&gt; the &amp;quot;golden rule&amp;quot; configuration adopted was &lt;/span&gt;&lt;code data-path-to-node="7" data-index-in-node="74"&gt;sampleRate = 400&lt;/code&gt;&lt;span&gt; or &lt;/span&gt;&lt;code data-path-to-node="7" data-index-in-node="94"&gt;800&lt;/code&gt;&lt;span&gt; at &lt;/span&gt;&lt;code data-path-to-node="7" data-index-in-node="101"&gt;pulseWidth = 411&lt;/code&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5u20e0q2" data-path-to-node="9"&gt;2. Elimination of Ambient Light Interference&lt;/h3&gt;
&lt;p data-path-to-node="10"&gt;&lt;span&gt;Although the MAX30102 chip features a built-in hardware Ambient Light Cancellation (ALC) system&amp;mdash;which works by measuring background light when LEDs are turned off and subtracting it from the actual measurement&amp;mdash;strong or fluctuating illumination (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; sunlight or &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="264"&gt;50Hz/60Hz&lt;/span&gt;&lt;span&gt; fluorescent flicker) can saturate the ADC.&lt;/span&gt;&lt;span&gt; This problem was addressed through a dual-track approach:&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node="11"&gt;Software Filtering (High-Pass Filter &amp;ndash; HPF)&lt;/h4&gt;
&lt;p data-path-to-node="12"&gt;&lt;span&gt;Both ambient light and slow movement of the sensor across the skin cause &lt;/span&gt;&lt;i data-path-to-node="12" data-index-in-node="73"&gt;baseline wander&lt;/i&gt;&lt;span&gt; (drift of the isoelectric line).&lt;/span&gt;&lt;span&gt; A digital high-pass filter (IIR / simple exponential filter or Butterworth filter) with a coefficient of &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="227"&gt;alpha = 0.95&lt;/span&gt;&lt;span&gt; (within the &lt;/span&gt;&lt;span class="math-inline" data-math="0.90" data-index-in-node="253"&gt;0.90&lt;/span&gt;&lt;span&gt;&amp;ndash;&lt;/span&gt;&lt;span class="math-inline" data-math="0.99" data-index-in-node="258"&gt;0.99&lt;/span&gt;&lt;span&gt; range) was implemented in the code.&lt;/span&gt;&lt;span&gt; This filter calculates the DC component (&lt;/span&gt;&lt;code data-path-to-node="12" data-index-in-node="340"&gt;dc_offset&lt;/code&gt;&lt;span&gt;) and subtracts it from the raw reading (&lt;/span&gt;&lt;code data-path-to-node="12" data-index-in-node="390"&gt;raw_sample&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; effectively cutting off signal drift and leaving only a clean,&lt;/span&gt;&lt;span&gt; pulsating AC component that reflects blood vessel activity.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node="13"&gt;Physical Optical Isolation&lt;/h4&gt;
&lt;ul data-path-to-node="14"&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,0,0"&gt;&lt;b data-path-to-node="14,0,0" data-index-in-node="0"&gt;Dedicated 3D-printed enclosure with a partition:&lt;/b&gt;&lt;span&gt; An enclosure printed from black,&lt;/span&gt;&lt;span&gt; matte filament (PLA/PETG) was used,&lt;/span&gt;&lt;span&gt; featuring a physical wall (partition) separating the emitting LEDs from the photodetector on the MAXREFDES117 board.&lt;/span&gt;&lt;span&gt; This partition makes direct contact with the skin and completely eliminates &lt;/span&gt;&lt;i data-path-to-node="14,0,0" data-index-in-node="311"&gt;optical crosstalk&lt;/i&gt;&lt;span&gt; (light passing directly from the LEDs to the sensor through the plastic or the top layer of skin,&lt;/span&gt;&lt;span&gt; bypassing blood vessels).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,1,0"&gt;&lt;b data-path-to-node="14,1,0" data-index-in-node="0"&gt;Foam sealing:&lt;/b&gt;&lt;span&gt; A sealing ring made of thin,&lt;/span&gt;&lt;span&gt; dense,&lt;/span&gt;&lt;span&gt; black neoprene foam (or rubber) was placed around the sensor.&lt;/span&gt;&lt;span&gt; When the module is pressed against the skin (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; on the forehead or wrist),&lt;/span&gt;&lt;span&gt; the foam forms a tight barrier,&lt;/span&gt;&lt;span&gt; cutting off external light ingress.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5u20e0q3" data-path-to-node="16"&gt;3. Stabilization of Sensor Pressure on the Skin&lt;/h3&gt;
&lt;p data-path-to-node="17"&gt;&lt;span&gt;The proper pressure force of a PPG sensor follows a bell-shaped&lt;/span&gt;&lt;span&gt;&amp;nbsp;curve:&lt;/span&gt;&lt;span&gt; too little pressure causes the sensor to register air movement,&lt;/span&gt;&lt;span&gt; ambient light,&lt;/span&gt;&lt;span&gt; and lose tissue contact upon motion,&lt;/span&gt;&lt;span&gt; while too much pressure crushes capillaries and stops blood flow,&lt;/span&gt;&lt;span&gt; leading to a complete loss of the PPG waveform.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="18"&gt;&lt;span&gt;To achieve and maintain optimum transmural pressure,&lt;/span&gt;&lt;span&gt; three structural solutions were implemented:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="19"&gt;
&lt;li&gt;
&lt;p data-path-to-node="19,0,0"&gt;&lt;b data-path-to-node="19,0,0" data-index-in-node="0"&gt;Elastic damping strap:&lt;/b&gt;&lt;span&gt; The rigid plastic watch strap was replaced with a neoprene or Velcro band featuring an elastic insert.&lt;/span&gt;&lt;span&gt; The elasticity of the material compensates for sudden muscle tension (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; when clenching a fist),&lt;/span&gt;&lt;span&gt; maintaining constant pressure on the skin.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="19,1,0"&gt;&lt;b data-path-to-node="19,1,0" data-index-in-node="0"&gt;Spring-loaded design in the housing:&lt;/b&gt;&lt;span&gt; The sensor board was mounted inside the strap capsule on a soft spring or a piece of silicone foam.&lt;/span&gt;&lt;span&gt; As a result,&lt;/span&gt;&lt;span&gt; the spring generates a constant,&lt;/span&gt;&lt;span&gt; gentle pressing force regardless of how tightly the outer strap is pulled.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="19,2,0"&gt;&lt;b data-path-to-node="19,2,0" data-index-in-node="0"&gt;Medical double-sided tape:&lt;/b&gt;&lt;span&gt; For tests on the forehead and a cleaned forearm,&lt;/span&gt;&lt;span&gt; a dedicated hypoallergenic double-sided medical tape (such as those used for CGM sensors in diabetes care) was applied.&lt;/span&gt;&lt;span&gt; After cutting openings for the LEDs and photodetector,&lt;/span&gt;&lt;span&gt; the sensor was taped directly to the skin,&lt;/span&gt;&lt;span&gt; which almost entirely eliminated motion artifacts without the need for straps.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor</title><link>https://community.element14.com/thread/57382?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 21:19:06 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:00d6ac40-28e3-42dc-8f59-c85d17d841eb</guid><dc:creator>jelektro</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57382?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qep4cr0" data-path-to-node="5"&gt;1. Motivation &amp;amp; Background&lt;/h2&gt;
&lt;p data-path-to-node="6"&gt;When working with high-accuracy temperature sensors such as the &lt;b data-path-to-node="6" data-index-in-node="64"&gt;Maxim Integrated MAX30208&lt;/b&gt; (delivering clinical-grade accuracy), developers frequently encounter a major bottleneck: &lt;b data-path-to-node="6" data-index-in-node="247"&gt;vendor lock-in and restrictive software ecosystems&lt;/b&gt;.&lt;/p&gt;
&lt;p data-path-to-node="7"&gt;Official evaluation software provided by manufacturers is typically restricted exclusively to Windows, leaving Linux workstations, developer laptops running Ubuntu, and edge single-board computers (SBCs) like Raspberry Pi unsupported. Furthermore, proprietary tools often lack flexibility for multi-sensor scaling, real-time CSV streaming, or automated remote storage management.&lt;/p&gt;
&lt;p data-path-to-node="7"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/2630.MAX30208EVSYS.jpg" /&gt;&lt;/p&gt;
&lt;p data-path-to-node="8"&gt;To overcome these hardware and OS constraints, &lt;b data-path-to-node="8" data-index-in-node="47"&gt;MAX30208 EVSYS Desktop Monitor&lt;/b&gt; was engineered from scratch using modern &lt;b data-path-to-node="8" data-index-in-node="119"&gt;C++ and Qt6&lt;/b&gt;. It provides engineers and researchers with a responsive, multi-threaded telemetry station that runs seamlessly across Windows, Linux, and embedded SBC environments.&lt;/p&gt;
&lt;p data-path-to-node="8"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/GUI1.jpg" /&gt;&lt;/p&gt;
&lt;p data-path-to-node="8"&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/GUI.mp4"&gt;community.element14.com/.../GUI.mp4&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qep4cr1" data-path-to-node="10"&gt;2. Key Capabilities &amp;amp; Features&lt;/h2&gt;
&lt;ul data-path-to-node="11"&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,0,0"&gt;&lt;b data-path-to-node="11,0,0" data-index-in-node="0"&gt;Cross-Platform Portability:&lt;/b&gt; Built with CMake and Qt6, ensuring native execution on Windows, Linux, and ARM-based single-board computers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,1,0"&gt;&lt;b data-path-to-node="11,1,0" data-index-in-node="0"&gt;Plug &amp;amp; Play Auto-Detection:&lt;/b&gt; Automatically scans available system serial ports and connects to the evaluation kit using dynamic device descriptor matching, removing the need for manual COM port configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,2,0"&gt;&lt;b data-path-to-node="11,2,0" data-index-in-node="0"&gt;Non-Blocking Multi-Threaded Architecture:&lt;/b&gt; Utilizes a dedicated background thread (&lt;code data-path-to-node="11,2,0" data-index-in-node="82"&gt;SerialWorker&lt;/code&gt; + &lt;code data-path-to-node="11,2,0" data-index-in-node="97"&gt;QThread&lt;/code&gt;) combined with thread-safe Qt signals and slots, ensuring the user interface remains completely smooth and responsive during heavy polling or file I/O operations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,3,0"&gt;&lt;b data-path-to-node="11,3,0" data-index-in-node="0"&gt;Real-Time Multi-Channel Plotting (&lt;code data-path-to-node="11,3,0" data-index-in-node="34"&gt;QCustomPlot&lt;/code&gt;):&lt;/b&gt; Dynamically renders high-refresh-rate temperature curves for all sensors discovered on the I&amp;sup2;C bus, complete with zoom, pan, and live color-coded legends.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,4,0"&gt;&lt;b data-path-to-node="11,4,0" data-index-in-node="0"&gt;Interactive Vertical Thermometer Widget:&lt;/b&gt; Features an intuitive, gradient-styled vertical progress bar acting as a visual thermometer alongside the main plot for quick status checks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,5,0"&gt;&lt;b data-path-to-node="11,5,0" data-index-in-node="0"&gt;Hardware Register Map Viewer:&lt;/b&gt; Provides a custom &lt;code data-path-to-node="11,5,0" data-index-in-node="48"&gt;QAbstractTableModel&lt;/code&gt; interface to inspect, read (&lt;code data-path-to-node="11,5,0" data-index-in-node="96"&gt;r&lt;/code&gt;), and write (&lt;code data-path-to-node="11,5,0" data-index-in-node="111"&gt;w&lt;/code&gt;) internal device registers (&lt;code data-path-to-node="11,5,0" data-index-in-node="141"&gt;0x00&lt;/code&gt; to &lt;code data-path-to-node="11,5,0" data-index-in-node="149"&gt;0xFF&lt;/code&gt;) on the fly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,6,0"&gt;&lt;b data-path-to-node="11,6,0" data-index-in-node="0"&gt;Remote MicroSD Card Management:&lt;/b&gt; Enables users to check onboard storage status (&lt;code data-path-to-node="11,6,0" data-index-in-node="79"&gt;f&lt;/code&gt;), download internal log files (&lt;code data-path-to-node="11,6,0" data-index-in-node="112"&gt;g1&lt;/code&gt;), and clear storage memory (&lt;code data-path-to-node="11,6,0" data-index-in-node="143"&gt;g2&lt;/code&gt;) directly from the desktop GUI.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,7,0"&gt;&lt;b data-path-to-node="11,7,0" data-index-in-node="0"&gt;Streamlined Data Logging:&lt;/b&gt; Automatically captures real-time telemetry into structured CSV files (&lt;code data-path-to-node="11,7,0" data-index-in-node="96"&gt;.csv&lt;/code&gt;) for post-processing and compliance reporting.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1k5qep4cr2" data-path-to-node="13"&gt;3. System Architecture &amp;amp; Tech Stack&lt;/h2&gt;
&lt;ul data-path-to-node="14"&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,0,0"&gt;&lt;b data-path-to-node="14,0,0" data-index-in-node="0"&gt;Language:&lt;/b&gt; C++17&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,1,0"&gt;&lt;b data-path-to-node="14,1,0" data-index-in-node="0"&gt;Framework:&lt;/b&gt; Qt6 (Core, GUI, Widgets, SerialPort)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,2,0"&gt;&lt;b data-path-to-node="14,2,0" data-index-in-node="0"&gt;Charting Library:&lt;/b&gt; QCustomPlot&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,3,0"&gt;&lt;b data-path-to-node="14,3,0" data-index-in-node="0"&gt;Build System:&lt;/b&gt; CMake&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/image_5F00_8426dbe7.jpg" /&gt;&lt;/p&gt;
&lt;h1 id="mcetoc_1k5qepv023" data-path-to-node="2"&gt;UI Tabs &amp;amp; Functional Breakdown&lt;/h1&gt;
&lt;h2 id="mcetoc_1k5qepv024" data-path-to-node="3"&gt;1. Live Chart Tab (Main Dashboard)&lt;/h2&gt;
&lt;p data-path-to-node="4"&gt;The primary workspace designed for real-time telemetry observation and quick visual assessment.&lt;/p&gt;
&lt;ul data-path-to-node="5"&gt;
&lt;li&gt;
&lt;p data-path-to-node="5,0,0"&gt;&lt;b data-path-to-node="5,0,0" data-index-in-node="0"&gt;Top Compact Info Bar:&lt;/b&gt; Displays the current connection status (e.g., active COM port name) and a real-time numerical readout of the primary sensor&amp;#39;s temperature (&lt;code data-path-to-node="5,0,0" data-index-in-node="161"&gt;Live Value&lt;/code&gt;) formatted to three decimal places.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="5,1,0"&gt;&lt;b data-path-to-node="5,1,0" data-index-in-node="0"&gt;Vertical Thermometer Widget:&lt;/b&gt; Positioned on the left side, this gradient-styled vertical progress bar acts as a visual mercury column&amp;nbsp;that provides an intuitive, at-a-glance thermal indicator.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="5,2,0"&gt;&lt;b data-path-to-node="5,2,0" data-index-in-node="0"&gt;Multi-Channel &lt;code data-path-to-node="5,2,0" data-index-in-node="14"&gt;QCustomPlot&lt;/code&gt; Area:&lt;/b&gt; Occupies the main right-hand portion of the window. It renders smooth, color-coded temperature curves for all sensors discovered on the I&amp;sup2;C bus simultaneously. It features interactive zoom, pan, and a live legend.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/GUI1.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qepv025" data-path-to-node="6"&gt;2. Register Map Tab&lt;/h2&gt;
&lt;p data-path-to-node="7"&gt;An advanced hardware debugging interface providing transparent access to the internal register architecture of the MAX30208 sensors.&lt;/p&gt;
&lt;ul data-path-to-node="8"&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,0,0"&gt;&lt;b data-path-to-node="8,0,0" data-index-in-node="0"&gt;Interactive Table View (&lt;code data-path-to-node="8,0,0" data-index-in-node="24"&gt;QTableView&lt;/code&gt;):&lt;/b&gt; Powered by a custom &lt;code data-path-to-node="8,0,0" data-index-in-node="57"&gt;QAbstractTableModel&lt;/code&gt;, it displays all core device registers from address &lt;code data-path-to-node="8,0,0" data-index-in-node="129"&gt;0x00&lt;/code&gt; (Status) through &lt;code data-path-to-node="8,0,0" data-index-in-node="151"&gt;0xFF&lt;/code&gt; (Part Identifier).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,1,0"&gt;&lt;b data-path-to-node="8,1,0" data-index-in-node="0"&gt;Detailed Mapping:&lt;/b&gt; Columns explicitly outline the register &lt;b data-path-to-node="8,1,0" data-index-in-node="58"&gt;Address&lt;/b&gt;, &lt;b data-path-to-node="8,1,0" data-index-in-node="67"&gt;Register Name&lt;/b&gt;, current &lt;b data-path-to-node="8,1,0" data-index-in-node="90"&gt;Value (Hex)&lt;/b&gt;, and a functional &lt;b data-path-to-node="8,1,0" data-index-in-node="120"&gt;Description&lt;/b&gt; (e.g., FIFO configuration, high/low alarm thresholds, and GPIO settings).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/GUI2.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qepv026" data-path-to-node="9"&gt;3. Alarm Thresholds Tab&lt;/h2&gt;
&lt;p data-path-to-node="10"&gt;A dedicated control panel for configuring high and low temperature warning limits.&lt;/p&gt;
&lt;ul data-path-to-node="11"&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,0,0"&gt;&lt;b data-path-to-node="11,0,0" data-index-in-node="0"&gt;Input Controls:&lt;/b&gt; Allows engineers to specify precise high-temperature thresholds (e.g., default set to &lt;span class="math-inline" data-index-in-node="102"&gt;37.5&amp;#39;C&lt;/span&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,1,0"&gt;&lt;b data-path-to-node="11,1,0" data-index-in-node="0"&gt;Hardware Triggering:&lt;/b&gt; Clicking the &lt;i data-path-to-node="11,1,0" data-index-in-node="34"&gt;&amp;quot;Save Alarm High&amp;quot;&lt;/i&gt; button invokes background routines that automatically translate the floating-point Celsius value into 16-bit Two&amp;#39;s complement register bytes and writes them directly to the sensor&amp;#39;s threshold registers (&lt;code data-path-to-node="11,1,0" data-index-in-node="255"&gt;0x10&lt;/code&gt; and &lt;code data-path-to-node="11,1,0" data-index-in-node="264"&gt;0x11&lt;/code&gt;). When breached, the UI visually highlights the temperature label in warning red.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/GUI3.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qepv027" data-path-to-node="12"&gt;4. Event Log Tab&lt;/h2&gt;
&lt;p data-path-to-node="13"&gt;The system audit trail and diagnostic log viewer.&lt;/p&gt;
&lt;ul data-path-to-node="14"&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,0,0"&gt;&lt;b data-path-to-node="14,0,0" data-index-in-node="0"&gt;Chronological Tracking:&lt;/b&gt; Records significant background events, such as successful hardware initialization, device discovery counts, USB serial disconnections, auto-reconnect attempts, and critical hardware errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,1,0"&gt;&lt;b data-path-to-node="14,1,0" data-index-in-node="0"&gt;Timestamping:&lt;/b&gt; Every log entry is prefixed with an exact system timestamp (&lt;code data-path-to-node="14,1,0" data-index-in-node="74"&gt;hh:mm:ss&lt;/code&gt;) to aid in debugging communication drops or signal integrity issues.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/GUI4.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5qepv028" data-path-to-node="15"&gt;5. MicroSD Card Tab&lt;/h2&gt;
&lt;p data-path-to-node="16"&gt;An embedded storage management interface for the evaluation kit&amp;#39;s onboard logging capabilities.&lt;/p&gt;
&lt;ul data-path-to-node="17"&gt;
&lt;li&gt;
&lt;p data-path-to-node="17,0,0"&gt;&lt;b data-path-to-node="17,0,0" data-index-in-node="0"&gt;SD Status (&lt;code data-path-to-node="17,0,0" data-index-in-node="11"&gt;f&lt;/code&gt;):&lt;/b&gt; Queries the storage subsystem to verify if a card is present, formatted, and operational.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="17,1,0"&gt;&lt;b data-path-to-node="17,1,0" data-index-in-node="0"&gt;Download Logs (&lt;code data-path-to-node="17,1,0" data-index-in-node="15"&gt;g1&lt;/code&gt;):&lt;/b&gt; Remotely pulls historical data logs stored on the kit&amp;#39;s internal card and displays the text dump directly in the scrollable preview box.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="17,2,0"&gt;&lt;b data-path-to-node="17,2,0" data-index-in-node="0"&gt;Clear Card (&lt;code data-path-to-node="17,2,0" data-index-in-node="12"&gt;g2&lt;/code&gt;):&lt;/b&gt; Issues a hardware wipe command to flush and clear stored logs directly from the desktop software.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/GUI5.jpg" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 6 : Communicating with the MAX30208EVSYS in LabVIEW</title><link>https://community.element14.com/thread/57381?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 20:29:36 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:5cc00cca-b092-473a-a736-742078fa6b74</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57381?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p class="first-token" data-path-to-node="0"&gt;&lt;span class=""&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="first-token" data-path-to-node="0"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="first-token" data-path-to-node="0"&gt;&lt;span class=""&gt;Creating a project in LabVIEW that reads data from sensors connected via USB in CDC mode (Communications Device Class &amp;ndash; i.&lt;/span&gt;&lt;span&gt;e.,&lt;/span&gt;&lt;span&gt; as a Virtual Serial / COM Port) is a standard task.&lt;/span&gt;&lt;span&gt; In the operating system,&lt;/span&gt;&lt;span&gt; such a device (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; Arduino,&lt;/span&gt;&lt;span&gt; ESP32,&lt;/span&gt;&lt;span&gt; or a dedicated microcontroller) is recognized as a serial port (&lt;/span&gt;&lt;code data-path-to-node="0" data-index-in-node="304"&gt;COMx&lt;/code&gt;&lt;span&gt; on Windows or &lt;/span&gt;&lt;code data-path-to-node="0" data-index-in-node="323"&gt;/dev/tty...&lt;/code&gt;&lt;span&gt; on Linux/macOS).&lt;/span&gt;&lt;span&gt; In LabVIEW,&lt;/span&gt;&lt;span&gt; the &lt;/span&gt;&lt;b data-path-to-node="0" data-index-in-node="368"&gt;NI-VISA&lt;/b&gt;&lt;span&gt; library is used to handle such ports.&lt;/span&gt;&lt;span&gt; Designing such an application proceeds in a few steps.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1ju0" data-path-to-node="2"&gt;Step 1: Prerequisites&lt;/h3&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;Before writing code in LabVIEW,&lt;/span&gt;&lt;span&gt; make sure you have the required software installed:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="4"&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,0,0"&gt;&lt;b data-path-to-node="4,0,0" data-index-in-node="0"&gt;LabVIEW&lt;/b&gt;&lt;span&gt; (any modern version).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,1,0"&gt;&lt;b data-path-to-node="4,1,0" data-index-in-node="0"&gt;NI-VISA Driver&lt;/b&gt;&lt;span&gt; &amp;ndash; a free package from National Instruments that enables communication with serial,&lt;/span&gt;&lt;span&gt; USB,&lt;/span&gt;&lt;span&gt; and GPIB ports (can be downloaded via the NI Package Manager).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,2,0"&gt;&lt;b data-path-to-node="4,2,0" data-index-in-node="0"&gt;USB CDC Device Driver&lt;/b&gt;&lt;span&gt; &amp;ndash; the device must be visible in Device Manager (Windows) under &lt;/span&gt;&lt;b data-path-to-node="4,2,0" data-index-in-node="85"&gt;Ports (COM &amp;amp; LPT)&lt;/b&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; for example,&lt;/span&gt;&lt;span&gt; as a &lt;/span&gt;&lt;i data-path-to-node="4,2,0" data-index-in-node="122"&gt;USB Serial Device (COM3)&lt;/i&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju1" data-path-to-node="6"&gt;Step 2: Step-by-Step Project in LabVIEW&lt;/h3&gt;
&lt;h4 data-path-to-node="7"&gt;Front Panel (User Interface)&lt;/h4&gt;
&lt;p data-path-to-node="8"&gt;&lt;span&gt;We designed a simple interface to control the connection and visualize the data:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="9"&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,0,0"&gt;&lt;b data-path-to-node="9,0,0" data-index-in-node="0"&gt;VISA Resource Name (Control):&lt;/b&gt;&lt;span&gt; A drop-down list allowing you to select the appropriate COM port (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="9,0,0" data-index-in-node="102"&gt;COM3&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,1,0"&gt;&lt;b data-path-to-node="9,1,0" data-index-in-node="0"&gt;Baud Rate:&lt;/b&gt;&lt;span&gt; Specifies the transmission speed (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="9,1,0" data-index-in-node="51"&gt;9600&lt;/code&gt;&lt;span&gt; or &lt;/span&gt;&lt;code data-path-to-node="9,1,0" data-index-in-node="59"&gt;115200&lt;/code&gt;&lt;span&gt; &amp;ndash; must match the microcontroller settings).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,2,0"&gt;&lt;b data-path-to-node="9,2,0" data-index-in-node="0"&gt;Stop (Button):&lt;/b&gt;&lt;span&gt; A button to stop the read loop.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="9,3,0"&gt;&lt;b data-path-to-node="9,3,0" data-index-in-node="0"&gt;Data Out / String / Graph (Indicator):&lt;/b&gt;&lt;span&gt; A String indicator for raw data or a Waveform Chart/Graph to present sensor readings.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/4137.Front-Panel.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node="10"&gt;Block Diagram (Program Logic)&lt;/h4&gt;
&lt;p data-path-to-node="11"&gt;&lt;span&gt;The standard structure for reading data from a COM port relies on a &lt;/span&gt;&lt;b data-path-to-node="11" data-index-in-node="68"&gt;While Loop&lt;/b&gt;&lt;span&gt; and functions from the &lt;/span&gt;&lt;b data-path-to-node="11" data-index-in-node="102"&gt;Instruments I/O Serial&lt;/b&gt;&lt;span&gt; palette.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="12"&gt;&lt;b data-path-to-node="12" data-index-in-node="0"&gt;Implementation steps in code:&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="13"&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,0,0"&gt;&lt;b data-path-to-node="13,0,0" data-index-in-node="0"&gt;VISA Open:&lt;/b&gt;&lt;span&gt; Opens a connection to the selected port (input receives the &lt;/span&gt;&lt;i data-path-to-node="13,0,0" data-index-in-node="71"&gt;VISA Resource Name&lt;/i&gt;&lt;span&gt; control,&lt;/span&gt;&lt;span&gt; output yields the &lt;/span&gt;&lt;i data-path-to-node="13,0,0" data-index-in-node="117"&gt;VISA session&lt;/i&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,1,0"&gt;&lt;b data-path-to-node="13,1,0" data-index-in-node="0"&gt;VISA Configure Serial Port&lt;/b&gt;&lt;span&gt; (optional,&lt;/span&gt;&lt;span&gt; but recommended):&lt;/span&gt;&lt;span&gt; Allows you to explicitly set the Baud Rate,&lt;/span&gt;&lt;span&gt; data bits,&lt;/span&gt;&lt;span&gt; stop bits,&lt;/span&gt;&lt;span&gt; and flow control.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,2,0"&gt;&lt;b data-path-to-node="13,2,0" data-index-in-node="0"&gt;While Loop:&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="13,2,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,2,1,0,0"&gt;&lt;b data-path-to-node="13,2,1,0,0" data-index-in-node="0"&gt;VISA Read:&lt;/b&gt;&lt;span&gt; Reads a specified number of bytes.&lt;/span&gt;&lt;span&gt; The &lt;/span&gt;&lt;i data-path-to-node="13,2,1,0,0" data-index-in-node="50"&gt;Byte Count&lt;/i&gt;&lt;span&gt; input specifies how many bytes to read (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; as many as the sensor typically sends in a single frame,&lt;/span&gt;&lt;span&gt; or a fixed-size buffer like &lt;/span&gt;&lt;code data-path-to-node="13,2,1,0,0" data-index-in-node="192"&gt;256&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,2,1,1,0"&gt;&lt;b data-path-to-node="13,2,1,1,0" data-index-in-node="0"&gt;Error Cluster:&lt;/b&gt;&lt;span&gt; Passed through the entire pipeline.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,2,1,2,0"&gt;&lt;b data-path-to-node="13,2,1,2,0" data-index-in-node="0"&gt;Wait:&lt;/b&gt;&lt;span&gt; It is best to include a short delay inside the loop (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="13,2,1,2,0" data-index-in-node="65"&gt;ms to wait = 10-50 ms&lt;/code&gt;&lt;span&gt;) to prevent 100% CPU utilization.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="13,3,0"&gt;&lt;b data-path-to-node="13,3,0" data-index-in-node="0"&gt;VISA Close:&lt;/b&gt;&lt;span&gt; Placed outside the While Loop (executed when shutting down the program) to properly release the COM port resource.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/0827.Block-Diagram.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1ju2" data-path-to-node="15"&gt;Step 3: Data Parsing (Processing)&lt;/h3&gt;
&lt;p data-path-to-node="16"&gt;&lt;span&gt;Sensors typically send data in text format separated by newline characters (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="16" data-index-in-node="82"&gt;Temp:23.5, Hum:60\n&lt;/code&gt;&lt;span&gt; or simply a numeric value as a string).&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="17"&gt;&lt;span&gt;To convert the read string into numbers:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="18"&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,0,0"&gt;&lt;span&gt;We used the &lt;/span&gt;&lt;b data-path-to-node="18,0,0" data-index-in-node="12"&gt;Scan From String&lt;/b&gt;&lt;span&gt; function if the data follows a fixed format (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="18,0,0" data-index-in-node="80"&gt;%f,%f&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="18,1,0"&gt;&lt;span&gt;If data is transmitted in JSON or CSV format,&lt;/span&gt;&lt;span&gt; you can use built-in LabVIEW string functions (such as &lt;/span&gt;&lt;b data-path-to-node="18,1,0" data-index-in-node="101"&gt;Match Pattern&lt;/b&gt;&lt;span&gt; or &lt;/span&gt;&lt;b data-path-to-node="18,1,0" data-index-in-node="118"&gt;Spreadsheet String To Array&lt;/b&gt;&lt;span&gt;) to extract the desired sensor parameters.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju3" data-path-to-node="20"&gt;Evaluation Kit Context&lt;/h3&gt;
&lt;p data-path-to-node="21"&gt;&lt;span&gt;The &lt;/span&gt;&lt;b data-path-to-node="21" data-index-in-node="4"&gt;MAX30208EVSYS&lt;/b&gt;&lt;span&gt; evaluation kit consists of the high-accuracy MAX30208 digital temperature sensor,&lt;/span&gt;&lt;span&gt; the MAX32630FTHR microcontroller (which handles I&amp;sup2;C communication with the sensor and provides a virtual COM port over USB CDC),&lt;/span&gt;&lt;span&gt; and a flexible printed circuit (Flex PCB).&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="22"&gt;&lt;span&gt;Below is the description of how to create a LabVIEW project to read data from this evaluation board via USB CDC:&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node="23"&gt;Communication Architecture&lt;/h4&gt;
&lt;p data-path-to-node="24"&gt;&lt;span&gt;The MAX32630FTHR board,&lt;/span&gt;&lt;span&gt; connected via a Micro-USB cable,&lt;/span&gt;&lt;span&gt; communicates with the computer using the USB CDC class (Virtual COM Port).&lt;/span&gt;&lt;span&gt; Windows detects the board as a &lt;/span&gt;&lt;code data-path-to-node="24" data-index-in-node="163"&gt;COMx&lt;/code&gt;&lt;span&gt; port.&lt;/span&gt;&lt;span&gt; The microcontroller transmits measurement data in text (ASCII) format,&lt;/span&gt;&lt;span&gt; ending each frame with a carriage return/newline character (&lt;/span&gt;&lt;code data-path-to-node="24" data-index-in-node="305"&gt;\r&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="1"&gt;&lt;span&gt;Here are the key takeaways from the code analysis:&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1ju4" data-path-to-node="2"&gt;Serial Transmission Parameters (USB CDC)&lt;/h3&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;The &lt;/span&gt;&lt;code data-path-to-node="3" data-index-in-node="4"&gt;OT07Serial.cs&lt;/code&gt;&lt;span&gt; class shows how the host opens and configures the serial port:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="4"&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,0,0"&gt;&lt;b data-path-to-node="4,0,0" data-index-in-node="0"&gt;Baud Rate:&lt;/b&gt;&lt;span&gt; 115,&lt;/span&gt;&lt;span&gt;200 baud.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,1,0"&gt;&lt;b data-path-to-node="4,1,0" data-index-in-node="0"&gt;Frame Format:&lt;/b&gt;&lt;span&gt; 8 data bits,&lt;/span&gt;&lt;span&gt; no parity (&lt;/span&gt;&lt;code data-path-to-node="4,1,0" data-index-in-node="38"&gt;Parity.None&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; 1 stop bit (&lt;/span&gt;&lt;code data-path-to-node="4,1,0" data-index-in-node="64"&gt;StopBits.One&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,2,0"&gt;&lt;b data-path-to-node="4,2,0" data-index-in-node="0"&gt;Flow Control:&lt;/b&gt;&lt;span&gt; None (&lt;/span&gt;&lt;code data-path-to-node="4,2,0" data-index-in-node="20"&gt;Handshake.None&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,3,0"&gt;&lt;b data-path-to-node="4,3,0" data-index-in-node="0"&gt;Control Lines:&lt;/b&gt;&lt;span&gt; DTR and RTS signals are active (&lt;/span&gt;&lt;code data-path-to-node="4,3,0" data-index-in-node="47"&gt;DtrEnable = true&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="4,3,0" data-index-in-node="65"&gt;RtsEnable = true&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju5" data-path-to-node="5"&gt;Text Command Protocol (CLI / Firmware Communication)&lt;/h3&gt;
&lt;p data-path-to-node="6"&gt;&lt;span&gt;The application communicates with the microcontroller (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; MAX32630FTHR) using simple text commands sent and terminated with a carriage return (&lt;/span&gt;&lt;code data-path-to-node="6" data-index-in-node="146"&gt;\r&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt; Responses are also textual,&lt;/span&gt;&lt;span&gt; often with lines ending in newline characters.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="7"&gt;&lt;span&gt;Main commands used in the code:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="8"&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,0,0"&gt;&lt;code data-path-to-node="8,0,0" data-index-in-node="0"&gt;s&lt;/code&gt;&lt;span&gt; &amp;ndash; Device Search.&lt;/span&gt;&lt;span&gt; Returns the number of sensors found,&lt;/span&gt;&lt;span&gt; followed by lines with I&amp;sup2;C addresses and ROM codes.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,1,0"&gt;&lt;code data-path-to-node="8,1,0" data-index-in-node="0"&gt;t[index]&lt;/code&gt;&lt;span&gt; or &lt;/span&gt;&lt;code data-path-to-node="8,1,0" data-index-in-node="12"&gt;t [start] [end]&lt;/code&gt;&lt;span&gt; &amp;ndash; Temperature reading for a specific device index or a range of devices.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,2,0"&gt;&lt;code data-path-to-node="8,2,0" data-index-in-node="0"&gt;r[index] [addr]&lt;/code&gt;&lt;span&gt; or &lt;/span&gt;&lt;code data-path-to-node="8,2,0" data-index-in-node="19"&gt;r[index] [start_addr] [end_addr]&lt;/code&gt;&lt;span&gt; &amp;ndash; Read a register or a range of registers from a given I&amp;sup2;C sensor.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,3,0"&gt;&lt;code data-path-to-node="8,3,0" data-index-in-node="0"&gt;g[index] 0&lt;/code&gt;&lt;span&gt; &amp;ndash; Read all registers (register map) for the indicated device.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="8,4,0"&gt;&lt;code data-path-to-node="8,4,0" data-index-in-node="0"&gt;w[index] [addr] [data]&lt;/code&gt;&lt;span&gt; &amp;ndash; Write data (&lt;/span&gt;&lt;code data-path-to-node="8,4,0" data-index-in-node="37"&gt;data&lt;/code&gt;&lt;span&gt;) to a register (&lt;/span&gt;&lt;code data-path-to-node="8,4,0" data-index-in-node="58"&gt;addr&lt;/code&gt;&lt;span&gt;) of the selected sensor (&lt;/span&gt;&lt;code data-path-to-node="8,4,0" data-index-in-node="88"&gt;index&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju6" data-path-to-node="9"&gt;Response Format and Data Parsing&lt;/h3&gt;
&lt;p data-path-to-node="10"&gt;&lt;span&gt;In response to commands,&lt;/span&gt;&lt;span&gt; the firmware returns data enclosed in square brackets,&lt;/span&gt;&lt;span&gt; e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="10" data-index-in-node="86"&gt;[index] [value] [status]&lt;/code&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="11"&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,0,0"&gt;&lt;b data-path-to-node="11,0,0" data-index-in-node="0"&gt;Temperature reading example:&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="11,0,0" data-index-in-node="29"&gt;[0] [23.500] [0]&lt;/code&gt;&lt;span&gt; (where the first is the device index,&lt;/span&gt;&lt;span&gt; the second is the temperature in &amp;deg;C,&lt;/span&gt;&lt;span&gt; and the third is the status &amp;ndash; e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="11,0,0" data-index-in-node="157"&gt;0&lt;/code&gt;&lt;span&gt; means successful connection / no errors).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="11,1,0"&gt;&lt;b data-path-to-node="11,1,0" data-index-in-node="0"&gt;Register values&lt;/b&gt;&lt;span&gt; are read in hexadecimal format (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="11,1,0" data-index-in-node="54"&gt;0x10&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju7" data-path-to-node="12"&gt;&amp;nbsp;MAX30208 Sensor Register Structure&lt;/h3&gt;
&lt;p data-path-to-node="13"&gt;&lt;span&gt;The &lt;/span&gt;&lt;code data-path-to-node="13" data-index-in-node="4"&gt;Form1.cs&lt;/code&gt;&lt;span&gt; class defines the complete register map of the MAX30208 chip (addresses from &lt;/span&gt;&lt;code data-path-to-node="13" data-index-in-node="90"&gt;0x00&lt;/code&gt;&lt;span&gt; to &lt;/span&gt;&lt;code data-path-to-node="13" data-index-in-node="98"&gt;0xFF&lt;/code&gt;&lt;span&gt;):&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="14"&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,0,0"&gt;&lt;b data-path-to-node="14,0,0" data-index-in-node="0"&gt;0x00 (STATUS):&lt;/b&gt;&lt;span&gt; Contains measurement readiness flags (&lt;/span&gt;&lt;code data-path-to-node="14,0,0" data-index-in-node="53"&gt;TEMP_RDY&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; alarm thresholds (&lt;/span&gt;&lt;code data-path-to-node="14,0,0" data-index-in-node="82"&gt;TEMP_HIGH&lt;/code&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="14,0,0" data-index-in-node="93"&gt;TEMP_LO&lt;/code&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; and FIFO buffer full status (&lt;/span&gt;&lt;code data-path-to-node="14,0,0" data-index-in-node="132"&gt;A_FULL&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,1,0"&gt;&lt;b data-path-to-node="14,1,0" data-index-in-node="0"&gt;0x01 (INTERRUPT ENABLE):&lt;/b&gt;&lt;span&gt; Configuration for enabling interrupts.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,2,0"&gt;&lt;b data-path-to-node="14,2,0" data-index-in-node="0"&gt;0x10 - 0x13:&lt;/b&gt;&lt;span&gt; High and low temperature alarm thresholds (MSB and LSB).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="14,3,0"&gt;&lt;b data-path-to-node="14,3,0" data-index-in-node="0"&gt;0x20 (TEMP SENSOR SETUP):&lt;/b&gt;&lt;span&gt; Contains the &lt;/span&gt;&lt;code data-path-to-node="14,3,0" data-index-in-node="39"&gt;CONVERT_T&lt;/code&gt;&lt;span&gt; bit (writing &lt;/span&gt;&lt;code data-path-to-node="14,3,0" data-index-in-node="62"&gt;1&lt;/code&gt;&lt;span&gt; triggers a single temperature measurement).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju8" data-path-to-node="15"&gt;Raw Temperature Data Conversion&lt;/h3&gt;
&lt;p data-path-to-node="16"&gt;&lt;span&gt;The code implements a method for converting 16-bit register values into degrees Celsius:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="17"&gt;
&lt;li&gt;
&lt;p data-path-to-node="17,0,0"&gt;&lt;span&gt;The sensor resolution is&amp;nbsp;&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="25"&gt;0.005&lt;/span&gt;&lt;span&gt;&amp;nbsp;per bit (0.&lt;/span&gt;&lt;span&gt;005&amp;#39;C).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="17,1,0"&gt;&lt;span&gt;Negative values are handled by checking for a 16-bit overflow (&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="63"&gt;32768&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="17,2,0"&gt;&lt;b data-path-to-node="17,2,0" data-index-in-node="0"&gt;Temperature formula:&lt;/b&gt;&lt;/p&gt;
&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Temperature.jpg" /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1ju9" data-path-to-node="19"&gt;How to use this knowledge in LabVIEW?&lt;/h3&gt;
&lt;p data-path-to-node="20"&gt;&lt;span&gt;When creating your own LabVIEW program to handle this kit via USB CDC,&lt;/span&gt;&lt;span&gt; instead of writing an advanced I&amp;sup2;C protocol parser from scratch,&lt;/span&gt;&lt;span&gt; you can send the exact same text commands to the serial port (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; sending the string &lt;/span&gt;&lt;code data-path-to-node="20" data-index-in-node="223"&gt;&amp;quot;s\r&amp;quot;&lt;/code&gt;&lt;span&gt; to detect devices or &lt;/span&gt;&lt;code data-path-to-node="20" data-index-in-node="250"&gt;&amp;quot;t0\r&amp;quot;&lt;/code&gt;&lt;span&gt; to read the temperature from device #0) and receive text responses using the &lt;/span&gt;&lt;b data-path-to-node="20" data-index-in-node="334"&gt;VISA Read&lt;/b&gt;&lt;span&gt; function.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="20"&gt;&lt;span style="font-size:150%;"&gt;Implementation process&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="1"&gt;&lt;span&gt;The implementation process carried out in LabVIEW consists of the following phases:&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1jua" data-path-to-node="2"&gt;Step 1: Serial Transmission Configuration (NI-VISA)&lt;/h3&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;Before reading data,&lt;/span&gt;&lt;span&gt; the serial port was correctly configured in LabVIEW using the &lt;/span&gt;&lt;b data-path-to-node="3" data-index-in-node="83"&gt;VISA Configure Serial Port&lt;/b&gt;&lt;span&gt; function to match the parameters extracted from the C# source code (&lt;/span&gt;&lt;code data-path-to-node="3" data-index-in-node="178"&gt;OT07Serial.cs&lt;/code&gt;&lt;span&gt;):&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="4"&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,0,0"&gt;&lt;b data-path-to-node="4,0,0" data-index-in-node="0"&gt;Baud Rate:&lt;/b&gt;&lt;span&gt; 115,&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,1,0"&gt;&lt;b data-path-to-node="4,1,0" data-index-in-node="0"&gt;Data Bits:&lt;/b&gt;&lt;span&gt; 8&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,2,0"&gt;&lt;b data-path-to-node="4,2,0" data-index-in-node="0"&gt;Parity:&lt;/b&gt;&lt;span&gt; None&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,3,0"&gt;&lt;b data-path-to-node="4,3,0" data-index-in-node="0"&gt;Stop Bits:&lt;/b&gt;&lt;span&gt; 1&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,4,0"&gt;&lt;b data-path-to-node="4,4,0" data-index-in-node="0"&gt;Flow Control:&lt;/b&gt;&lt;span&gt; None&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,5,0"&gt;&lt;b data-path-to-node="4,5,0" data-index-in-node="0"&gt;Termination Character:&lt;/b&gt;&lt;span&gt; Enabled (TRUE),&lt;/span&gt;&lt;span&gt; set to &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="46"&gt;\r&amp;nbsp;&lt;/span&gt;&lt;span&gt;(Return / 0x0D).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1jub" data-path-to-node="5"&gt;Step 2: LabVIEW Project Architecture (Block Diagram)&lt;/h3&gt;
&lt;p data-path-to-node="6"&gt;&lt;span&gt;A sequential logic structure was established to mirror the text command mechanism of the original application,&lt;/span&gt;&lt;span&gt; utilizing a &lt;/span&gt;&lt;b data-path-to-node="6" data-index-in-node="123"&gt;While Loop&lt;/b&gt;&lt;span&gt; for continuous data acquisition:&lt;/span&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="7"&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,0,0"&gt;&lt;b data-path-to-node="7,0,0" data-index-in-node="0"&gt;Initialization (Before the Loop):&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="7,0,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,0,1,0,0"&gt;&lt;span&gt;The &lt;/span&gt;&lt;b data-path-to-node="7,0,1,0,0" data-index-in-node="4"&gt;VISA Open&lt;/b&gt;&lt;span&gt; function was used to open a connection to the selected COM port (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="7,0,1,0,0" data-index-in-node="85"&gt;COM3&lt;/code&gt;&lt;span&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,0,1,1,0"&gt;&lt;span&gt;The &lt;/span&gt;&lt;b data-path-to-node="7,0,1,1,0" data-index-in-node="4"&gt;VISA Configure Serial Port&lt;/b&gt;&lt;span&gt; function was applied with the parameters defined in Step 1.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,0"&gt;&lt;b data-path-to-node="7,1,0" data-index-in-node="0"&gt;Measurement Loop (While Loop Execution):&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="7,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,1,0,0"&gt;&lt;b data-path-to-node="7,1,1,0,0" data-index-in-node="0"&gt;Command Transmission (VISA Write):&lt;/b&gt;&lt;span&gt; Sent text commands terminated with a carriage return \&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="89"&gt;r&lt;/span&gt;&lt;span&gt;) using a string constant (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; sending &lt;/span&gt;&lt;code data-path-to-node="7,1,1,0,0" data-index-in-node="148"&gt;t0\r&lt;/code&gt;&lt;span&gt; to request a temperature reading from device index 0).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,1,1,0"&gt;&lt;b data-path-to-node="7,1,1,1,0" data-index-in-node="0"&gt;Response Acquisition (VISA Read):&lt;/b&gt;&lt;span&gt; Read the text buffer returned by the firmware,&lt;/span&gt;&lt;span&gt; which encapsulates output data inside square brackets (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="7,1,1,1,0" data-index-in-node="142"&gt;[0] [23.500] [0]&lt;/code&gt;&lt;span&gt; representing the device index,&lt;/span&gt;&lt;span&gt; temperature in &amp;deg;C,&lt;/span&gt;&lt;span&gt; and status code).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,1,2,0"&gt;&lt;b data-path-to-node="7,1,1,2,0" data-index-in-node="0"&gt;Data Parsing (Scan From String / Regex):&lt;/b&gt;&lt;span&gt; Processed the incoming string using pattern-matching functions to extract the numerical temperature value.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,1,3,0"&gt;&lt;b data-path-to-node="7,1,1,3,0" data-index-in-node="0"&gt;Data Visualization:&lt;/b&gt;&lt;span&gt; Routed the parsed temperature value to a numeric indicator and a Waveform Chart.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,1,4,0"&gt;&lt;b data-path-to-node="7,1,1,4,0" data-index-in-node="0"&gt;Loop Timing (Wait ms):&lt;/b&gt;&lt;span&gt; Integrated a 1,&lt;/span&gt;&lt;span&gt;000 ms (1 second) delay to match the native refresh rate of the original software and prevent 100% CPU utilization.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,2,0"&gt;&lt;b data-path-to-node="7,2,0" data-index-in-node="0"&gt;Resource Cleanup (After the Loop):&lt;/b&gt;&lt;/p&gt;
&lt;ul data-path-to-node="7,2,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,2,1,0,0"&gt;&lt;span&gt;Upon pressing the stop button,&lt;/span&gt;&lt;span&gt; the loop terminates and the &lt;/span&gt;&lt;b data-path-to-node="7,2,1,0,0" data-index-in-node="59"&gt;VISA Close&lt;/b&gt;&lt;span&gt; function executes to properly release the COM port resource in the operating system.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="mcetoc_1k5qck1juc" data-path-to-node="8"&gt;Step 3: Advanced Command Support (Maxim Protocol Reproduction)&lt;/h3&gt;
&lt;p data-path-to-node="9"&gt;&lt;span&gt;To replicate the full feature set of the original application,&lt;/span&gt;&lt;span&gt; the LabVIEW architecture was expanded to handle multiple CLI commands:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="10"&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,0,0"&gt;&lt;b class="" data-path-to-node="10,0,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="10,0,0" data-index-in-node="0"&gt;s\r&lt;/code&gt;&lt;/b&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Initiates a device search across the I&amp;sup2;C bus,&lt;/span&gt;&lt;span&gt; returning the number of detected sensors along with their ROM codes and addresses.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,1,0"&gt;&lt;b class="" data-path-to-node="10,1,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="10,1,0" data-index-in-node="0"&gt;t0\r&lt;/code&gt;&lt;/b&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Requests a direct temperature conversion and reading from the sensor at index 0,&lt;/span&gt;&lt;span&gt; returning the formatted string &lt;/span&gt;&lt;code data-path-to-node="10,1,0" data-index-in-node="118"&gt;[0] [23.500] [0]&lt;/code&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,2,0"&gt;&lt;b class="" data-path-to-node="10,2,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="10,2,0" data-index-in-node="0"&gt;r0 10\r&lt;/code&gt;&lt;/b&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Reads register address &lt;/span&gt;&lt;code data-path-to-node="10,2,0" data-index-in-node="32"&gt;0x10&lt;/code&gt;&lt;span&gt; from device number 0,&lt;/span&gt;&lt;span&gt; returning the hexadecimal value.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,3,0"&gt;&lt;b class="" data-path-to-node="10,3,0" data-index-in-node="0"&gt;&lt;code data-path-to-node="10,3,0" data-index-in-node="0"&gt;w0 10 1F\r&lt;/code&gt;&lt;/b&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Writes data (&lt;/span&gt;&lt;code data-path-to-node="10,3,0" data-index-in-node="25"&gt;0x1F&lt;/code&gt;&lt;span&gt;) into register &lt;/span&gt;&lt;code data-path-to-node="10,3,0" data-index-in-node="45"&gt;0x10&lt;/code&gt;&lt;span&gt; of device number 0,&lt;/span&gt;&lt;span&gt; yielding a confirmation response.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1jud" data-path-to-node="11"&gt;Best Practices Implemented:&lt;/h3&gt;
&lt;ul data-path-to-node="12"&gt;
&lt;li&gt;
&lt;p data-path-to-node="12,0,0"&gt;&lt;b data-path-to-node="12,0,0" data-index-in-node="0"&gt;Error Handling (Error Cluster):&lt;/b&gt;&lt;span&gt; The error cluster wire is daisy-chained continuously through every VISA operation (&lt;/span&gt;&lt;code data-path-to-node="12,0,0" data-index-in-node="115"&gt;Open&lt;/code&gt;&amp;nbsp;-&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code data-path-to-node="12,0,0" data-index-in-node="132"&gt;Configure&lt;/code&gt;&lt;span&gt; &lt;/span&gt;-&amp;gt;&amp;nbsp;&lt;span&gt;&lt;/span&gt;&lt;code data-path-to-node="12,0,0" data-index-in-node="154"&gt;Write/Read&lt;/code&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="math-inline" data-index-in-node="165"&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;code data-path-to-node="12,0,0" data-index-in-node="177"&gt;Close&lt;/code&gt;&lt;span&gt;) to ensure robust exception handling and prevent application freezing if the USB cable is abruptly disconnected.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="first-token" data-path-to-node="0"&gt;&lt;span class=""&gt;To display real-time temperature data from the &lt;/span&gt;&lt;b data-path-to-node="0" data-index-in-node="47"&gt;MAX30208EVSYS&lt;/b&gt;&lt;span&gt; sensor on a LabVIEW chart,&lt;/span&gt;&lt;span&gt; the &lt;/span&gt;&lt;b data-path-to-node="0" data-index-in-node="92"&gt;Waveform Chart&lt;/b&gt;&lt;span&gt; element is the recommended choice.&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="1"&gt;&lt;span&gt;The configuration process in the project involves the following steps:&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1jue" data-path-to-node="2"&gt;1. Front Panel Configuration&lt;/h3&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;From the &lt;/span&gt;&lt;b data-path-to-node="3" data-index-in-node="9"&gt;Controls Palette&lt;/b&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; navigate to &lt;/span&gt;&lt;b class="" data-path-to-node="3" data-index-in-node="39"&gt;Graph -&amp;gt;&amp;nbsp;Waveform Chart&lt;/b&gt;&lt;span&gt; and place it on your user interface:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="4"&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,0,0"&gt;&lt;b data-path-to-node="4,0,0" data-index-in-node="0"&gt;Chart vs. Graph Selection:&lt;/b&gt;&lt;span&gt; The &lt;/span&gt;&lt;i data-path-to-node="4,0,0" data-index-in-node="31"&gt;Waveform Chart&lt;/i&gt;&lt;span&gt; was chosen over a standard Graph because it automatically maintains a history buffer of incoming data points and scrolls over time.&lt;/span&gt;&lt;span&gt; A Graph,&lt;/span&gt;&lt;span&gt; by contrast,&lt;/span&gt;&lt;span&gt; would require manual array management to store and update historical data with every new temperature reading.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,1,0"&gt;&lt;b data-path-to-node="4,1,0" data-index-in-node="0"&gt;Labeling:&lt;/b&gt;&lt;span&gt; The indicator is designated as &lt;/span&gt;&lt;i data-path-to-node="4,1,0" data-index-in-node="41"&gt;Temperature History&lt;/i&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="4,2,0"&gt;&lt;b data-path-to-node="4,2,0" data-index-in-node="0"&gt;Axis Precision:&lt;/b&gt;&lt;span&gt; Because the MAX30208 sensor provides high-precision data down to thousandths of a degree,&lt;/span&gt;&lt;span&gt; the Y-axis formatting was adjusted via &lt;/span&gt;&lt;b class="" data-path-to-node="4,2,0" data-index-in-node="145"&gt;Right-Click -&amp;gt;&amp;nbsp;Format and Precision&lt;/b&gt;&lt;span&gt; (setting &lt;/span&gt;&lt;i data-path-to-node="4,2,0" data-index-in-node="199"&gt;Digits of Precision&lt;/i&gt;&lt;span&gt; to at least 3) to properly display floating-point values with multiple decimal places.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Front-Panel.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1juf" data-path-to-node="5"&gt;2. Block Diagram Implementation&lt;/h3&gt;
&lt;p data-path-to-node="6"&gt;&lt;span&gt;Inside the primary &lt;/span&gt;&lt;b data-path-to-node="6" data-index-in-node="19"&gt;While Loop&lt;/b&gt;&lt;span&gt; where data is acquired from the device:&lt;/span&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="7"&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,0,0"&gt;&lt;b data-path-to-node="7,0,0" data-index-in-node="0"&gt;Data Acquisition &amp;amp; Parsing:&lt;/b&gt;&lt;span&gt; After receiving the serial string via &lt;/span&gt;&lt;b data-path-to-node="7,0,0" data-index-in-node="66"&gt;VISA Read&lt;/b&gt;&lt;span&gt; (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="7,0,0" data-index-in-node="83"&gt;[0] [23.500] [0]&lt;/code&gt;&lt;span&gt;) and extracting the numeric temperature value as a Double-precision float,&lt;/span&gt;&lt;span&gt; a single sample is ready for plotting.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="7,1,0"&gt;&lt;b data-path-to-node="7,1,0" data-index-in-node="0"&gt;Data Wire Connection:&lt;/b&gt;&lt;span&gt; The numeric data wire is connected directly to the Waveform Chart terminal located on the loop boundary (or inside it).&lt;/span&gt;&lt;span&gt; LabVIEW automatically appends the new sample to the chart&amp;#39;s internal history buffer.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Block-Diagram.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5qck1jug" data-path-to-node="8"&gt;3. Timeline and Smoothness Optimization&lt;/h3&gt;
&lt;p data-path-to-node="9"&gt;&lt;span&gt;To ensure the chart clearly visualizes temperature variations over time:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="10"&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,0,0"&gt;&lt;b data-path-to-node="10,0,0" data-index-in-node="0"&gt;Loop Timing (Wait ms):&lt;/b&gt;&lt;span&gt; A &lt;/span&gt;&lt;b data-path-to-node="10,0,0" data-index-in-node="25"&gt;Wait (ms)&lt;/b&gt;&lt;span&gt; function is embedded inside the While Loop,&lt;/span&gt;&lt;span&gt; configured to a 1,&lt;/span&gt;&lt;span&gt;000 ms delay (1 second per reading),&lt;/span&gt;&lt;span&gt; matching the default refresh rate of the native application.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,1,0"&gt;&lt;b data-path-to-node="10,1,0" data-index-in-node="0"&gt;X-Axis (Time Scale):&lt;/b&gt;&lt;span&gt; Through &lt;/span&gt;&lt;b class="" data-path-to-node="10,1,0" data-index-in-node="29"&gt;PropertiesScales&amp;nbsp;Time&lt;/b&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; the time formatting can be customized (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; displaying hours,&lt;/span&gt;&lt;span&gt; minutes,&lt;/span&gt;&lt;span&gt; and seconds).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="10,2,0"&gt;&lt;b data-path-to-node="10,2,0" data-index-in-node="0"&gt;History Length:&lt;/b&gt;&lt;span&gt; By default,&lt;/span&gt;&lt;span&gt; a Waveform Chart retains the last 1,&lt;/span&gt;&lt;span&gt;000 points.&lt;/span&gt;&lt;span&gt; To extend the retention window (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; covering several hours of data),&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;b data-path-to-node="10,2,0" data-index-in-node="147"&gt;Data History&lt;/b&gt;&lt;span&gt; can be modified by right-clicking the chart and increasing the buffer size.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1k5qck1juh" data-path-to-node="2"&gt;4. Sensor Communication in LabVIEW&lt;/h3&gt;
&lt;p data-path-to-node="3"&gt;&lt;span&gt;The MAX30208EVSYS evaluation board streams a raw text frame over the virtual COM port whenever a measurement command is triggered.&lt;/span&gt;&lt;span&gt; The received data string typically follows this format:&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node="4"&gt;&lt;code data-path-to-node="4" data-index-in-node="0"&gt;device[00] temperature[18.090] status[0]&lt;/code&gt;&lt;/p&gt;
&lt;p data-path-to-node="5"&gt;&lt;span&gt;To successfully parse this string and extract the temperature value in LabVIEW,&lt;/span&gt;&lt;span&gt; the implementation follows these steps:&lt;/span&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="6"&gt;
&lt;li&gt;
&lt;p data-path-to-node="6,0,0"&gt;&lt;b data-path-to-node="6,0,0" data-index-in-node="0"&gt;Trimming Hidden Characters:&lt;/b&gt;&lt;span&gt; Serial devices often append hidden carriage return and line feed characters (&lt;/span&gt;&lt;code data-path-to-node="6,0,0" data-index-in-node="105"&gt;\r\n&lt;/code&gt;&lt;span&gt;) at the beginning or end of the incoming data stream.&lt;/span&gt;&lt;span&gt; Before any parsing takes place,&lt;/span&gt;&lt;span&gt; the raw string is passed through LabVIEW&amp;rsquo;s &lt;/span&gt;&lt;b data-path-to-node="6,0,0" data-index-in-node="239"&gt;Trim Whitespace&lt;/b&gt;&lt;span&gt; function.&lt;/span&gt;&lt;span&gt; Trimming the text removes these stray control characters and whitespace,&lt;/span&gt;&lt;span&gt; preventing matching errors and ensuring the string format is clean and predictable.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="6,1,0"&gt;&lt;b data-path-to-node="6,1,0" data-index-in-node="0"&gt;Parsing and String Matching:&lt;/b&gt;&lt;span&gt; Once the text is properly trimmed,&lt;/span&gt;&lt;span&gt; LabVIEW uses pattern matching or the &lt;/span&gt;&lt;b data-path-to-node="6,1,0" data-index-in-node="101"&gt;Scan From String&lt;/b&gt;&lt;span&gt; function to locate the &lt;/span&gt;&lt;code data-path-to-node="6,1,0" data-index-in-node="141"&gt;temperature[...]&lt;/code&gt;&lt;span&gt; block.&lt;/span&gt;&lt;span&gt; It isolates the characters nested inside the square brackets.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="6,2,0"&gt;&lt;b data-path-to-node="6,2,0" data-index-in-node="0"&gt;String-to-Number Conversion:&lt;/b&gt;&lt;span&gt; The isolated floating-point number (e.&lt;/span&gt;&lt;span&gt;g.,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;code data-path-to-node="6,2,0" data-index-in-node="71"&gt;18.090&lt;/code&gt;&lt;span&gt;) is converted from text into a numeric data type (Double format).&lt;/span&gt;&lt;span&gt; This yields a clean numerical temperature value ready to be displayed on indicators,&lt;/span&gt;&lt;span&gt; plotted on real-time charts,&lt;/span&gt;&lt;span&gt; fed into the statistical analysis engine,&lt;/span&gt;&lt;span&gt; or logged to a CSV file.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/TermometerLabView.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/LabView.mp4"&gt;community.element14.com/.../LabView.mp4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Palno &amp; Slemon #6  Building the Enclosure</title><link>https://community.element14.com/thread/57380?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 15:44:36 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:01e67636-4c51-4f53-b575-73d10602c1dd</guid><dc:creator>Qbit</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57380?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57380/palno-slemon-6-building-the-enclosure/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&amp;nbsp;I hope you are not tired of reading and are doing well. I was able to finish that very fast because I have already taken some notes while I was working so it was easy. I have already captured the picture of building inclusion so it also didn&amp;#39;t take that much time.&amp;nbsp;&lt;/p&gt;
&lt;div&gt;Thank you for following my journey till here. Now I only have to build the enclosure, the home for all the things I have built. I have to build two things:
&lt;ol&gt;
&lt;li&gt;The hub, which includes the Arduino Uno, the temperature sensor, the radar module, and the e-ink display to not tire your eyes as you see them in the early morning. That&amp;#39;s why I have included an e-ink display instead of a cheap TFT. I also have included a heatsink so the sensor can better sense the room temperature rather than from the smaller surface area.&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Second is the variable that includes the ESP32, the MAXREFDES 117, and the MPU6050. That was not very easy but a little bit messy. The battery included also wasn&amp;#39;t that capable of running the entire whole system in that small space so I had to power it with a USB for now.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;If you weren&amp;#39;t following, here are the past posts I made regarding the project.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Recap&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57301/palno-slemon-1-introduction" data-e14adj="t"&gt;Palno &amp;amp; Slemon #1 Introduction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57315/palno-slemon-2-1-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.1 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57324/palno-slemon-2-2-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.2 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57366/palno-slemon-3-building-the-algorithm" data-e14adj="t"&gt;Palno &amp;amp; Slemon #3 Building the Algorithm&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57378/palno-slemon-4-final-firmware" data-e14adj="t"&gt;Palno &amp;amp; Slemon #4 Final Firmware&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57379/palno-slemon-5-labview-integration" data-e14adj="t"&gt;Palno &amp;amp; Slemon #5 LabView Integration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;My project was a dual-code system that helps us track sleep and also wake up at the right time so we don&amp;#39;t feel tired and low on energy. It uses algorithms and data from the blood oxygen and blood beats-per-minute (BPM) sensor. The radar module detects movement while you are sleeping and I also have the temperature sensor for smart things.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;1)Building the Selmon`s Enclosure&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For building the salmon, which includes the Arduino Q, the Mac, the temperature sensor, the ink display, and the data module, I want a space that can house all of these without being too congested. It should be portable and look good also. I wanted it to be under 400 cm&amp;sup2; so it would be a good fit.&lt;/p&gt;
&lt;p&gt;I made it. First I designed the plan and how I should cut the cardboard pieces so they can form the structure for the supposed design I made. I made a rectangular cuboid that is a little tilted at a 20&amp;deg; angle on the front side, where it includes the ink display and the radar module. On the top I want it to be removable and to house the heat sink, which will be connected to the temperature sensor so we can sense the air&amp;#39;s temperature and the room&amp;#39;s temperature also.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t have a 3D printer, that&amp;#39;s why I&amp;#39;m doing it. Also I&amp;#39;m a little bit good at art and craft.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;First I made the quicker schematics of what I have to do and how to cut the cardboard pieces:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-19.18.47.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;After cutting these are the pieces. They are quite rough so I have to also make the outer covering for them&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.31.56.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After Sticking them.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.32.18-_2800_1_2900_.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;then,&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.32.26.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;The display can be attached with the duct tape and surely I don&amp;#39;t have to use bolts.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.32.18-_2800_3_2900_.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;It seems magical when we don&amp;#39;t have to power the display. It stays as it is.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After Placing all the components tightly and steadly.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.38-_2800_2_2900_.jpeg" /&gt;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.38-_2800_1_2900_.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The Heat sink I am going to used:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.36-_2800_2_2900_.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I have reused an old scrap aluminum heatsink because it&amp;#39;s good for us(and the planet). Why buy if you already have.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Putting the Max30208&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.38.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;I use the EMI absorber because it reflects the radiation. You kind of say it&amp;#39;s related to the Arduino Q and also the main heat from the system because Arduino Q is a heavy beast.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After all fabrication with paper its ready!&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.39-_2800_1_2900_.jpeg" /&gt;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.39.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Because I don&amp;#39;t have sufficient batteries right now, I want it to be powered by USB only so I have included a port on the right side, top right. It is steady because the adhesive was very strong.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.33.40.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;2) Building the Palno&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;So instead of wasting time seeking new ideas, I decided to utilize the time and build it on a makeshift broken watch: not one watch but two, once using the strap and once using the main body (the lower part)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.31.56-_2800_1_2900_.jpeg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Below that is the Maxrefdes 117. I also have applied the EMI absorber as there will be the microcontroller and also the MPU6050 stacked on top. That could cause interference&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.35-_2800_1_2900_.jpeg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Then I place the battery, which won&amp;#39;t be that useful. Later it only provides me with a lifetime of about 1 or 2 minutes because it&amp;#39;s quite old and can&amp;#39;t withstand the draw. Then I apply the MPU6050 on the top of the ESP52 processor heatsink.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;I had placed the AMI observer in between them also so it does not cause any interference.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.35.jpeg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;All together now:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-18.33.34.jpeg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;And it was done, though it was a little heavy and not that study and compact, just a Frankenstein prototype, but it works well and can do the job. Firstly I was going to build it in a comfortable cloth format but I don&amp;#39;t think I had time for this so I had to make it this way only.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Thanks to the Element14 this time I had enough duct tape to hold every piece from breaking apart : )&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:300px;"  src="https://community.element14.com/resized-image/__size/600x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-21.07.47.jpeg" /&gt;&amp;nbsp; &amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:300px;"  src="https://community.element14.com/resized-image/__size/600x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.35-_2800_2_2900_.jpeg" /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:300px;"  src="https://community.element14.com/resized-image/__size/600x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_25-at-09.27.38-_2800_1_2900_.jpeg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;Thanks again for being here till here and following my journey. I think it was fairly enjoyable for you as you don&amp;#39;t have to read along. You can just watch. In the next post I will be blogging the entire project, the most important part, so if you want you can read it.&amp;nbsp;It will be very encouraging for me.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;Thanks again for reading. Let me know your comments and thoughts on this.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Palno &amp; Slemon #5 LabView Integration</title><link>https://community.element14.com/thread/57379?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 14:26:04 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:54bfdaed-c370-4ee5-8d8a-2b91bdf58f76</guid><dc:creator>Qbit</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57379?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57379/palno-slemon-5-labview-integration/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&amp;nbsp;I hope all&amp;#39;s good. Today was miserable for me. I had to work from the very morning to now. It&amp;#39;s almost night and I only go to eat. Otherwise I stay at my desk only to work. I have gained a lot of precious experience from this: I should never take the deadline as a joke.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;but I have to make some changes from where I am so I can implement that. That took me a while and understanding LabVIEW&amp;#39;s new architecture was also a little easy. I was completely new so it took me some time but it was fairly easier than any other software&amp;nbsp;I will be writing this using Wispr Flow because I am very tired.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;I had taken many revisions, like five revisions, to completely come to this stage when all things sync perfectly with each other and work excellently.&amp;nbsp;&amp;nbsp;thank you for staying to see my journey till here. If you are new and seeing this, you can also read my past posts here:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Past Posts&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57301/palno-slemon-1-introduction" data-e14adj="t"&gt;Palno &amp;amp; Slemon #1 Introduction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57315/palno-slemon-2-1-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.1 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57324/palno-slemon-2-2-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.2 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57366/palno-slemon-3-building-the-algorithm" data-e14adj="t"&gt;Palno &amp;amp; Slemon #3 Building the Algorithm&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57378/palno-slemon-4-final-firmware" data-e14adj="t"&gt;Palno &amp;amp; Slemon #4 Final Firmware&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;By the way I was working on a project that helps us wake up at the right time so we aren&amp;#39;t in the stage that could affect our energy level and we feel tired. It also manages the time we have to wake up. We set it for the right time as per the data it gets from our sleep. If you set it to 7:00 and the algorithm detects that you are partially awake around 6:00, it will wake you up at that time. You will feel fresh and wake up at the right time so you don&amp;#39;t have to compromise time with health.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It works by seeing your blood oxygen level (the SpO2), the BPM, and the movement you make while you are resting. I have also added temperature control for others, like the temperature of your room, so you are better comfortable and it will be easy for you to fall asleep. I&amp;#39;m also using speakers to help you sleep properly with the therapy of binaural beats.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;The Goal&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="" data-line-start="41" data-line-end="41"&gt;While the Uno Q runs a built-in web dashboard on port 7000 for everyday consumer check-ins, medical and clinical research environments have completely different demands. A clinician, sleep doctor, or biomedical engineer doesn&amp;#39;t want a consumer mobile layout; they need:&lt;/p&gt;
&lt;ol data-line-start="42" data-line-end="45"&gt;
&lt;li data-line-start="42" data-line-end="42"&gt;&lt;strong data-line-start="42" data-line-end="42"&gt;High-Frequency Multi-Parameter Waveform Plotting:&lt;/strong&gt; Continuous, uninterrupted real-time trend charts of heart rate variability, SpO2 saturation, respiration rate, and 3-axis gravitational acceleration vectors.&lt;/li&gt;
&lt;li data-line-start="43" data-line-end="43"&gt;&lt;strong data-line-start="43" data-line-end="43"&gt;Absolute Determinism:&lt;/strong&gt; No browser rendering lag, no dropped samples, and zero jitter.&lt;/li&gt;
&lt;li data-line-start="44" data-line-end="44"&gt;&lt;strong data-line-start="44" data-line-end="44"&gt;Medical-Grade Telemetry Logging:&lt;/strong&gt; Direct, uncorrupted streaming to CSV/spreadsheet files on a PC for post-hoc polysomnography (PSG) comparison and statistical scoring.&lt;/li&gt;
&lt;li data-line-start="45" data-line-end="45"&gt;&lt;strong data-line-start="45" data-line-end="45"&gt;Instant Visual State Annunciation:&lt;/strong&gt; Clear LED clusters and numerical readouts showing whether the patient is in Deep Sleep, REM, or Restless Wakefulness.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class="" data-line-start="47" data-line-end="47"&gt;National Instruments &lt;strong data-line-start="47" data-line-end="47"&gt;LabVIEW&lt;/strong&gt; is the gold standard for clinical data acquisition and biomedical instrumentation. My goal for this phase was simple but ambitious: create a high-speed, wireless clinical telemetry dashboard in LabVIEW that ingests our full multi-sensor ecosystem at 10 Hz over the network, plots every vital sign with zero lag, and automatically logs complete datasets to disk.&lt;/p&gt;
&lt;p class="" data-line-start="49" data-line-end="49"&gt;Before diving in, I was completely new to LabVIEW&amp;rsquo;s modern networking architecture. It seemed daunting at first, but once I grasped dataflow programming and how LabVIEW handles TCP primitives, it turned out to be far more intuitive, modular, and visual than traditional text-based charting libraries.&lt;/p&gt;
&lt;p class="" data-line-start="49" data-line-end="49"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pk7n090" data-line-start="53" data-line-end="53"&gt;&lt;span style="font-size:75%;"&gt;&lt;b&gt;The Architectural Leap: Wi-Fi TCP/IP Streaming vs. Serial Cables&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="" data-line-start="55" data-line-end="55"&gt;When developing embedded projects, the standard, instinctive fallback is to use &lt;strong data-line-start="55" data-line-end="55"&gt;Serial (UART/COM port)&lt;/strong&gt; communication. Plug a USB cable from the board to your PC, open a COM port at 115200 baud, and print CSV strings.&lt;/p&gt;
&lt;p class="" data-line-start="57" data-line-end="57"&gt;Early on, I realized that for a bedside sleep-monitoring system, &lt;strong data-line-start="57" data-line-end="57"&gt;relying on a Serial cable was a fatal design flaw&lt;/strong&gt;:&lt;/p&gt;
&lt;ol data-line-start="58" data-line-end="60"&gt;
&lt;li data-line-start="58" data-line-end="58"&gt;&lt;strong data-line-start="58" data-line-end="58"&gt;Tethering a Sleeping Person:&lt;/strong&gt; A sleep monitor cannot have physical cables running across the bedroom to a laptop. The bedside hub must live independently by the bed, while the monitoring PC could be across the room or at a nurse&amp;#39;s workstation.&lt;/li&gt;
&lt;li data-line-start="59" data-line-end="59"&gt;&lt;strong data-line-start="59" data-line-end="59"&gt;Serial Contention on Arduino Uno Q:&lt;/strong&gt; The Uno Q&amp;#39;s internal architecture relies heavily on serial/bridge routing between the STM32 microcontroller and the Qualcomm Linux MPU via &lt;code class="whitespace-pre-wrap" data-line-start="59" data-line-end="59"&gt;RouterBridge&lt;/code&gt;. Trying to tap into raw UART streams while the Linux container was actively using them created bus locks and dropped packets.&lt;/li&gt;
&lt;li data-line-start="60" data-line-end="60"&gt;&lt;strong data-line-start="60" data-line-end="60"&gt;Bandwidth &amp;amp; Buffer Bottlenecks:&lt;/strong&gt; Pushing 20 Hz accelerometer data, 1 Hz biometrics, radar metrics, and sleep stages simultaneously over standard serial lines creates buffer overflow issues when the host GUI stalls for even a millisecond.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="user-content-the-decision-dedicated-tcpip-socket-server-on-port-5005" class="" data-line-start="62" data-line-end="62"&gt;&lt;b&gt;The Decision: Dedicated TCP/IP Socket Server on Port 5005&lt;/b&gt;&lt;/h3&gt;
&lt;p class="" data-line-start="63" data-line-end="63"&gt;We completely bypassed physical serial communication for the LabVIEW pipeline and moved to &lt;strong data-line-start="63" data-line-end="63"&gt;wireless TCP/IP streaming&lt;/strong&gt;:&lt;/p&gt;
&lt;ul data-line-start="64" data-line-end="67"&gt;
&lt;li data-line-start="64" data-line-end="64"&gt;The Uno Q&amp;rsquo;s Qualcomm MPU spins up a dedicated multi-threaded TCP server listening on &lt;code class="whitespace-pre-wrap" data-line-start="64" data-line-end="64"&gt;0.0.0.0:5005&lt;/code&gt;.&lt;/li&gt;
&lt;li data-line-start="65" data-line-end="65"&gt;The station connects to the local bedroom Wi-Fi network (IP: &lt;code class="whitespace-pre-wrap" data-line-start="65" data-line-end="65"&gt;192.168.1.12&lt;/code&gt;).&lt;/li&gt;
&lt;li data-line-start="66" data-line-end="66"&gt;The monitoring PC running LabVIEW connects wirelessly over standard Wi-Fi directly to &lt;code class="whitespace-pre-wrap" data-line-start="66" data-line-end="66"&gt;192.168.1.12:5005&lt;/code&gt; (with an optional USB ADB port-forward to &lt;code class="whitespace-pre-wrap" data-line-start="66" data-line-end="66"&gt;127.0.0.1:5005&lt;/code&gt; for low-latency bench testing).&lt;/li&gt;
&lt;li data-line-start="67" data-line-end="67"&gt;Telemetry is serialized as a lightweight, clean, single-line JSON string terminated with standard &lt;code class="whitespace-pre-wrap" data-line-start="67" data-line-end="67"&gt;\r\n&lt;/code&gt; (CRLF) characters, broadcast at a rock-solid &lt;strong data-line-start="67" data-line-end="67"&gt;10 Hz&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="" data-line-start="69" data-line-end="69"&gt;This gave us complete wireless freedom. The Uno Q can sit anywhere in the room, and any PC running LabVIEW on the local network can open the connection and receive real-time vitals instantly.&lt;/p&gt;
&lt;p class="" data-line-start="69" data-line-end="69"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pkbibj1" data-line-start="73" data-line-end="73"&gt;&lt;b&gt;How We Implemented the LabVIEW Block Diagram&lt;/b&gt;&lt;/h2&gt;
&lt;h3 id="user-content-detailed-subsystems-in-the-block-diagram" class="" data-line-start="123" data-line-end="123"&gt;&lt;b&gt;Detailed Subsystems in the Block Diagram:&lt;/b&gt;&lt;/h3&gt;
&lt;ol data-line-start="125" data-line-end="156"&gt;
&lt;li data-line-start="125" data-line-end="126"&gt;
&lt;p class="" data-line-start="125" data-line-end="125"&gt;&lt;strong data-line-start="125" data-line-end="125"&gt;Connection Initialization:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-line-start="126" data-line-end="126"&gt;
&lt;li data-line-start="126" data-line-end="126"&gt;At the far left of the diagram, a &lt;strong data-line-start="126" data-line-end="126"&gt;TCP Open Connection&lt;/strong&gt; function takes the target IP (&lt;code class="whitespace-pre-wrap" data-line-start="126" data-line-end="126"&gt;192.168.1.12&lt;/code&gt; or &lt;code class="whitespace-pre-wrap" data-line-start="126" data-line-end="126"&gt;127.0.0.1&lt;/code&gt;) and Port (&lt;code class="whitespace-pre-wrap" data-line-start="126" data-line-end="126"&gt;5005&lt;/code&gt;). A 5000 ms timeout constant prevents the VI from hanging if the bedside station is powered off.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-line-start="128" data-line-end="129"&gt;
&lt;p class="" data-line-start="128" data-line-end="128"&gt;&lt;strong data-line-start="128" data-line-end="128"&gt;CRLF-Delimited TCP Reading:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-line-start="129" data-line-end="129"&gt;
&lt;li data-line-start="129" data-line-end="129"&gt;Inside the main While Loop, we use &lt;strong data-line-start="129" data-line-end="129"&gt;TCP Read.vi&lt;/strong&gt; configured in &lt;strong data-line-start="129" data-line-end="129"&gt;Standard Mode (Mode 1)&lt;/strong&gt; with a Carriage Return / Line Feed (&lt;code class="whitespace-pre-wrap" data-line-start="129" data-line-end="129"&gt;\r\n&lt;/code&gt;) delimiter. Rather than guessing byte lengths or implementing complex byte-header framing, LabVIEW reads until it encounters &lt;code class="whitespace-pre-wrap" data-line-start="129" data-line-end="129"&gt;\n&lt;/code&gt;. Because our Python backend appends &lt;code class="whitespace-pre-wrap" data-line-start="129" data-line-end="129"&gt;\r\n&lt;/code&gt; to every frame, LabVIEW yields one complete, pristine JSON frame per iteration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-line-start="131" data-line-end="146"&gt;
&lt;p class="" data-line-start="131" data-line-end="131"&gt;&lt;strong data-line-start="131" data-line-end="131"&gt;JSON Unflattening via Type Prototype Cluster:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-line-start="132" data-line-end="146"&gt;
&lt;li data-line-start="132" data-line-end="132"&gt;The ASCII string output from &lt;code class="whitespace-pre-wrap" data-line-start="132" data-line-end="132"&gt;TCP Read&lt;/code&gt; is wired directly into the JSON String terminal of &lt;strong data-line-start="132" data-line-end="132"&gt;Unflatten From JSON.vi&lt;/strong&gt;.&lt;/li&gt;
&lt;li data-line-start="133" data-line-end="146"&gt;To the &lt;code class="whitespace-pre-wrap" data-line-start="133" data-line-end="133"&gt;type and defaults&lt;/code&gt; terminal, we wired a strict LabVIEW &lt;strong data-line-start="133" data-line-end="133"&gt;Cluster Constant&lt;/strong&gt; defining the exact schema:
&lt;ul data-line-start="134" data-line-end="146"&gt;
&lt;li data-line-start="134" data-line-end="134"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="134" data-line-end="134"&gt;ts&lt;/code&gt; (Double-precision float: Epoch timestamp)&lt;/li&gt;
&lt;li data-line-start="135" data-line-end="135"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="135" data-line-end="135"&gt;heart_rate&lt;/code&gt; &amp;amp; &lt;code class="whitespace-pre-wrap" data-line-start="135" data-line-end="135"&gt;hr_bpm&lt;/code&gt; (32-bit signed integers)&lt;/li&gt;
&lt;li data-line-start="136" data-line-end="136"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="136" data-line-end="136"&gt;hr_valid&lt;/code&gt; (Integer boolean flag: 1 = Valid, 0 = Baseline)&lt;/li&gt;
&lt;li data-line-start="137" data-line-end="137"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="137" data-line-end="137"&gt;spo2&lt;/code&gt; (32-bit signed integer: Blood oxygen percentage)&lt;/li&gt;
&lt;li data-line-start="138" data-line-end="138"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="138" data-line-end="138"&gt;spo2_valid&lt;/code&gt; (Integer boolean flag)&lt;/li&gt;
&lt;li data-line-start="139" data-line-end="139"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="139" data-line-end="139"&gt;breath_bpm&lt;/code&gt; (Single-precision float: Respiration rate)&lt;/li&gt;
&lt;li data-line-start="140" data-line-end="140"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="140" data-line-end="140"&gt;temp_c&lt;/code&gt; &amp;amp; &lt;code class="whitespace-pre-wrap" data-line-start="140" data-line-end="140"&gt;room_temp_c&lt;/code&gt; (Single-precision float: Ambient temp)&lt;/li&gt;
&lt;li data-line-start="141" data-line-end="141"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="141" data-line-end="141"&gt;disturbance&lt;/code&gt; (Single-precision float: 0.0 - 100.0 restlessness)&lt;/li&gt;
&lt;li data-line-start="142" data-line-end="142"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="142" data-line-end="142"&gt;sleep_stage&lt;/code&gt; (String: &amp;quot;WAKE&amp;quot;, &amp;quot;N1&amp;quot;, &amp;quot;N2&amp;quot;, &amp;quot;N3&amp;quot;, &amp;quot;REM&amp;quot;)&lt;/li&gt;
&lt;li data-line-start="143" data-line-end="143"&gt;&lt;code class="whitespace-pre-wrap" data-line-start="143" data-line-end="143"&gt;sleep_stage_numeric&lt;/code&gt; (32-bit integer: 0=N3, 1=N2, 2=REM, 3=N1, 4=WAKE)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-line-start="148" data-line-end="153"&gt;
&lt;p class="" data-line-start="148" data-line-end="148"&gt;&lt;strong data-line-start="148" data-line-end="148"&gt;Telemetry Extraction &amp;amp; Front Panel Indicators:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-line-start="149" data-line-end="153"&gt;
&lt;li data-line-start="149" data-line-end="153"&gt;The parsed cluster passes into &lt;strong data-line-start="149" data-line-end="149"&gt;Unbundle By Name.vi&lt;/strong&gt;, splitting into dedicated Front Panel channels:
&lt;ul data-line-start="150" data-line-end="153"&gt;
&lt;li data-line-start="150" data-line-end="150"&gt;&lt;strong data-line-start="150" data-line-end="150"&gt;Vitals Waveform Charts:&lt;/strong&gt; Three distinct, rolling visual charts plotting Heart Rate (40&amp;ndash;120 BPM), SpO2 (90&amp;ndash;100%), and Respiration Rate (0&amp;ndash;30 BPM) with 60-second history buffers.&lt;/li&gt;
&lt;li data-line-start="151" data-line-end="151"&gt;&lt;strong data-line-start="151" data-line-end="151"&gt;3-Axis Movement Waveform:&lt;/strong&gt; A multi-plot graph showing &lt;code class="whitespace-pre-wrap" data-line-start="151" data-line-end="151"&gt;accel_x&lt;/code&gt;, &lt;code class="whitespace-pre-wrap" data-line-start="151" data-line-end="151"&gt;accel_y&lt;/code&gt;, and &lt;code class="whitespace-pre-wrap" data-line-start="151" data-line-end="151"&gt;accel_z&lt;/code&gt;. When the user is calm, &lt;code class="whitespace-pre-wrap" data-line-start="151" data-line-end="151"&gt;accel_z&lt;/code&gt; sits right near &lt;code class="whitespace-pre-wrap" data-line-start="151" data-line-end="151"&gt;1.0 G&lt;/code&gt; (Earth gravity); when restless, sharp oscillations visually reflect micro-awakenings.&lt;/li&gt;
&lt;li data-line-start="152" data-line-end="152"&gt;&lt;strong data-line-start="152" data-line-end="152"&gt;Sleep Stage Enum Bar:&lt;/strong&gt; Mapped from &lt;code class="whitespace-pre-wrap" data-line-start="152" data-line-end="152"&gt;sleep_stage_numeric&lt;/code&gt; to show the active hypnogram state in real time.&lt;/li&gt;
&lt;li data-line-start="153" data-line-end="153"&gt;&lt;strong data-line-start="153" data-line-end="153"&gt;Hardware Diagnostics:&lt;/strong&gt; LED boolean indicators showing BLE wristband connectivity and alarm status.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-line-start="155" data-line-end="156"&gt;
&lt;p class="" data-line-start="155" data-line-end="155"&gt;&lt;strong data-line-start="155" data-line-end="155"&gt;Automated Continuous File Logging:&lt;/strong&gt;&lt;/p&gt;
&lt;ul data-line-start="156" data-line-end="156"&gt;
&lt;li data-line-start="156" data-line-end="156"&gt;Rather than prompting the user with a dialog, the unbundled data is piped into an automated file-writing pipeline that records every sample to a CSV file on disk.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p class="" data-line-start="158" data-line-end="159"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_25-182151.png" /&gt;&lt;/p&gt;
&lt;p class="" data-line-start="158" data-line-end="159"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pleeec2" data-line-start="132" data-line-end="132"&gt;&lt;b&gt;The Clinical Mandate: Why National Instruments LabVIEW?&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="134" data-line-end="140"&gt;For this specific blog update, I want to direct all attention to the National Instruments LabVIEW portion of the project. While the Arduino Uno Q hosts a built-in web dashboard on port 7000 that works nicely for everyday home monitoring, a clinical healthcare system demands something far more rigorous. In a medical research setting, a hospital sleep clinic, or a biomedical testing laboratory, clinicians and researchers do not want a mobile-friendly browser interface.&lt;/p&gt;
&lt;p class="" data-line-start="142" data-line-end="147"&gt;They require high-precision continuous waveform visualization, deterministic data acquisition without browser rendering jitter, synchronous multi-channel signal alignment, and direct, uninterrupted file logging into spreadsheets for post-hoc polysomnography validation. National Instruments LabVIEW is the worldwide standard for virtual instrumentation, medical equipment interfaces, and complex automated data logging.&lt;/p&gt;
&lt;p class="" data-line-start="149" data-line-end="158"&gt;When a sleep specialist reviews patient data, they need to examine the raw morphology of vitals over time. They want to see the exact relationship between an elevation in wrist movement energy and a subsequent drop in blood oxygen saturation, or observe how an abrupt change in respiration rate correlates with an autonomic heart rate spike. Browser-based charting libraries like Chart.js or Canvas are inherently limited by JavaScript&amp;#39;s single-threaded event loop and garbage collection pauses, which frequently introduce visual stutter and micro- delays. LabVIEW, on the other hand, runs directly on native hardware execution threads, guaranteeing deterministic waveform rendering that never misses a single incoming frame.&lt;/p&gt;
&lt;p class="" data-line-start="160" data-line-end="165"&gt;My goal was to turn LabVIEW into the central clinical telemetry workstation for Palno &amp;amp; Slemon. I wanted any monitoring PC on the hospital or laboratory network to wirelessly ingest our complete multi-sensor stream at ten samples per second, display every vital sign on specialized medical charts, and automatically save every single data point to disk without requiring any human operator to intervene.&lt;/p&gt;
&lt;p class="" data-line-start="160" data-line-end="165"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5plgt8l3" data-line-start="220" data-line-end="220"&gt;&lt;b&gt;The Journey Across Five Revisions: From Loose Scripts to Containerized Harmony&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="222" data-line-end="229"&gt;Getting to a fully functional system did not happen overnight. In fact, it required five exhaustive architectural revisions, each resolving critical weaknesses discovered during testing. In the very first revision, the system consisted of disparate standalone scripts running directly on the Linux host with manual terminal executions. I had to manually SSH into the board, run an audio test script, open a serial listener for the radar, and manually initiate Bluetooth scanning. It was fragile, crashed whenever a terminal disconnected, and lacked any cohesive orchestration.&lt;/p&gt;
&lt;p class="" data-line-start="231" data-line-end="236"&gt;In revision two, I attempted to containerize the application within the Arduino App Lab environment. This introduced immediate permission barriers. The Docker container was isolated from the Linux host&amp;#39;s D-Bus daemon and Bluetooth subsystems, which meant that our Python code could not see or pair with the Palno ESP32 wristband. We had to spend days exploring socket bridging to expose the system bus into the container space.&lt;/p&gt;
&lt;p class="" data-line-start="238" data-line-end="242"&gt;Revision three brought the initial implementation of the NI LabVIEW bridge, but it suffered from severe latency and thread contention. Sensor polling, algorithmic sleep stage calculations, and socket broadcasting were all running on the main application thread. Every time an algorithm did heavy computation, the LabVIEW output stalled, and the TCP socket dropped packets.&lt;/p&gt;
&lt;p class="" data-line-start="244" data-line-end="249"&gt;Revision four resolved the thread blocking by introducing threading workers, but introduced a static networking trap. The systemd services on the host machine were hardcoded to point to container names and IP addresses specific to revision four. The moment I uploaded revision five via App Lab, the entire background forwarding system collapsed because Docker created a new network namespace with different IP addresses.&lt;/p&gt;
&lt;p class="" data-line-start="251" data-line-end="257"&gt;Finally, in revision five, we achieved a truly production-grade, autonomous architecture. We established dynamic host scripts that auto-detect container IPs, created an isolated ten-Hertz non-blocking telemetry broadcast thread, implemented physiological window filtering on the ESP32 firmware, and engineered zero-touch systemd boot orchestration. Every lesson learned across revisions one through four was consolidated into revision five, creating an ecosystem that starts automatically on boot and streams flawlessly to LabVIEW.&lt;/p&gt;
&lt;p class="" data-line-start="251" data-line-end="257"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pli5qg4" data-line-start="262" data-line-end="262"&gt;&lt;b&gt;The Nightmare of JSON Unflattening Error Hex 0xFFFA4725&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="264" data-line-end="269"&gt;Translating raw embedded data into clean visual streams in LabVIEW took a massive amount of troubleshooting, and I ran headfirst into several severe bugs that tested my patience. The first obstacle appeared the very moment I attempted to parse the network stream, manifesting as the dreaded LabVIEW Error Hex 0xFFFA4725, which reported that the JSON string was invalid and did not conform to the JSON grammar.&lt;/p&gt;
&lt;p class="" data-line-start="271" data-line-end="276"&gt;When I wired a string indicator to the output of the TCP Read block, the incoming payload appeared truncated, ending abruptly in the middle of a word or bracket. At first, I assumed there was an issue with character encoding or hidden non-printable bytes. I spent hours inspecting string length nodes, checking for null bytes, and experimenting with UTF-8 byte order marks. But upon auditing the Python backend on the Uno Q, I uncovered the real culprit.&lt;/p&gt;
&lt;p class="" data-line-start="278" data-line-end="284"&gt;In my general web backend, I had included a historical data array called hypnogram inside the JSON packet so the web dashboard could render a twenty- minute sleep stage history. That array contained dozens of nested dictionaries, which inflated the size of each single-line JSON transmission to over 2.5 kilobytes. In streaming socket communication using carriage return and line feed delimiters, sending a 2.5-kilobyte string in a single burst causes network fragmentation across TCP packet boundaries.&lt;/p&gt;
&lt;p class="" data-line-start="286" data-line-end="291"&gt;When LabVIEW&amp;#39;s TCP Read buffer received the incoming stream, it only read the first chunk up to the buffer boundary, resulting in an incomplete, half-formed JSON fragment that lacked closing brackets. LabVIEW received half of the JSON object, couldn&amp;#39;t find the closing bracket, and threw a fatal syntax error. The parser simply could not unflatten an open-ended fragment into a strict LabVIEW Type Cluster.&lt;/p&gt;
&lt;p class="" data-line-start="293" data-line-end="300"&gt;To eliminate this bug, I went back into the Python engine on the Uno Q and engineered a dedicated serialization routine named get_labview_payload. This method completely stripped out all bulky historical arrays, nested dictionaries, and non-essential strings, producing a compact, strictly scalar JSON payload of approximately 390 bytes. I configured the serializer to output pure ASCII characters, explicitly disallowed any NaN or null floating-point representations, and terminated every single transmission with an explicit carriage return and line feed escape sequence.&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;The exact payload structure was refined to contain only immediate scalar metrics: timestamp, heart rate, heart rate validity, blood oxygen level, oxygen validity, respiration rate, ambient temperature, restlessness disturbance index, sleep stage text, numeric sleep stage, BLE connection state, smart alarm trigger flag, and three-axis accelerometer vectors. As soon as I uploaded this fix, the transmission payload shrank by eighty-five percent. LabVIEW was able to ingest the entire 390-byte packet in a single read cycle, and the JSON unflattening syntax error vanished completely.&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;&lt;pre class="ui-code" data-mode="python"&gt;def get_labview_payload(self, now: float) -&amp;gt; dict:
    stage_map = {&amp;quot;N3&amp;quot;: 0, &amp;quot;N2&amp;quot;: 1, &amp;quot;REM&amp;quot;: 2, &amp;quot;N1&amp;quot;: 3, &amp;quot;WAKE&amp;quot;: 4}
    return {
        &amp;quot;ts&amp;quot;: round(now, 2),
        &amp;quot;breath_bpm&amp;quot;: round(self.breath_engine.breath_bpm, 1),
        &amp;quot;hr_bpm&amp;quot;: int(self.heart_rate),
        &amp;quot;heart_rate&amp;quot;: int(self.heart_rate),
        &amp;quot;hr_valid&amp;quot;: int(self.hr_valid),
        &amp;quot;spo2&amp;quot;: int(self.spo2),
        &amp;quot;spo2_valid&amp;quot;: int(self.spo2_valid),
        &amp;quot;room_temp_c&amp;quot;: round(self.room_temp_c, 2),
        &amp;quot;temp_c&amp;quot;: round(self.room_temp_c, 2),
        &amp;quot;disturbance&amp;quot;: round(self.breath_engine.disturbance, 1),
        &amp;quot;sleep_stage&amp;quot;: self.current_stage,
        &amp;quot;stage&amp;quot;: self.current_stage,
        &amp;quot;sleep_stage_numeric&amp;quot;: stage_map.get(self.current_stage, 4),
        &amp;quot;alarm_active&amp;quot;: bool(self.alarm_triggered),
        &amp;quot;ble_connected&amp;quot;: bool(self.ble_client.state.get(&amp;quot;connected&amp;quot;, False)),
        &amp;quot;sleep_score&amp;quot;: int(self.sleep_score),

    }&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;And here is the exact, unflatten-ready JSON frame that LabVIEW receives across the Wi-Fi socket on port 5005 ten times every second. Notice how every single key is a clean primitive number, string, or boolean:&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;&lt;pre class="ui-code" data-mode="json"&gt;{
  &amp;quot;ts&amp;quot;: 1792931468.36,
  &amp;quot;breath_bpm&amp;quot;: 15.0,
  &amp;quot;hr_bpm&amp;quot;: 71,
  &amp;quot;heart_rate&amp;quot;: 71,
  &amp;quot;hr_valid&amp;quot;: 1,
  &amp;quot;spo2&amp;quot;: 98,
  &amp;quot;spo2_valid&amp;quot;: 1,
  &amp;quot;room_temp_c&amp;quot;: 28.27,
  &amp;quot;temp_c&amp;quot;: 28.27,
  &amp;quot;disturbance&amp;quot;: 9.2,
  &amp;quot;sleep_stage&amp;quot;: &amp;quot;WAKE&amp;quot;,
  &amp;quot;stage&amp;quot;: &amp;quot;WAKE&amp;quot;,
  &amp;quot;sleep_stage_numeric&amp;quot;: 4,
  &amp;quot;alarm_active&amp;quot;: false,
  &amp;quot;ble_connected&amp;quot;: true,
  &amp;quot;sleep_score&amp;quot;: 85,
  }&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;As soon as I uploaded this fix, the transmission payload shrank by eighty-five percent. LabVIEW was able to ingest the entire 390-byte packet in a single read cycle, and the JSON unflattening syntax error vanished completely.&lt;/p&gt;
&lt;p class="" data-line-start="302" data-line-end="309"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pltt9o5" data-line-start="370" data-line-end="370"&gt;&lt;b&gt;Network Ghosting: Diagnosing Error Hex 0x42 and Docker Bridge Reallocations&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="" data-line-start="372" data-line-end="375"&gt;Just as I was celebrating the JSON fix, a second major bug brought the pipeline down. I updated the Uno Q with version five of our application container, and immediately LabVIEW refused to connect, throwing Error Hex 0x42, stating that the network connection was closed by the peer.&lt;/p&gt;
&lt;p class="" data-line-start="377" data-line-end="381"&gt;I was baffled because running netstat on the Linux host confirmed that port 5005 was actively listening, yet every connection attempt from my Windows PC was instantly reset. The socket would accept the initial handshake and immediately close without sending a single byte. It felt like the network was haunted by ghost connections.&lt;/p&gt;
&lt;p class="" data-line-start="383" data-line-end="389"&gt;After digging into Docker&amp;#39;s internal networking with docker inspect, I finally unmasked the problem. The background systemd forwarder service on the Linux host, labview-forward.service, had been statically configured to pipe incoming port 5005 traffic to the container IP address 172.18.0.2. That IP address had belonged to the older version four container. When the Arduino App Lab platform built and launched version five, Docker automatically created a new virtual bridge network and assigned the new container the IP address 172.19.0.2.&lt;/p&gt;
&lt;p class="" data-line-start="391" data-line-end="394"&gt;The host forwarder was faithfully redirecting LabVIEW&amp;#39;s incoming packets to a dead, non-existent IP address. Because no process was listening on 172.18.0.2, the Linux kernel immediately responded with a TCP Reset packet, which LabVIEW translated as Error Hex 0x42.&lt;/p&gt;
&lt;p class="" data-line-start="396" data-line-end="400"&gt;To permanently prevent this from ever happening again, I created a dynamic shell script called labview_forwarder.sh on the Linux host. The script uses Docker inspection commands to query the active container ID in real time, extracts its live IP address regardless of what bridge network Docker creates, and dynamically establishes the socat forwarding bridge:&lt;/p&gt;
&lt;p class="" data-line-start="396" data-line-end="400"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="396" data-line-end="400"&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;#!/bin/bash
# labview_forwarder.sh — Dynamically forwards port 5005 to whichever container is active

echo &amp;quot;[FORWARDER] Dynamic LabVIEW Port 5005 Forwarder starting...&amp;quot;

while true; do
    CONTAINER_ID=$(docker ps -q --filter &amp;quot;name=main-1&amp;quot; | head -1)
    if [ -n &amp;quot;$CONTAINER_ID&amp;quot; ]; then
        CONTAINER_IP=$(docker inspect -f &amp;#39;{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}&amp;#39; &amp;quot;$CONTAINER_ID&amp;quot;)
        if [ -n &amp;quot;$CONTAINER_IP&amp;quot; ]; then
            echo &amp;quot;[FORWARDER] Found container $CONTAINER_ID at $CONTAINER_IP - starting socat...&amp;quot;
            socat TCP-LISTEN:5005,fork,reuseaddr TCP:&amp;quot;$CONTAINER_IP&amp;quot;:5005
        fi
    fi
    sleep 2
done&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="396" data-line-end="400"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="396" data-line-end="400"&gt;The script continuously verifies that the container is alive, and if the container restarts or acquires a new IP, socat rebinds to the correct destination within two seconds. With this dynamic script active, LabVIEW reconnected immediately and proved immune to future container rebuilds.&lt;/p&gt;
&lt;p class="" data-line-start="396" data-line-end="400"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pm1fov6" data-line-start="429" data-line-end="429"&gt;&lt;b&gt;The Missing Dependency Trap: Bleak Library Not Installed&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;While testing version five, another unexpected error reared its head inside the Docker container logs. Even though our code had imported the Bleak Bluetooth library, the container log was suddenly reporting that Bleak was not installed and that the BLE client was running in fallback dummy mode.&lt;/p&gt;
&lt;p&gt;When I investigated how Arduino App Lab builds containers, I discovered the cause. The python folder inside our new version five workspace was missing a requirements.txt file. In version four, App Lab had cached the dependencies, but version five started with a fresh virtual environment. Without requirements.txt, pip never installed bleak or dbus-fast.&lt;/p&gt;
&lt;p&gt;I quickly created python/requirements.txt containing bleak&amp;gt;=0.21.0, dbus- fast&amp;gt;=2.0.0, and fastapi. The moment App Lab rebuilt the container, the virtual environment properly populated, and the Bleak scanner sprang to life.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pm2dj47" data-line-start="447" data-line-end="447"&gt;&lt;b&gt;The D-Bus Proxy Puzzle: Bridging Host Bluetooth into an Isolated Container&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="449" data-line-end="454"&gt;Even with Bleak installed, another related issue emerged regarding the Palno ESP32 BLE connection. On the Linux host, the BlueZ Bluetooth daemon controls the Qualcomm radio hardware and creates a Unix domain socket at /var/run/dbus/system_bus_socket. However, inside our Docker container, that socket did not exist, meaning the Bleak Python library had no way to issue scan or connect commands to the Bluetooth hardware.&lt;/p&gt;
&lt;p class="" data-line-start="456" data-line-end="459"&gt;To solve this, we created a background service called dbus-proxy.service that runs socat on the host. It listens on a socket placed inside the application directory and bridges it to the host D-Bus socket. But the first time we ran it, Bleak threw an authentication error: REJECTED: ['EXTERNAL'].&lt;/p&gt;
&lt;p class="" data-line-start="461" data-line-end="466"&gt;This was another deeply technical Linux mystery. The host systemd service was originally executing socat as root (UID 0), whereas the Docker container process was executing as the standard non-privileged user arduino (UID 1000). When D-Bus performs SASL EXTERNAL authentication over Unix domain sockets, the kernel checks the peer credentials (SO_PEERCRED). Because UID 0 did not match UID 1000, D-Bus rejected the connection for security reasons.&lt;/p&gt;
&lt;p class="" data-line-start="468" data-line-end="471"&gt;To fix this, we reconfigured the systemd unit to run strictly under User=arduino, ensuring that the UID matched the container user perfectly. Furthermore, we created dbus_proxy.sh to dynamically bind the socket into whichever slemon_app folder is active at boot time:&lt;/p&gt;
&lt;p class="" data-line-start="468" data-line-end="471"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="468" data-line-end="471"&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;#!/bin/bash
# dbus_proxy.sh — Proxies D-Bus into the active slemon_app directory for Palno BLE
ACTIVE_APP=$(ls -td /home/arduino/ArduinoApps/slemon_app* 2&amp;gt;/dev/null | head -1)

if [ -z &amp;quot;$ACTIVE_APP&amp;quot; ] || [ ! -d &amp;quot;$ACTIVE_APP&amp;quot; ]; then
    ACTIVE_APP=&amp;quot;/home/arduino/ArduinoApps/slemon_app_v5&amp;quot;
fi

echo &amp;quot;[DBUS] Active app is: $ACTIVE_APP&amp;quot;
rm -f &amp;quot;$ACTIVE_APP/system_bus_socket&amp;quot;
exec /usr/bin/socat UNIX-LISTEN:&amp;quot;$ACTIVE_APP/system_bus_socket&amp;quot;,fork,unlink-early,mode=777 UNIX-CONNECT:/var/run/dbus/system_bus_socket&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="468" data-line-end="471"&gt;The moment that permission mismatch was corrected, the authentication succeeded, and the container was able to discover and connect to the Palno ESP32 seamlessly.&lt;/p&gt;
&lt;p class="" data-line-start="468" data-line-end="471"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pm5car9" data-line-start="536" data-line-end="536"&gt;&lt;b&gt;The Phantom Popup: Demystifying File Logging Error Hex 0x2B&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="538" data-line-end="543"&gt;The next issue occurred when I implemented automated data logging to record the sleep session to disk. My objective was to write every incoming vital sign into a continuous CSV file on my PC so that an overnight sleep record could be analyzed in medical software or Excel. But as soon as I added the file writing function to the While Loop, LabVIEW crashed with Error Hex 0x2B, indicating that the operation was cancelled by the user.&lt;/p&gt;
&lt;p class="" data-line-start="545" data-line-end="550"&gt;This error was deeply confusing because I had not cancelled anything. I had simply pressed the Run arrow, watched the charts plot for a fraction of a second, and watched the VI abruptly halt. Being new to LabVIEW&amp;#39;s file I/O palette, I had dropped the Open/Create/Replace File block onto the diagram but had left its file path terminal unwired, assuming LabVIEW would default to the current project directory.&lt;/p&gt;
&lt;p class="" data-line-start="552" data-line-end="556"&gt;In LabVIEW, when the file path terminal of a file creation block is left empty or unwired, the function automatically spawns an interactive Windows File Dialog asking the user to choose or confirm a filename. Because my While Loop was executing ten times per second, LabVIEW was attempting to spawn this modal dialog ten times a second.&lt;/p&gt;
&lt;p class="" data-line-start="558" data-line-end="563"&gt;The moment the dialog appeared, the Windows operating system intercepted the application thread. If the user clicked Cancel, closed the window, or if the dialog was dismissed by a focus change, LabVIEW registered an aborted file operation. In LabVIEW&amp;#39;s standard error handling flow, any error on the error cluster wire halts subsequent execution, which immediately terminated the entire data acquisition loop.&lt;/p&gt;
&lt;p class="" data-line-start="565" data-line-end="572"&gt;I solved this by placing an explicit File Path Constant on the block diagram, typing in the exact destination path on my hard drive (C:\PY_work\zlgothirm\sleep_data_log.csv), setting the file operation mode to open or create, and enabling the append flag. By wiring this static path, LabVIEW checks if the spreadsheet exists, creates it automatically if it is missing, and continuously appends every new line of biometric data silently in the background without ever prompting the user or interrupting the streaming charts.&lt;/p&gt;
&lt;p class="" data-line-start="565" data-line-end="572"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_25-193744.png" /&gt;&lt;/p&gt;
&lt;h2 id="user-content-breaking-the-bottleneck-decoupling-e-ink-refreshes-and-creating-the-10-hz-telemetry-worker" class="" data-line-start="577" data-line-end="577"&gt;&lt;b&gt;Breaking the Bottleneck: Decoupling E-Ink Refreshes and Creating the 10 Hz Telemetry Worker&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="579" data-line-end="582"&gt;The next major challenge was eliminating UI lag and chart stuttering. In our earliest software prototype, the Python backend on the Uno Q was running sensor polling, E-ink display updates, and LabVIEW network broadcasting inside a single procedural loop.&lt;/p&gt;
&lt;p class="" data-line-start="584" data-line-end="588"&gt;The bedside station features a local E-ink screen that updates every minute to show the user their current sleep stage, sleep score, and room temperature. E-ink displays are notoriously slow to refresh. They require an extensive series of SPI commands, waveform lookup table uploads, and a full physical pigment flashing cycle that takes over a second to complete.&lt;/p&gt;
&lt;p class="" data-line-start="590" data-line-end="596"&gt;Because sensor processing, display updates, and socket streaming were executing sequentially on the same main Python thread, the entire LabVIEW TCP server froze for over a second every time the E-ink screen redrew itself. On my Windows PC, the LabVIEW waveform charts would roll smoothly for fifty-nine seconds, freeze completely for over a second, and then jump forward abruptly as the backlog of packets cleared. This periodic jitter destroyed the clinical fidelity of the waveforms.&lt;/p&gt;
&lt;p class="" data-line-start="598" data-line-end="599"&gt;To fix this, I decoupled the LabVIEW telemetry stream into its own independent, non-blocking background thread executing at a steady ten Hertz:&lt;/p&gt;
&lt;p class="" data-line-start="598" data-line-end="599"&gt;&lt;pre class="ui-code" data-mode="python"&gt;def telemetry_worker():
    logger.info(&amp;quot;[TELEMETRY] Dedicated 10 Hz telemetry and LabVIEW TCP broadcast started.&amp;quot;)
    while True:
        try:
            now = time.time()
            telemetry_payload = app_mgr.get_telemetry_payload(now)
            ui.send_message(&amp;quot;telemetry&amp;quot;, telemetry_payload)

            labview_payload = app_mgr.get_labview_payload(now)
            lv_bridge.broadcast(labview_payload)
        except Exception as e:
            logger.warning(&amp;quot;[TELEMETRY] Broadcast error: %s&amp;quot;, e)
        time.sleep(UI_PUSH_INTERVAL_S)

telemetry_thread = threading.Thread(target=telemetry_worker, daemon=True)
telemetry_thread.start()&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="598" data-line-end="599"&gt;Even if the microcontroller takes several seconds to redraw the E-ink display, poll an unresponsive I2C sensor, or execute heavy algorithmic math, the LabVIEW telemetry worker continues to broadcast at exactly ten Hertz without dropping a single millisecond of data. The waveform charts in LabVIEW transitioned from stuttering graphs into silky-smooth, continuous clinical displays.&lt;/p&gt;
&lt;p class="" data-line-start="598" data-line-end="599"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pma6l8a" data-line-start="629" data-line-end="629"&gt;&lt;b&gt;Embedded Firmware Surgery: Taming the MAX30102 with Physiological Window Filters&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="631" data-line-end="634"&gt;Sending raw embedded sensor data directly into LabVIEW&amp;#39;s strict type-casting environment usually causes headaches because LabVIEW Type Clusters expect consistent numeric types. A single NaN, null, or sudden string in place of an integer will break the unflattening operation.&lt;/p&gt;
&lt;p class="" data-line-start="636" data-line-end="641"&gt;To ensure pristine transmission, I had to make critical improvements to the Palno wearable firmware running on the ESP32. Optical pulse oximetry sensors like the MAX30102 are highly susceptible to ambient light leakage and motion artifacts caused by tossing and turning in bed. The sensor works by shining red and infrared light through cutaneous capillary beds and measuring the ratio of pulsatile AC components to baseline DC components.&lt;/p&gt;
&lt;p class="" data-line-start="643" data-line-end="648"&gt;When a patient shifts their wrist or turns over, the optical sensor momentarily loses contact with the skin. Standard algorithmic calculations, such as the classic Maxim pulse oximetry routines, frequently misinterpret these optical baseline shifts as massive physiological spikes. The raw code will suddenly output an impossible heart rate of 166 BPM, drop down to 40 BPM, or output an invalid status where heart rate and SpO2 are reported as zero.&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;If raw, erratic numbers like that enter LabVIEW, they blow out the auto-scaling on waveform charts, trigger false alarm indicators, and corrupt statistical averages. To solve this, I wrote an intelligent physiological sliding-window filter in biometrics.h on the ESP32:&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// biometrics.h — Physiological Window &amp;amp; Outlier Substitution Engine
#define BIO_HIST_LEN 5
static int32_t hr_history[BIO_HIST_LEN]   = {72, 74, 73, 75, 72};
static int32_t spo2_history[BIO_HIST_LEN] = {98, 97, 98, 98, 99};

// Clamping boundaries to preserve physiological realism
if (raw_spo2 &amp;gt;= 94 &amp;amp;&amp;amp; raw_spo2 &amp;lt;= 100 &amp;amp;&amp;amp; spo2_valid) {
    spo2_history[spo2_idx] = raw_spo2;
    spo2_idx = (spo2_idx + 1) % BIO_HIST_LEN;
} else {
    // Substitute noisy read with moving average of valid window
    int32_t sum = 0;
    for (int i = 0; i &amp;lt; BIO_HIST_LEN; i++) sum += spo2_history[i];
    raw_spo2 = sum / BIO_HIST_LEN;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;The filter enforces strict physiological boundary clamps: blood oxygen saturation is bounded between ninety-four and one hundred percent, while resting heart rate is bounded between fifty and one hundred and ten beats per minute. Whenever the raw optical calculation is flagged as invalid or exhibits an impossible jump beyond physiological rate-of-change thresholds, the firmware suppresses the artifact and substitutes the value with the running moving average of the last five valid readings. This guarantees that the stream sent over BLE to the Uno Q, and subsequently broadcast to LabVIEW, is always biologically realistic, smooth, and perfectly formatted for uninterrupted clinical charting.&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;See the noise:&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;&lt;pre class="ui-code" data-mode="text"&gt;[DATA] HR=125 v=0 | SpO2=82 v=0 | AX=0.161 AY=0.127 AZ=1.023 | GX=0.4 GY=4.8 GZ=-0.9 | dA=0.043 | BLE=N Alarm=off
[DATA] HR=42 v=1 | SpO2=72 v=1 | AX=0.158 AY=0.127 AZ=1.023 | GX=0.4 GY=4.2 GZ=-1.2 | dA=0.043 | BLE=N Alarm=off
[DATA] HR=42 v=0 | SpO2=84 v=1 | AX=0.146 AY=0.124 AZ=1.021 | GX=-0.1 GY=5.1 GZ=-0.2 | dA=0.038 | BLE=N Alarm=off
[DATA] HR=83 v=1 | SpO2=84 v=0 | AX=0.139 AY=0.127 AZ=1.016 | GX=-0.1 GY=4.7 GZ=-0.5 | dA=0.033 | BLE=N Alarm=off
[DATA] HR=83 v=0 | SpO2=84 v=0 | AX=0.156 AY=0.125 AZ=1.014 | GX=0.1 GY=5.3 GZ=-0.9 | dA=0.034 | BLE=N Alarm=off
[DATA] HR=83 v=0 | SpO2=84 v=0 | AX=0.146 AY=0.125 AZ=1.022 | GX=-0.0 GY=5.7 GZ=-0.4 | dA=0.040 | BLE=N Alarm=off
[DATA] HR=71 v=1 | SpO2=84 v=0 | AX=0.137 AY=0.118 AZ=1.014 | GX=-0.0 GY=5.2 GZ=-0.2 | dA=0.030 | BLE=N Alarm=off
[DATA] HR=71 v=1 | SpO2=75 v=1 | AX=0.156 AY=0.126 AZ=1.018 | GX=-0.3 GY=5.0 GZ=-0.8 | dA=0.038 | BLE=N Alarm=off
[DATA] HR=107 v=1 | SpO2=98 v=1 | AX=0.148 AY=0.128 AZ=1.019 | GX=0.1 GY=5.3 GZ=-0.7 | dA=0.038 | BLE=N Alarm=off
[DATA] HR=136 v=1 | SpO2=83 v=1 | AX=0.149 AY=0.123 AZ=1.016 | GX=0.2 GY=4.5 GZ=0.0 | dA=0.035 | BLE=N Alarm=off
[DATA] HR=136 v=0 | SpO2=83 v=1 | AX=0.137 AY=0.118 AZ=1.014 | GX=-0.2 GY=4.4 GZ=-0.4 | dA=0.030 | BLE=N Alarm=off
[DATA] HR=136 v=0 | SpO2=83 v=1 | AX=0.143 AY=0.122 AZ=1.018 | GX=-0.0 GY=5.5 GZ=-0.9 | dA=0.035 | BLE=N Alarm=off
[DATA] HR=136 v=0 | SpO2=81 v=1 | AX=0.136 AY=0.118 AZ=1.016 | GX=0.2 GY=4.0 GZ=-0.5 | dA=0.032 | BLE=N Alarm=off
[DATA] HR=136 v=0 | SpO2=80 v=1 | AX=0.138 AY=0.120 AZ=1.014 | GX=0.2 GY=4.5 GZ=-0.1 | dA=0.030 | BLE=N Alarm=off
[DATA] HR=48 v=1 | SpO2=73 v=1 | AX=0.148 AY=0.123 AZ=1.021 | GX=0.0 GY=4.9 GZ=-0.5 | dA=0.039 | BLE=N Alarm=off
[DATA] HR=46 v=1 | SpO2=73 v=1 | AX=0.142 AY=0.124 AZ=1.015 | GX=-0.0 GY=4.0 GZ=-0.4 | dA=0.033 | BLE=N Alarm=off
[DATA] HR=166 v=1 | SpO2=73 v=0 | AX=0.109 AY=0.100 AZ=1.016 | GX=3.1 GY=-1.8 GZ=2.3 | dA=0.027 | BLE=N Alarm=off
[DATA] HR=166 v=0 | SpO2=72 v=1 | AX=0.163 AY=0.102 AZ=1.040 | GX=15.3 GY=-23.5 GZ=0.3 | dA=0.057 | BLE=N Alarm=off
[DATA] HR=166 v=0 | SpO2=72 v=0 | AX=0.311 AY=-0.378 AZ=0.509 | GX=72.4 GY=-178.9 GZ=-84.6 | dA=0.294 | BLE=N Alarm=off
[DATA] HR=166 v=0 | SpO2=94 v=1 | AX=0.071 AY=0.142 AZ=-1.024 | GX=12.2 GY=-47.8 GZ=11.7 | dA=0.036 | BLE=N Alarm=off
[DATA] HR=166 v=0 | SpO2=98 v=1 | AX=0.056 AY=0.029 AZ=-1.009 | GX=26.4 GY=-19.0 GZ=5.0 | dA=0.011 | BLE=N Alarm=off&lt;/pre&gt;&lt;/p&gt;
&lt;p class="" data-line-start="650" data-line-end="653"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pmfj6kb" data-line-start="870" data-line-end="870"&gt;&lt;b&gt;Dissecting the LabVIEW Block Diagram: From TCP Socket to File Writer&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="" data-line-start="872" data-line-end="875"&gt;Understanding how data moves through the LabVIEW Block Diagram reveals the power of graphical dataflow programming. The entire application is structured around a sequential, error-propagating architecture that guarantees deterministic execution.&lt;/p&gt;
&lt;p class="" data-line-start="877" data-line-end="881"&gt;At the far left of the diagram, the initialization sequence begins. The IP Address and Port controls feed into the TCP Open Connection function. A numeric constant of 5000 milliseconds is wired to the timeout terminal, ensuring that if the bedside station is powered off or disconnected from Wi-Fi, the VI will not freeze indefinitely but will raise an informative timeout error.&lt;/p&gt;
&lt;p class="" data-line-start="883" data-line-end="890"&gt;The resulting connection ID and error cluster wires pass through the boundary of the main While Loop via shift registers. Inside the While Loop, the connection ID connects to the TCP Read block. The TCP Read function is configured in Mode 1 (Standard CRLF Delimited Mode). In this mode, LabVIEW ignores arbitrary byte counts and instead buffers incoming network bytes until it encounters the carriage return and line feed termination sequence (\r\n). Because our Python backend appends \r\n to every JSON packet, TCP Read cleanly yields exactly one complete telemetry string on every iteration.&lt;/p&gt;
&lt;p class="" data-line-start="892" data-line-end="898"&gt;The raw ASCII string output connects directly to the JSON String terminal of the Unflatten From JSON function. Wired into the type and defaults terminal of this block is the master Type Prototype Cluster. This cluster contains strictly typed default constants that match our JSON keys: a double-precision float for timestamp, signed 32-bit integers for heart rate and SpO2, single-precision floats for respiration rate, ambient temperature, and disturbance, strings and integers for sleep stages, and booleans for BLE connectivity and alarm state.&lt;/p&gt;
&lt;p class="" data-line-start="900" data-line-end="904"&gt;The unflattened cluster output feeds into an Unbundle By Name block. This block acts as a demultiplexer, exposing every individual signal as an independent wire. Heart rate connects to the HR chart, SpO2 connects to the oxygen chart, respiration rate connects to the breathing chart, and the three acceleration floats are combined into a cluster to drive the multi-plot motion graph.&lt;/p&gt;
&lt;p class="" data-line-start="906" data-line-end="911"&gt;Simultaneously, the unbundled numeric values are wired into a Format Into String function that constructs a comma-delimited CSV text row, appending a newline character. This formatted string connects to the Write to Text File function. Before the While Loop started, an Open/Create/Replace File block initialized the file handle using our fixed File Path Constant with open or create mode. Inside the loop, each new row is appended to disk.&lt;/p&gt;
&lt;p class="" data-line-start="913" data-line-end="919"&gt;The loop timing is governed by the incoming TCP socket stream. Because the Python backend broadcasts at ten Hertz, the TCP Read block naturally paces the loop at a stable 100-millisecond execution interval. When the operator clicks the Stop button on the Front Panel, the While Loop terminates, the file handle passes to the Close File block, the connection ID passes to the TCP Close Connection block, and any runtime errors are reported through the Simple Error Handler.&lt;/p&gt;
&lt;p class="" data-line-start="913" data-line-end="919"&gt;&lt;/p&gt;
&lt;p class="" data-line-start="913" data-line-end="919"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pmh050c" data-line-start="924" data-line-end="924"&gt;&lt;b&gt;Zero-Touch Automation Across Reboots: The Linux Systemd Boot Orchestrator&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="" data-line-start="926" data-line-end="930"&gt;One of my strictest self-imposed requirements for this challenge was that the system must be completely autonomous. A consumer or healthcare product cannot require a user to open a terminal, type SSH commands, or run shell scripts every time the power is plugged in. If the power blinks in the middle of the night, the system must recover and resume monitoring completely on its own.&lt;/p&gt;
&lt;p class="" data-line-start="932" data-line-end="935"&gt;To accomplish this on the Arduino Uno Q, I created a master boot orchestration service called slemon-startup.service, managed by the Linux systemd daemon. When the Uno Q powers on, systemd executes slemon_startup.sh, a robust shell script located in the home directory.&lt;/p&gt;
&lt;p class="" data-line-start="937" data-line-end="943"&gt;The script executes a precise sequence of boot initialization steps. First, it brings up the Qualcomm Bluetooth radio by calling hciconfig hci0 up and bluetoothctl power on. Second, it dynamically inspects the file system and Docker daemon to locate whichever application version is active, completely eliminating hardcoded directory paths. Third, it updates the Docker container&amp;#39;s restart policy to unless-stopped, guaranteeing that Docker will automatically boot the container on startup.&lt;/p&gt;
&lt;p class="" data-line-start="945" data-line-end="950"&gt;Fourth, the script verifies that all three critical background helper services are active: dbus-proxy.service, which proxies the host Bluetooth D-Bus socket into the Docker container so the Bleak library can communicate with the Palno ESP32; labview-forward.service, which dynamically resolves the container IP and forwards TCP port 5005; and bt-host-agent.service, which manages Bluetooth Classic A2DP audio pairing for the external speaker.&lt;/p&gt;
&lt;p class="" data-line-start="952" data-line-end="958"&gt;Finally, the script writes a connection request to trigger auto-pairing with the ZEBRONICS Bluetooth speaker. Inside the container, the Python application initializes its sensor workers, launches the ten-Hertz LabVIEW broadcast server, auto-connects to the Palno wristband via BLE, and begins streaming. From a cold power-on, the entire ecosystem is fully operational, connected to Palno, and streaming to LabVIEW within fifteen seconds, with zero terminal commands required.&lt;/p&gt;
&lt;p class="" data-line-start="952" data-line-end="958"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pmmgn8d" data-line-start="963" data-line-end="963"&gt;&lt;b&gt;The Clinician&amp;#39;s Verification Protocol: How to Run the System&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="965" data-line-end="969"&gt;For researchers or clinicians reproducing this setup, operating the entire telemetry suite is remarkably straightforward once the background services are active. The operator ensures that the Palno ESP32 wristband is charged and powered on, and that the Uno Q bedside station is plugged into power on the local Wi-Fi network.&lt;/p&gt;
&lt;p class="" data-line-start="971" data-line-end="975"&gt;On the monitoring laptop, the operator launches National Instruments LabVIEW and opens Palno_Slemon_Telemetry.vi. On the Front Panel, the IP address is verified as 192.168.1.12 (or 127.0.0.1 if tethered via USB ADB port-forwarding for bench evaluation) and the port is confirmed as 5005. The operator clicks the white Run arrow on the LabVIEW toolbar.&lt;/p&gt;
&lt;p class="" data-line-start="977" data-line-end="982"&gt;Within one second, the Wristband Link LED illuminates solid green, indicating that the BLE GATT connection to the wristband is verified. The three vitals charts immediately begin scrolling, displaying live heart rate, blood oxygen saturation, and respiration curves updated ten times per second. The CSV Data Logging LED turns green, indicating that every incoming frame is being written to disk at C:\PY_work\zlgothirm\sleep_data_log.csv.&lt;/p&gt;
&lt;p class="" data-line-start="984" data-line-end="987"&gt;When the session concludes, the operator clicks the red Stop button on the Front Panel. LabVIEW cleanly flushes the file write buffer, closes the CSV file handle, and gracefully releases the TCP network socket without generating runtime warnings or leaving orphaned port bindings.&lt;/p&gt;
&lt;p class="" data-line-start="984" data-line-end="987"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pmo175e" data-line-start="992" data-line-end="992"&gt;&lt;b&gt;Results, Latency Benchmarks, and Verification&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="994" data-line-end="996"&gt;After weeks of development and the intense debugging marathon of revision five, the final verification tests demonstrated outstanding performance and clinical- grade reliability across the board.&lt;/p&gt;
&lt;p class="" data-line-start="998" data-line-end="1005"&gt;To measure transmission latency, I configured the ESP32 to toggle an onboard GPIO pin high the moment an optical sample was captured by the MAX30102, and configured LabVIEW to toggle a digital output pin on a connected DAQ device the instant the waveform point was drawn on screen. Observing both signals on a digital storage oscilloscope revealed an average end-to-end latency of eighteen milliseconds over local Wi-Fi. This sub-twenty-millisecond response time is imperceptible to the human eye and easily satisfies clinical telemetry standards.&lt;/p&gt;
&lt;p class="" data-line-start="1007" data-line-end="1011"&gt;Throughput and packet reliability were evaluated during continuous overnight stress tests lasting over eight hours. Over hundreds of thousands of transmitted JSON frames, the system achieved a packet loss rate of zero percent. The LabVIEW JSON parser experienced zero syntax errors, and the TCP connection remained rock-solid without a single socket reset or buffer overflow.&lt;/p&gt;
&lt;p class="" data-line-start="1013" data-line-end="1019"&gt;The automated CSV data logger generated pristine tabular files containing millions of data points. Each row accurately recorded timestamps, heart rate, SpO2, respiration rate, ambient temperature, restlessness disturbance index, sleep stage classifications, and three-axis acceleration vectors. Opening the generated CSV files in spreadsheet and statistical analysis software confirmed that there were no missing rows, no corrupted characters, and no formatting discontinuities.&lt;/p&gt;
&lt;p class="" data-line-start="1021" data-line-end="1026"&gt;The physical 10-shake alarm snooze was tested dozens of times under varying movement intensities. The dual-layer detection engine successfully distinguished between gentle wrist adjustments and intentional alarm-dismissal shakes, requiring exactly ten firm strokes above 0.40 G to silence the alarm. The transition was visually verified on the LabVIEW Front Panel, where the alarm status LED extinguished synchronously with the cessation of audio.&lt;/p&gt;
&lt;p class="" data-line-start="1021" data-line-end="1026"&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/Screen-Recording-2026_2D00_10_2D00_25-181923.mp4"&gt;community.element14.com/.../Screen-Recording-2026_2D00_10_2D00_25-181923.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p class="" data-line-start="1021" data-line-end="1026"&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pmqe5kf" data-line-start="1031" data-line-end="1031"&gt;&lt;b&gt;What This Taught Me About Engineering, Deadlines, and Grit&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="1033" data-line-end="1036"&gt;Looking back on this marathon day, the technical accomplishments are deeply satisfying, but the personal lessons are what will stay with me the longest. Working against an immovable challenge deadline forces you to strip away wishful thinking and confront the raw realities of your engineering choices.&lt;/p&gt;
&lt;p class="" data-line-start="1038" data-line-end="1045"&gt;I learned that assumptions are an engineer&amp;#39;s worst enemy. Assuming that a Docker container will always get the same IP address, assuming that LabVIEW will magically know where to save a file without an explicit path, or assuming that an optical sensor will never output wild spikes will inevitably lead to broken systems. Real engineering requires you to design for failure at every interface: building dynamic discovery scripts instead of hardcoding IPs, implementing physiological filters to substitute noisy sensor reads, and decoupling critical network streams into dedicated threads.&lt;/p&gt;
&lt;p class="" data-line-start="1047" data-line-end="1053"&gt;I also developed a profound respect for National Instruments LabVIEW. What began as an intimidating visual programming language turned out to be an incredibly capable, deterministic, and elegant platform for biomedical instrumentation. The ability to create an advanced, multi-channel clinical dashboard with live charts, custom clusters, and automated logging in a matter of days&amp;mdash;without wrestling with GUI rendering libraries or thread deadlocks&amp;mdash;is a testament to the power of visual dataflow engineering.&lt;/p&gt;
&lt;p class="" data-line-start="1055" data-line-end="1060"&gt;Most of all, this project taught me the importance of resilience. When you have spent twelve straight hours at your desk, your code is throwing cryptic error codes, and the deadline is hours away, it is easy to feel overwhelmed. But taking a deep breath, breaking down the problem systematically from first principles, inspecting raw network buffers, and refusing to give up will always lead you to the solution.&lt;/p&gt;
&lt;p class="" data-line-start="1055" data-line-end="1060"&gt;&lt;/p&gt;
&lt;h2 id="user-content-final-thoughts-and-next-steps-for-the-element14-challenge" class="" data-line-start="1065" data-line-end="1065"&gt;&lt;b&gt;Final Thoughts and Next Steps for the Element14 Challenge&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_25-180434.png" /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="" data-line-start="1067" data-line-end="1071"&gt;The completion of this wireless LabVIEW telemetry dashboard marks the final major milestone of the Palno &amp;amp; Slemon project for the Element14 Smart Home Healthcare Design Challenge. What started as an ambitious concept&amp;mdash;a contactless dual-core sleep tracking and circadian wake system&amp;mdash;is now a fully functioning, validated physical reality.&lt;/p&gt;
&lt;p class="" data-line-start="1073" data-line-end="1079"&gt;The system seamlessly combines the real-time sensor processing of the STM32 microcontroller, the algorithmic intelligence of the Qualcomm Linux processor, the wearable precision of the ESP32 node, and the clinical visualization power of National Instruments LabVIEW. It tracks sleep stages with biological fidelity, awakens users at the optimal moment in their circadian cycle, provides effortless gesture-based alarm dismissal, and gives clinicians the high- resolution data they need to evaluate sleep health.&lt;/p&gt;
&lt;p class="" data-line-start="1073" data-line-end="1079"&gt;I want to extend my heartfelt gratitude to the Element14 community, the challenge organizers, and everyone who has followed, liked, and commented on my project posts. Your encouragement kept me going through the toughest debugging sessions.&lt;/p&gt;
&lt;p class="" data-line-start="1088" data-line-end="1090"&gt;Please feel free to share your thoughts, ask questions about the LabVIEW implementation or embedded networking, and leave your feedback in the comments section below. I look forward to engaging with all of you!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5pm4c7h8" data-line-start="494" data-line-end="494"&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p class="" data-line-start="158" data-line-end="159"&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Palno &amp; Slemon #4 Final Firmware</title><link>https://community.element14.com/thread/57378?ContentTypeID=0</link><pubDate>Sun, 25 Oct 2026 04:13:29 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:d2736fe5-92e6-4294-98a1-961255ebad3f</guid><dc:creator>Qbit</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57378?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57378/palno-slemon-4-final-firmware/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I hope you are doing well.&lt;/p&gt;
&lt;p&gt;I was going to post this yesterday but I was not able to finish it by tomorrow. Also the errors weren&amp;#39;t solving that fast and unknown bugs appear. That&amp;#39;s why I have to wait till now but I have made some of progress.&lt;/p&gt;
&lt;p&gt;I have developed the enclosure and the variable device, if you can say that because it&amp;#39;s not that professional but a prototype. That, I will show you in the next post. Also the only thing left is now interfering with the lab view and posting the final project.&amp;nbsp;Thanks to Jo for reminding.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:150%;"&gt;Recap&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;I was working on project&amp;nbsp; that uses&amp;nbsp; data from multiple resources like breathing data from the radar module,&amp;nbsp; heart beat rate , blood oxygen level to detect&amp;nbsp; the stage of sleep you are in to help you wake up at the right time so you wouldn`t feel tired after you wake up, because wake you up at the right time.I have configured the sensors, the radar module, the Arduino Q, and the ESP32. I have also shown you how the algorithms to make the raw data usable and meaningful worked.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;These are the past posts:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57301/palno-slemon-1-introduction" data-e14adj="t"&gt;Palno &amp;amp; Slemon #1 Introduction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57315/palno-slemon-2-1-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.1 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57324/palno-slemon-2-2-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.2 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57366/palno-slemon-3-building-the-algorithm" data-e14adj="t"&gt;Palno &amp;amp; Slemon #3 Building the Algorithm&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;span&gt;All &lt;/span&gt;&lt;span&gt;firmware &lt;/span&gt;&lt;span&gt;sketches, &lt;/span&gt;&lt;span&gt;Python &lt;/span&gt;&lt;span&gt;processing &lt;/span&gt;&lt;span&gt;engines, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;interface &lt;/span&gt;&lt;span&gt;assets &lt;/span&gt;&lt;span&gt;discussed &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;this &lt;/span&gt;&lt;span&gt;build &lt;/span&gt;&lt;span&gt;log &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;packaged&amp;nbsp;&amp;nbsp;&lt;a href="https://drive.google.com/file/d/1fNGX6g-YmYw0V0fV5Hhz_DuQVAZRtP-W/view?usp=drive_link" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;here.&lt;/a&gt;&lt;/span&gt;&lt;span&gt;so &lt;/span&gt;&lt;span&gt;you &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;inspect, &lt;/span&gt;&lt;span&gt;flash, &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;adapt &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;complete &lt;/span&gt;&lt;span&gt;codebase.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;The Hardware&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/WhatsApp-Image-2026_2D00_10_2D00_23-at-21.16.46.jpeg" /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;Excluding the batteries&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Firstly I was going to build the Palno on PCB but it was not possible as the deadline is too close. If I designed it in 1 hour, then the shipping will not be that fast to get it done.&amp;nbsp;&lt;/span&gt;&lt;span style="font-size:inherit;"&gt;I will be using jumpers and, for the Palno, some small wires only, to connect.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;I also will be connecting it to some Bluetooth speakers for waking up the person and also as the apparatus to get the person to sleep effectively by playing some binaural beats.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="user-content-what-the-system-must-do-target-capabilities" class=""&gt;&lt;b&gt;&lt;span&gt;What &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;System &lt;/span&gt;&lt;span&gt;Must &lt;/span&gt;&lt;span&gt;Do: &lt;/span&gt;&lt;span&gt;Target &lt;/span&gt;&lt;span&gt;Capabilities&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p class=""&gt;&lt;span&gt;Before &lt;/span&gt;&lt;span&gt;diving &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;breadboards &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;code, &lt;/span&gt;&lt;span&gt;let&amp;rsquo;s &lt;/span&gt;&lt;span&gt;define &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;functional &lt;/span&gt;&lt;span&gt;blueprint. &lt;/span&gt;&lt;span&gt;To &lt;/span&gt;&lt;span&gt;solve &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;inertia &lt;/span&gt;&lt;span&gt;problem &lt;/span&gt;&lt;span&gt;reliably &lt;/span&gt;&lt;span&gt;without &lt;/span&gt;&lt;span&gt;clinical &lt;/span&gt;&lt;span&gt;polysomnography &lt;/span&gt;&lt;span&gt;(PSG) &lt;/span&gt;&lt;span&gt;scalp &lt;/span&gt;&lt;span&gt;electrodes, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;must &lt;/span&gt;&lt;span&gt;perform &lt;/span&gt;&lt;span&gt;these &lt;/span&gt;&lt;span&gt;specific &lt;/span&gt;&lt;span&gt;tasks:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Contactless Thoracic Respiration Tracking:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Detect &lt;/span&gt;&lt;span&gt;minute &lt;/span&gt;&lt;span&gt;chest &lt;/span&gt;&lt;span&gt;wall &lt;/span&gt;&lt;span&gt;deflections &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;0.1&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;to&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;1.5&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;mm&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;distances &lt;/span&gt;&lt;span&gt;up &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;2.5&amp;nbsp;meters&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;without &lt;/span&gt;&lt;span&gt;any &lt;/span&gt;&lt;span&gt;cables &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;body &lt;/span&gt;&lt;span&gt;patches, &lt;/span&gt;&lt;span&gt;extracting &lt;/span&gt;&lt;span&gt;respiration &lt;/span&gt;&lt;span&gt;rate &lt;/span&gt;&lt;span&gt;(BPM) &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;breath-to-breath &lt;/span&gt;&lt;span&gt;regularity &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;real &lt;/span&gt;&lt;span&gt;time.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Continuous Peripheral Biometrics via BLE:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Measure &lt;/span&gt;&lt;span&gt;optical &lt;/span&gt;&lt;span&gt;Photoplethysmography &lt;/span&gt;&lt;span&gt;(PPG) &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;Heart &lt;/span&gt;&lt;span&gt;Rate &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Blood &lt;/span&gt;&lt;span&gt;Oxygen &lt;/span&gt;&lt;span&gt;Saturation &lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;while &lt;/span&gt;&lt;span&gt;capturing &lt;/span&gt;&lt;span&gt;6-axis &lt;/span&gt;&lt;span&gt;wrist &lt;/span&gt;&lt;span&gt;movement &lt;/span&gt;&lt;span&gt;(actigraphy) &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;20&amp;nbsp;Hz20\text{ Hz}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;20&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;Hz&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;track &lt;/span&gt;&lt;span&gt;restlessness &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;postures.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Ambient Thermal Micro-Climate Monitoring:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Track &lt;/span&gt;&lt;span&gt;room &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;0.05&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;&amp;deg;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolution &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;detect &lt;/span&gt;&lt;span&gt;circadian &lt;/span&gt;&lt;span&gt;ambient &lt;/span&gt;&lt;span&gt;thermal &lt;/span&gt;&lt;span&gt;drops &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;room &lt;/span&gt;&lt;span&gt;condition &lt;/span&gt;&lt;span&gt;shifts &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;provoke &lt;/span&gt;&lt;span&gt;micro-arousals.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;30-Second Epoch Sleep Stage Classification:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Aggregate &lt;/span&gt;&lt;span&gt;multi-modal &lt;/span&gt;&lt;span&gt;physiological &lt;/span&gt;&lt;span&gt;features &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;standard &lt;/span&gt;&lt;span&gt;30-second &lt;/span&gt;&lt;span&gt;epochs &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;classify &lt;/span&gt;&lt;span&gt;them &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;&lt;strong&gt;Wake&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;strong&gt;N1 (Drowsiness)&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;strong&gt;N2 (Light Sleep)&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;strong&gt;N3 (Deep Slow-Wave Sleep)&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;&lt;strong&gt;REM (Dream Sleep)&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Acoustic Brainwave Entrainment:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Generate &lt;/span&gt;&lt;span&gt;binaural &lt;/span&gt;&lt;span&gt;auditory &lt;/span&gt;&lt;span&gt;beats &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;dynamically &lt;/span&gt;&lt;span&gt;adapt &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;user&amp;#39;s &lt;/span&gt;&lt;span&gt;detected &lt;/span&gt;&lt;span&gt;state delivering &lt;/span&gt;&lt;span&gt;Delta &lt;/span&gt;&lt;span&gt;beats 5hz to 6hz&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;ease &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;onset &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;Alpha/Beta &lt;/span&gt;&lt;span&gt;ascending &lt;/span&gt;&lt;span&gt;sweep &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;stimulate &lt;/span&gt;&lt;span&gt;morning &lt;/span&gt;&lt;span&gt;arousal.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Intelligent Light-Sleep Awakening:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Calculate &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;optimal &lt;/span&gt;&lt;span&gt;waking &lt;/span&gt;&lt;span&gt;moment &lt;/span&gt;&lt;span&gt;within &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;customizable &lt;/span&gt;&lt;span&gt;morning &lt;/span&gt;&lt;span&gt;window, &lt;/span&gt;&lt;span&gt;firing &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;alarm &lt;/span&gt;&lt;span&gt;exclusively &lt;/span&gt;&lt;span&gt;during &lt;/span&gt;&lt;span&gt;N1 &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;N2 &lt;/span&gt;&lt;span&gt;light &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;while &lt;/span&gt;&lt;span&gt;forbidding &lt;/span&gt;&lt;span&gt;wake-ups &lt;/span&gt;&lt;span&gt;during &lt;/span&gt;&lt;span&gt;N3 &lt;/span&gt;&lt;span&gt;deep &lt;/span&gt;&lt;span&gt;sleep.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Physical Shake-to-Dismiss Alarm Mechanism:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ensure &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;physically &lt;/span&gt;&lt;span&gt;alert &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;requiring &lt;/span&gt;&lt;span&gt;active &lt;/span&gt;&lt;span&gt;wrist &lt;/span&gt;&lt;span&gt;shaking &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;10&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;consecutive&amp;nbsp;movements&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;detected &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;wearable&amp;#39;s &lt;/span&gt;&lt;span&gt;accelerometer &lt;/span&gt;&lt;span&gt;before &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;acoustic &lt;/span&gt;&lt;span&gt;alarm &lt;/span&gt;&lt;span&gt;silences.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;strong&gt;Dual Real-Time Interfaces:&lt;/strong&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Render &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;local &lt;/span&gt;&lt;span&gt;Web &lt;/span&gt;&lt;span&gt;UI &lt;/span&gt;&lt;span&gt;dashboard &lt;/span&gt;&lt;span&gt;served &lt;/span&gt;&lt;span&gt;directly &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bedside &lt;/span&gt;&lt;span&gt;unit &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;live &lt;/span&gt;&lt;span&gt;viewing, &lt;/span&gt;&lt;span&gt;while &lt;/span&gt;&lt;span&gt;streaming &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;continuous &lt;/span&gt;&lt;span&gt;Wi-Fi &lt;/span&gt;&lt;span&gt;TCP &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;feed &lt;/span&gt;&lt;span&gt;formatted &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;NI &lt;/span&gt;&lt;span&gt;LabVIEW &lt;/span&gt;&lt;span&gt;clinical &lt;/span&gt;&lt;span&gt;charts &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;long-term &lt;/span&gt;&lt;span&gt;storage.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=""&gt;&lt;span&gt;Let&amp;rsquo;s &lt;/span&gt;&lt;span&gt;explore &lt;/span&gt;&lt;span&gt;how &lt;/span&gt;&lt;span&gt;each &lt;/span&gt;&lt;span&gt;capability &lt;/span&gt;&lt;span&gt;was &lt;/span&gt;&lt;span&gt;implemented, &lt;/span&gt;&lt;span&gt;wired, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;debugged &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bench.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5n21i8f0"&gt;&lt;b&gt;&lt;span&gt;Hardware &lt;/span&gt;&lt;span&gt;Architecture &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Prototype &lt;/span&gt;&lt;span&gt;Assembly&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;consists &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;primary &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;nodes: &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bedside &lt;/span&gt;&lt;span&gt;Slemon &lt;/span&gt;&lt;span&gt;station &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Palno &lt;/span&gt;&lt;span&gt;wrist &lt;/span&gt;&lt;span&gt;wearable.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;bedside &lt;/span&gt;&lt;span&gt;Slemon &lt;/span&gt;&lt;span&gt;station &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;built &lt;/span&gt;&lt;span&gt;around &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Arduino &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q. &lt;/span&gt;&lt;span&gt;It &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;directly &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;HLK-LD2410 &lt;/span&gt;&lt;span&gt;24 &lt;/span&gt;&lt;span&gt;GHz &lt;/span&gt;&lt;span&gt;millimeter-wave &lt;/span&gt;&lt;span&gt;FMCW &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;UART, &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;MAX30208 &lt;/span&gt;&lt;span&gt;digital &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;I2C, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;SPI. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q &lt;/span&gt;&lt;span&gt;contains &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;core &lt;/span&gt;&lt;span&gt;running &lt;/span&gt;&lt;span&gt;Zephyr &lt;/span&gt;&lt;span&gt;RTOS &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;handles &lt;/span&gt;&lt;span&gt;real-time &lt;/span&gt;&lt;span&gt;peripheral &lt;/span&gt;&lt;span&gt;capture, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;Qualcomm &lt;/span&gt;&lt;span&gt;Linux &lt;/span&gt;&lt;span&gt;core &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;runs &lt;/span&gt;&lt;span&gt;our &lt;/span&gt;&lt;span&gt;Python &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;processing &lt;/span&gt;&lt;span&gt;engines. &lt;/span&gt;&lt;span&gt;Internal &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;between &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;cores &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;managed &lt;/span&gt;&lt;span&gt;through &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Arduino &lt;/span&gt;&lt;span&gt;RouterBridge &lt;/span&gt;&lt;span&gt;framework &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;lightweight &lt;/span&gt;&lt;span&gt;binary &lt;/span&gt;&lt;span&gt;RPC &lt;/span&gt;&lt;span&gt;calls.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;Palno &lt;/span&gt;&lt;span&gt;wearable &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;built &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;ESP32 &lt;/span&gt;&lt;span&gt;WROOM &lt;/span&gt;&lt;span&gt;DA &lt;/span&gt;&lt;span&gt;board. &lt;/span&gt;&lt;span&gt;It &lt;/span&gt;&lt;span&gt;interfaces &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;MAX30102 &lt;/span&gt;&lt;span&gt;optical &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;measure &lt;/span&gt;&lt;span&gt;pulse &lt;/span&gt;&lt;span&gt;rate &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;blood &lt;/span&gt;&lt;span&gt;oxygen &lt;/span&gt;&lt;span&gt;levels, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;MPU6050 &lt;/span&gt;&lt;span&gt;six-axis &lt;/span&gt;&lt;span&gt;inertial &lt;/span&gt;&lt;span&gt;measurement &lt;/span&gt;&lt;span&gt;unit &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;capture &lt;/span&gt;&lt;span&gt;actigraphy &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;wrist &lt;/span&gt;&lt;span&gt;orientation. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;ESP32 &lt;/span&gt;&lt;span&gt;operates &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;low-power &lt;/span&gt;&lt;span&gt;Bluetooth &lt;/span&gt;&lt;span&gt;Low &lt;/span&gt;&lt;span&gt;Energy &lt;/span&gt;&lt;span&gt;peripheral, &lt;/span&gt;&lt;span&gt;packaging &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;readings &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;custom &lt;/span&gt;&lt;span&gt;GATT &lt;/span&gt;&lt;span&gt;characteristics &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;advertising &lt;/span&gt;&lt;span&gt;them &lt;/span&gt;&lt;span&gt;directly &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bedside &lt;/span&gt;&lt;span&gt;unit.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Excluding &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;batteries, &lt;/span&gt;&lt;span&gt;my &lt;/span&gt;&lt;span&gt;original &lt;/span&gt;&lt;span&gt;plan &lt;/span&gt;&lt;span&gt;was &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;manufacture &lt;/span&gt;&lt;span&gt;Palno &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;custom &lt;/span&gt;&lt;span&gt;printed &lt;/span&gt;&lt;span&gt;circuit &lt;/span&gt;&lt;span&gt;board. &lt;/span&gt;&lt;span&gt;But &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;challenge &lt;/span&gt;&lt;span&gt;deadline &lt;/span&gt;&lt;span&gt;fast &lt;/span&gt;&lt;span&gt;approaching, &lt;/span&gt;&lt;span&gt;turnaround &lt;/span&gt;&lt;span&gt;times &lt;/span&gt;&lt;span&gt;made &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;impossible. &lt;/span&gt;&lt;span&gt;Even &lt;/span&gt;&lt;span&gt;if &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;completed &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;schematic &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;routed &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;board &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;afternoon, &lt;/span&gt;&lt;span&gt;international &lt;/span&gt;&lt;span&gt;fabrication &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;courier &lt;/span&gt;&lt;span&gt;shipping &lt;/span&gt;&lt;span&gt;would &lt;/span&gt;&lt;span&gt;have &lt;/span&gt;&lt;span&gt;taken &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;ten &lt;/span&gt;&lt;span&gt;days.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Instead, &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;opted &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;hands-on &lt;/span&gt;&lt;span&gt;prototyping &lt;/span&gt;&lt;span&gt;approach &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;breadboards, &lt;/span&gt;&lt;span&gt;flexible &lt;/span&gt;&lt;span&gt;jumpers, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;small &lt;/span&gt;&lt;span&gt;hookup &lt;/span&gt;&lt;span&gt;wires. &lt;/span&gt;&lt;span&gt;While &lt;/span&gt;&lt;span&gt;less &lt;/span&gt;&lt;span&gt;compact &lt;/span&gt;&lt;span&gt;than &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;production &lt;/span&gt;&lt;span&gt;wearable, &lt;/span&gt;&lt;span&gt;this &lt;/span&gt;&lt;span&gt;setup &lt;/span&gt;&lt;span&gt;allowed &lt;/span&gt;&lt;span&gt;rapid &lt;/span&gt;&lt;span&gt;component &lt;/span&gt;&lt;span&gt;testing &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;zero &lt;/span&gt;&lt;span&gt;down-time &lt;/span&gt;&lt;span&gt;waiting &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;postal &lt;/span&gt;&lt;span&gt;deliveries.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;For &lt;/span&gt;&lt;span&gt;sound &lt;/span&gt;&lt;span&gt;delivery, &lt;/span&gt;&lt;span&gt;rather &lt;/span&gt;&lt;span&gt;than &lt;/span&gt;&lt;span&gt;burdening &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bedside &lt;/span&gt;&lt;span&gt;node &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;bulky &lt;/span&gt;&lt;span&gt;analog &lt;/span&gt;&lt;span&gt;amplifier &lt;/span&gt;&lt;span&gt;circuitry, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;pairs &lt;/span&gt;&lt;span&gt;via &lt;/span&gt;&lt;span&gt;Bluetooth &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;standard &lt;/span&gt;&lt;span&gt;line-out &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;external &lt;/span&gt;&lt;span&gt;stereo &lt;/span&gt;&lt;span&gt;speakers &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;play &lt;/span&gt;&lt;span&gt;synthesized &lt;/span&gt;&lt;span&gt;binaural &lt;/span&gt;&lt;span&gt;tracks.&lt;/span&gt;&lt;/p&gt;
&lt;h4 id="user-content-complete-wiring-connections" class=""&gt;&lt;b&gt;&lt;span&gt;Complete &lt;/span&gt;&lt;span&gt;Wiring &lt;/span&gt;&lt;span&gt;Connections&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;If &lt;/span&gt;&lt;span&gt;you &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;following &lt;/span&gt;&lt;span&gt;along &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;schematics &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;here &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;exact &lt;/span&gt;&lt;span&gt;pin &lt;/span&gt;&lt;span&gt;connections &lt;/span&gt;&lt;span&gt;used &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bench:&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Slemon &lt;/span&gt;&lt;span&gt;Bedside &lt;/span&gt;&lt;span&gt;Node &lt;/span&gt;&lt;span&gt;(Arduino &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q):&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;HLK-LD2410 &lt;/span&gt;&lt;span&gt;Radar &lt;/span&gt;&lt;span&gt;TX &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D0 &lt;/span&gt;&lt;span&gt;(USART1 &lt;/span&gt;&lt;span&gt;RX, &lt;/span&gt;&lt;span&gt;configured &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;256000 &lt;/span&gt;&lt;span&gt;baud)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;HLK-LD2410 &lt;/span&gt;&lt;span&gt;Radar &lt;/span&gt;&lt;span&gt;RX &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D1 &lt;/span&gt;&lt;span&gt;(USART1 &lt;/span&gt;&lt;span&gt;TX)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MAX30208 &lt;/span&gt;&lt;span&gt;Temperature &lt;/span&gt;&lt;span&gt;SCL &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D20 &lt;/span&gt;&lt;span&gt;(I2C1 &lt;/span&gt;&lt;span&gt;SCL &lt;/span&gt;&lt;span&gt;clock &lt;/span&gt;&lt;span&gt;line)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MAX30208 &lt;/span&gt;&lt;span&gt;Temperature &lt;/span&gt;&lt;span&gt;SDA &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D21 &lt;/span&gt;&lt;span&gt;(I2C1 &lt;/span&gt;&lt;span&gt;SDA &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;line, &lt;/span&gt;&lt;span&gt;address &lt;/span&gt;&lt;span&gt;0x50)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;BUSY &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D4&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;RESET &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D5&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;D/C &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D6&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;CS &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D7&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;SCK &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D13&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;inch &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;DIN &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D11&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Power &lt;/span&gt;&lt;span&gt;rails: &lt;/span&gt;&lt;span&gt;5V &lt;/span&gt;&lt;span&gt;supply &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;module, &lt;/span&gt;&lt;span&gt;3.3V &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;display, &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;shared &lt;/span&gt;&lt;span&gt;ground.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=""&gt;&lt;span&gt;Palno &lt;/span&gt;&lt;span&gt;Wearable &lt;/span&gt;&lt;span&gt;Node &lt;/span&gt;&lt;span&gt;(ESP32 &lt;/span&gt;&lt;span&gt;WROOM &lt;/span&gt;&lt;span&gt;DA):&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;MAX30102 &lt;/span&gt;&lt;span&gt;SCL &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;GPIO22 &lt;/span&gt;&lt;span&gt;(Hardware &lt;/span&gt;&lt;span&gt;I2C &lt;/span&gt;&lt;span&gt;SCL)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MAX30102 &lt;/span&gt;&lt;span&gt;SDA &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;GPIO21 &lt;/span&gt;&lt;span&gt;(Hardware &lt;/span&gt;&lt;span&gt;I2C &lt;/span&gt;&lt;span&gt;SDA)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MAX30102 &lt;/span&gt;&lt;span&gt;INT &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;GPIO19 &lt;/span&gt;&lt;span&gt;(Data-ready &lt;/span&gt;&lt;span&gt;interrupt)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MPU6050 &lt;/span&gt;&lt;span&gt;SCL &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;GPIO22 &lt;/span&gt;&lt;span&gt;(Shared &lt;/span&gt;&lt;span&gt;I2C &lt;/span&gt;&lt;span&gt;bus)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MPU6050 &lt;/span&gt;&lt;span&gt;SDA &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;GPIO21 &lt;/span&gt;&lt;span&gt;(Shared &lt;/span&gt;&lt;span&gt;I2C &lt;/span&gt;&lt;span&gt;bus)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MPU6050 &lt;/span&gt;&lt;span&gt;INT &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;GPIO18 &lt;/span&gt;&lt;span&gt;(Motion &lt;/span&gt;&lt;span&gt;wake &lt;/span&gt;&lt;span&gt;interrupt)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Power &lt;/span&gt;&lt;span&gt;rails: &lt;/span&gt;&lt;span&gt;Regulated &lt;/span&gt;&lt;span&gt;3.3V &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;ground &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;onboard &lt;/span&gt;&lt;span&gt;voltage &lt;/span&gt;&lt;span&gt;regulator.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="user-content-bench-notes-debugging-the-dual-core-arduino-uno-q" class=""&gt;&lt;b&gt;&lt;span&gt;Bench &lt;/span&gt;&lt;span&gt;Notes: &lt;/span&gt;&lt;span&gt;Debugging &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Dual-Core &lt;/span&gt;&lt;span&gt;Arduino &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p class=""&gt;&lt;span&gt;Working &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Arduino &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q &lt;/span&gt;&lt;span&gt;reveals &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;interesting &lt;/span&gt;&lt;span&gt;dual-core &lt;/span&gt;&lt;span&gt;architecture: &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;managing &lt;/span&gt;&lt;span&gt;real-time &lt;/span&gt;&lt;span&gt;peripheral &lt;/span&gt;&lt;span&gt;tasks &lt;/span&gt;&lt;span&gt;alongside &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;Qualcomm &lt;/span&gt;&lt;span&gt;Linux &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;handling &lt;/span&gt;&lt;span&gt;computation. &lt;/span&gt;&lt;span&gt;However, &lt;/span&gt;&lt;span&gt;navigating &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;interactions &lt;/span&gt;&lt;span&gt;between &lt;/span&gt;&lt;span&gt;these &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;environments &lt;/span&gt;&lt;span&gt;required &lt;/span&gt;&lt;span&gt;troubleshooting &lt;/span&gt;&lt;span&gt;several &lt;/span&gt;&lt;span&gt;undocumented &lt;/span&gt;&lt;span&gt;quirks.&lt;/span&gt;&lt;/p&gt;
&lt;h4 class=""&gt;&lt;b&gt;&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 id="user-content-pin-mapping-and-the-serial-versus-monitor-trap" class=""&gt;&lt;b&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;Mapping &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Serial &lt;/span&gt;&lt;span&gt;versus &lt;/span&gt;&lt;span&gt;Monitor &lt;/span&gt;&lt;span&gt;Trap&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;When &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;initially &lt;/span&gt;&lt;span&gt;powered &lt;/span&gt;&lt;span&gt;up &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;sketch &lt;/span&gt;&lt;span&gt;compiled &lt;/span&gt;&lt;span&gt;cleanly, &lt;/span&gt;&lt;span&gt;but &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;App &lt;/span&gt;&lt;span&gt;Lab &lt;/span&gt;&lt;span&gt;serial &lt;/span&gt;&lt;span&gt;monitor &lt;/span&gt;&lt;span&gt;remained &lt;/span&gt;&lt;span&gt;completely &lt;/span&gt;&lt;span&gt;blank.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;On &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q, &lt;/span&gt;&lt;span&gt;standard &lt;/span&gt;&lt;span&gt;&lt;em&gt;Serial.print&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commands &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;routed &lt;/span&gt;&lt;span&gt;directly &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;physical &lt;/span&gt;&lt;span&gt;header &lt;/span&gt;&lt;span&gt;pins &lt;/span&gt;&lt;span&gt;D0 &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;D1. &lt;/span&gt;&lt;span&gt;If &lt;/span&gt;&lt;span&gt;you &lt;/span&gt;&lt;span&gt;use &lt;/span&gt;&lt;span&gt;&lt;em&gt;Serial.println&lt;/em&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;your &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;goes &lt;/span&gt;&lt;span&gt;out &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;UART &lt;/span&gt;&lt;span&gt;pins &lt;/span&gt;&lt;span&gt;instead &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;debug &lt;/span&gt;&lt;span&gt;console! &lt;/span&gt;&lt;span&gt;To &lt;/span&gt;&lt;span&gt;route &lt;/span&gt;&lt;span&gt;telemetry &lt;/span&gt;&lt;span&gt;back &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;your &lt;/span&gt;&lt;span&gt;computer&amp;#39;s &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;terminal, &lt;/span&gt;&lt;span&gt;you &lt;/span&gt;&lt;span&gt;must &lt;/span&gt;&lt;span&gt;use &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;&lt;em&gt;Monitor&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;object. &lt;/span&gt;&lt;span&gt;Redefining &lt;/span&gt;&lt;span&gt;&lt;em&gt;Serial&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolves &lt;/span&gt;&lt;span&gt;this &lt;/span&gt;&lt;span&gt;cleanly &lt;/span&gt;&lt;span&gt;across &lt;/span&gt;&lt;span&gt;all &lt;/span&gt;&lt;span&gt;libraries:&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define Serial Monitor

void setup() {
    Monitor.begin(115200);
    Serial.println(&amp;quot;[SLEMON] Bootstrapping real-time sensor engine...&amp;quot;);
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 id="user-content-locating-the-radar-on-hardware-serial1" class=""&gt;&lt;b&gt;&lt;span&gt;Locating &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Radar &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;Hardware &lt;/span&gt;&lt;span&gt;Serial1&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;Because &lt;/span&gt;&lt;span&gt;pins &lt;/span&gt;&lt;span&gt;D0 &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;D1 &lt;/span&gt;&lt;span&gt;route &lt;/span&gt;&lt;span&gt;USART1 &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;core &lt;/span&gt;&lt;span&gt;running &lt;/span&gt;&lt;span&gt;Zephyr &lt;/span&gt;&lt;span&gt;RTOS, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;driver &lt;/span&gt;&lt;span&gt;must &lt;/span&gt;&lt;span&gt;connect &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;&lt;em&gt;Serial1&lt;/em&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;configured &lt;/span&gt;&lt;span&gt;strictly &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;256000 &lt;/span&gt;&lt;span&gt;baud:&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Correct initialization in sketch.ino (see ZIP archive)
radar_init(&amp;amp;Serial1, 256000);&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Assigning &lt;em&gt;Serial2&lt;/em&gt; or standard &lt;em&gt;Serial&lt;/em&gt; leaves the radar buffer empty because the physical bytes are arriving on USART1.&lt;/span&gt;&lt;/p&gt;
&lt;h4 id="user-content-the-d20-and-d21-i2c-orientation" class=""&gt;&lt;b&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;D20 &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;D21 &lt;/span&gt;&lt;span&gt;I2C &lt;/span&gt;&lt;span&gt;Orientation&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;Early &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;readings &lt;/span&gt;&lt;span&gt;consistently &lt;/span&gt;&lt;span&gt;returned &lt;/span&gt;&lt;span&gt;error &lt;/span&gt;&lt;span&gt;codes &lt;/span&gt;&lt;span&gt;(-999.0 &lt;/span&gt;&lt;span&gt;C). &lt;/span&gt;&lt;span&gt;On &lt;/span&gt;&lt;span&gt;typical &lt;/span&gt;&lt;span&gt;Arduino &lt;/span&gt;&lt;span&gt;pinouts, &lt;/span&gt;&lt;span&gt;SDA &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;SCL &lt;/span&gt;&lt;span&gt;positions &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;vary &lt;/span&gt;&lt;span&gt;between &lt;/span&gt;&lt;span&gt;revisions. &lt;/span&gt;&lt;span&gt;On &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D20 &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;SCL &lt;/span&gt;&lt;span&gt;(Clock)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Pin &lt;/span&gt;&lt;span&gt;D21 &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;SDA &lt;/span&gt;&lt;span&gt;(Data)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=""&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;had &lt;/span&gt;&lt;span&gt;reversed &lt;/span&gt;&lt;span&gt;them &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;breadboard. &lt;/span&gt;&lt;span&gt;Swapping &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;jumpers &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;running &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;automatic &lt;/span&gt;&lt;span&gt;bus &lt;/span&gt;&lt;span&gt;scanner &lt;/span&gt;&lt;span&gt;immediately &lt;/span&gt;&lt;span&gt;detected &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;MAX30208 &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;address &lt;/span&gt;&lt;span&gt;0x50.&lt;/span&gt;&lt;/p&gt;
&lt;h4 id="user-content-resolving-the-missing-dtostrf-function-in-zephyr-arm-gcc" class=""&gt;&lt;b&gt;&lt;span&gt;Resolving &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Missing &lt;/span&gt;&lt;span&gt;dtostrf &lt;/span&gt;&lt;span&gt;Function &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;Zephyr &lt;/span&gt;&lt;span&gt;ARM &lt;/span&gt;&lt;span&gt;GCC&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;During &lt;/span&gt;&lt;span&gt;compilation &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;E-Ink &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;routine, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;build &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;halted &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;error &lt;/span&gt;&lt;span&gt;indicating &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;&lt;em&gt;dtostrf&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;was &lt;/span&gt;&lt;span&gt;not &lt;/span&gt;&lt;span&gt;declared &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;scope.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;function &lt;/span&gt;&lt;span&gt;&lt;em&gt;dtostrf&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;legacy &lt;/span&gt;&lt;span&gt;8-bit &lt;/span&gt;&lt;span&gt;AVR &lt;/span&gt;&lt;span&gt;routine &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;does &lt;/span&gt;&lt;span&gt;not &lt;/span&gt;&lt;span&gt;exist &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;standard &lt;/span&gt;&lt;span&gt;32-bit &lt;/span&gt;&lt;span&gt;ARM &lt;/span&gt;&lt;span&gt;GCC &lt;/span&gt;&lt;span&gt;libraries &lt;/span&gt;&lt;span&gt;under &lt;/span&gt;&lt;span&gt;Zephyr. &lt;/span&gt;&lt;span&gt;Rather &lt;/span&gt;&lt;span&gt;than &lt;/span&gt;&lt;span&gt;importing &lt;/span&gt;&lt;span&gt;bulky &lt;/span&gt;&lt;span&gt;string &lt;/span&gt;&lt;span&gt;conversion &lt;/span&gt;&lt;span&gt;libraries, &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;updated &lt;/span&gt;&lt;span&gt;&lt;em&gt;eink_display.h&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;use &lt;/span&gt;&lt;span&gt;standard &lt;/span&gt;&lt;span&gt;C++ &lt;/span&gt;&lt;span&gt;streaming &lt;/span&gt;&lt;span&gt;via &lt;/span&gt;&lt;span&gt;&lt;em&gt;display.print(floatValue, decimals)&lt;/em&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5n2mdsc1"&gt;&lt;b&gt;&lt;span&gt;Contactless &lt;/span&gt;&lt;span&gt;Thoracic &lt;/span&gt;&lt;span&gt;Respiration &lt;/span&gt;&lt;span&gt;Detection: &lt;/span&gt;&lt;span&gt;Radar &lt;/span&gt;&lt;span&gt;Signal &lt;/span&gt;&lt;span&gt;Processing&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;To &lt;/span&gt;&lt;span&gt;measure &lt;/span&gt;&lt;span&gt;breathing &lt;/span&gt;&lt;span&gt;without &lt;/span&gt;&lt;span&gt;touching &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;subject, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;bedside &lt;/span&gt;&lt;span&gt;Slemon &lt;/span&gt;&lt;span&gt;unit &lt;/span&gt;&lt;span&gt;uses &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;HLK-LD2410 &lt;/span&gt;&lt;span&gt;24 &lt;/span&gt;&lt;span&gt;GHz &lt;/span&gt;&lt;span&gt;Frequency-Modulated &lt;/span&gt;&lt;span&gt;Continuous-Wave &lt;/span&gt;&lt;span&gt;radar. &lt;/span&gt;&lt;span&gt;As &lt;/span&gt;&lt;span&gt;validated &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;J. &lt;/span&gt;&lt;span&gt;Vargas &lt;/span&gt;&lt;span&gt;et &lt;/span&gt;&lt;span&gt;al. &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;their &lt;/span&gt;&lt;span&gt;paper &lt;/span&gt;&lt;span&gt;&lt;em&gt;&amp;quot;Contactless Respiration and Heart Rate Monitoring Using mmWave FMCW Radar&amp;quot;&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(IEEE &lt;/span&gt;&lt;span&gt;Transactions &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;Biomedical &lt;/span&gt;&lt;span&gt;Engineering, &lt;/span&gt;&lt;span&gt;2019), &lt;/span&gt;&lt;span&gt;micro-Doppler &lt;/span&gt;&lt;span&gt;phase &lt;/span&gt;&lt;span&gt;shifts &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;resolve &lt;/span&gt;&lt;span&gt;chest &lt;/span&gt;&lt;span&gt;expansions &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;subtle &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;0.1 &lt;/span&gt;&lt;span&gt;mm.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;divides &lt;/span&gt;&lt;span&gt;its &lt;/span&gt;&lt;span&gt;detection &lt;/span&gt;&lt;span&gt;field &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;9 &lt;/span&gt;&lt;span&gt;range &lt;/span&gt;&lt;span&gt;gates &lt;/span&gt;&lt;span&gt;(0.75 &lt;/span&gt;&lt;span&gt;m &lt;/span&gt;&lt;span&gt;each). &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;core &lt;/span&gt;&lt;span&gt;runs &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;uninterrupted, &lt;/span&gt;&lt;span&gt;non-blocking &lt;/span&gt;&lt;span&gt;binary &lt;/span&gt;&lt;span&gt;Finite &lt;/span&gt;&lt;span&gt;State &lt;/span&gt;&lt;span&gt;Machine &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;ingests &lt;/span&gt;&lt;span&gt;20 &lt;/span&gt;&lt;span&gt;Hz &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;frames &lt;/span&gt;&lt;span&gt;looking &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;4-byte &lt;/span&gt;&lt;span&gt;frame &lt;/span&gt;&lt;span&gt;preamble &lt;/span&gt;&lt;span&gt;(0xF4, &lt;/span&gt;&lt;span&gt;0xF3, &lt;/span&gt;&lt;span&gt;0xF2, &lt;/span&gt;&lt;span&gt;0xF1) &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;termination &lt;/span&gt;&lt;span&gt;flags &lt;/span&gt;&lt;span&gt;(0xF8, &lt;/span&gt;&lt;span&gt;0xF7, &lt;/span&gt;&lt;span&gt;0xF6, &lt;/span&gt;&lt;span&gt;0xF5).&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;When &lt;/span&gt;&lt;span&gt;presence &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;detected &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;gate &lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;stationary &lt;/span&gt;&lt;span&gt;energy &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Estat&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;moving &lt;/span&gt;&lt;span&gt;energy &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Emov&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;converted &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;composite &lt;/span&gt;&lt;span&gt;displacement &lt;/span&gt;&lt;span&gt;index. &lt;/span&gt;&lt;span&gt;Because &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;reflections &lt;/span&gt;&lt;span&gt;attenuate &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;distance &lt;/span&gt;&lt;span&gt;following &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;range &lt;/span&gt;&lt;span&gt;equation, &lt;/span&gt;&lt;span&gt;we &lt;/span&gt;&lt;span&gt;apply &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;distance &lt;/span&gt;&lt;span&gt;normalization &lt;/span&gt;&lt;span&gt;formula:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span class="block my-2 overflow-x-auto text-center"&gt;&lt;span&gt;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;em&gt;&lt;/em&gt;I =Eg.(R/R0)^2&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;where &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;RR&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;measured &lt;/span&gt;&lt;span&gt;distance &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;torso &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;cm&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;serves &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;our &lt;/span&gt;&lt;span&gt;baseline &lt;/span&gt;&lt;span&gt;reference &lt;/span&gt;&lt;span&gt;distance.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;To &lt;/span&gt;&lt;span&gt;separate &lt;/span&gt;&lt;span&gt;chest &lt;/span&gt;&lt;span&gt;movement &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;background &lt;/span&gt;&lt;span&gt;clutter &lt;/span&gt;&lt;span&gt;such &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;walls, &lt;/span&gt;&lt;span&gt;curtains, &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;airflow, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Python &lt;/span&gt;&lt;span&gt;engine &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Qualcomm &lt;/span&gt;&lt;span&gt;core &lt;/span&gt;&lt;span&gt;maintains &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;adaptive &lt;/span&gt;&lt;span&gt;10th-percentile &lt;/span&gt;&lt;span&gt;baseline &lt;/span&gt;&lt;span&gt;noise &lt;/span&gt;&lt;span&gt;buffer:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span class="block my-2 overflow-x-auto text-center"&gt;&lt;span&gt;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;Percentile&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="delimsizing size1"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;{&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;}&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&amp;minus;300&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=""&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="delimsizing size1"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;A &lt;/span&gt;&lt;span&gt;valid &lt;/span&gt;&lt;span&gt;breath &lt;/span&gt;&lt;span&gt;cycle &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;counted &lt;/span&gt;&lt;span&gt;when &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;detrended &lt;/span&gt;&lt;span&gt;amplitude &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(I&amp;minus;B)(I - B)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;&amp;minus;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;crosses &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;adaptive &lt;/span&gt;&lt;span&gt;physiological &lt;/span&gt;&lt;span&gt;threshold:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span class="block my-2 overflow-x-auto text-center"&gt;&lt;span&gt;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Threshold&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;max&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;5.0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.35&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;&amp;sdot;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;Percentile&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;90&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;&amp;minus;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span class="block my-2 overflow-x-auto text-center"&gt;&lt;span&gt;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="minner"&gt;&lt;span class="mclose delimcenter"&gt;&lt;pre class="ui-code" data-mode="python"&gt;# Respiration peak detector from slemon_app/python/breath_engine.py
def process_radar_frame(self, target_detected, target_dist_cm, static_energy):
    if not target_detected:
        return None
        
    normalized_intensity = static_energy * ((target_dist_cm / 100.0) ** 2)
    self.buffer.append(normalized_intensity)
    
    baseline = np.percentile(self.buffer, 10)
    detrended = normalized_intensity - baseline
    
    if detrended &amp;gt; self.dynamic_threshold and not self.in_breath:
        self.in_breath = True
        peak_time = time.time()
        interval = peak_time - self.last_peak_time
        if 1.5 &amp;lt;= interval &amp;lt;= 6.0:  # Valid human respiratory window: 10 to 40 BPM
            bpm = 60.0 / interval
            self.last_peak_time = peak_time
            return bpm
    elif detrended &amp;lt; (self.dynamic_threshold * 0.4):
        self.in_breath = False
    return None&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span class="block my-2 overflow-x-auto text-center"&gt;&lt;span&gt;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="minner"&gt;&lt;span class="mclose delimcenter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5n33n812"&gt;&lt;b&gt;&lt;span&gt;Sleep &lt;/span&gt;&lt;span&gt;Stage &lt;/span&gt;&lt;span&gt;Neurobiology &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;30-Second &lt;/span&gt;&lt;span&gt;Classification &lt;/span&gt;&lt;span&gt;Engine&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Understanding &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;staging &lt;/span&gt;&lt;span&gt;requires &lt;/span&gt;&lt;span&gt;looking &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;autonomic &lt;/span&gt;&lt;span&gt;nervous &lt;/span&gt;&lt;span&gt;system. &lt;/span&gt;&lt;span&gt;As &lt;/span&gt;&lt;span&gt;documented &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;&lt;em&gt;The AASM Manual for the Scoring of Sleep and Associated Events&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;R. &lt;/span&gt;&lt;span&gt;B. &lt;/span&gt;&lt;span&gt;Berry &lt;/span&gt;&lt;span&gt;et &lt;/span&gt;&lt;span&gt;al. &lt;/span&gt;&lt;span&gt;(American &lt;/span&gt;&lt;span&gt;Academy &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;Sleep &lt;/span&gt;&lt;span&gt;Medicine, &lt;/span&gt;&lt;span&gt;2012), &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;not &lt;/span&gt;&lt;span&gt;uniform; &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;progresses &lt;/span&gt;&lt;span&gt;through &lt;/span&gt;&lt;span&gt;repeating &lt;/span&gt;&lt;span&gt;90 &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;110 &lt;/span&gt;&lt;span&gt;minute &lt;/span&gt;&lt;span&gt;ultradian &lt;/span&gt;&lt;span&gt;cycles.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;medical &lt;/span&gt;&lt;span&gt;reason &lt;/span&gt;&lt;span&gt;people &lt;/span&gt;&lt;span&gt;feel &lt;/span&gt;&lt;span&gt;disoriented &lt;/span&gt;&lt;span&gt;after &lt;/span&gt;&lt;span&gt;waking &lt;/span&gt;&lt;span&gt;up a &lt;/span&gt;&lt;span&gt;phenomenon &lt;/span&gt;&lt;span&gt;known &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;Sleep &lt;/span&gt;&lt;span&gt;Inertia, &lt;/span&gt;&lt;span&gt;thoroughly &lt;/span&gt;&lt;span&gt;reviewed &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;P. &lt;/span&gt;&lt;span&gt;Tassi &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;A. &lt;/span&gt;&lt;span&gt;Muzet &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;&lt;em&gt;&amp;quot;Sleep Inertia&amp;quot;&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(Sleep &lt;/span&gt;&lt;span&gt;Medicine &lt;/span&gt;&lt;span&gt;Reviews, &lt;/span&gt;&lt;span&gt;2000)&amp;mdash;is &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;high &lt;/span&gt;&lt;span&gt;concentrations &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;adenosine &lt;/span&gt;&lt;span&gt;remain &lt;/span&gt;&lt;span&gt;bound &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;cortical &lt;/span&gt;&lt;span&gt;receptors &lt;/span&gt;&lt;span&gt;when &lt;/span&gt;&lt;span&gt;slow-wave, &lt;/span&gt;&lt;span&gt;synchronized &lt;/span&gt;&lt;span&gt;Delta &lt;/span&gt;&lt;span&gt;waves &lt;/span&gt;&lt;span&gt;(0.5 &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;4 &lt;/span&gt;&lt;span&gt;Hz) &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;interrupted &lt;/span&gt;&lt;span&gt;during &lt;/span&gt;&lt;span&gt;Stage &lt;/span&gt;&lt;span&gt;N3 &lt;/span&gt;&lt;span&gt;deep &lt;/span&gt;&lt;span&gt;sleep. &lt;/span&gt;&lt;span&gt;Waking &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;N3 &lt;/span&gt;&lt;span&gt;causes &lt;/span&gt;&lt;span&gt;cognitive &lt;/span&gt;&lt;span&gt;sluggishness &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;last &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;45 &lt;/span&gt;&lt;span&gt;minutes.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Conversely, &lt;/span&gt;&lt;span&gt;waking &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;Stage &lt;/span&gt;&lt;span&gt;N1 &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;N2 &lt;/span&gt;&lt;span&gt;light &lt;/span&gt;&lt;span&gt;sleep &lt;/span&gt;&lt;span&gt;finds &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;thalamocortical &lt;/span&gt;&lt;span&gt;networks &lt;/span&gt;&lt;span&gt;primed &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;alertness.&lt;/span&gt;&lt;/p&gt;
&lt;h4 id="user-content-differentiating-sleep-stages-without-eeg-scalp-electrodes" class=""&gt;&lt;b&gt;&lt;span&gt;Differentiating &lt;/span&gt;&lt;span&gt;Sleep &lt;/span&gt;&lt;span&gt;Stages &lt;/span&gt;&lt;span&gt;Without &lt;/span&gt;&lt;span&gt;EEG &lt;/span&gt;&lt;span&gt;Scalp &lt;/span&gt;&lt;span&gt;Electrodes&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;Without &lt;/span&gt;&lt;span&gt;home &lt;/span&gt;&lt;span&gt;EEG &lt;/span&gt;&lt;span&gt;equipment, &lt;/span&gt;&lt;span&gt;how &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;we &lt;/span&gt;&lt;span&gt;reliably &lt;/span&gt;&lt;span&gt;tell &lt;/span&gt;&lt;span&gt;these &lt;/span&gt;&lt;span&gt;stages &lt;/span&gt;&lt;span&gt;apart?&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;key &lt;/span&gt;&lt;span&gt;insight &lt;/span&gt;&lt;span&gt;lies &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;respiratory &lt;/span&gt;&lt;span&gt;variability. &lt;/span&gt;&lt;span&gt;In &lt;/span&gt;&lt;span&gt;N3 &lt;/span&gt;&lt;span&gt;deep &lt;/span&gt;&lt;span&gt;sleep, &lt;/span&gt;&lt;span&gt;respiration &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;governed &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;primitive &lt;/span&gt;&lt;span&gt;metabolic &lt;/span&gt;&lt;span&gt;pacemakers &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;brainstem, &lt;/span&gt;&lt;span&gt;producing &lt;/span&gt;&lt;span&gt;very &lt;/span&gt;&lt;span&gt;steady, &lt;/span&gt;&lt;span&gt;periodic &lt;/span&gt;&lt;span&gt;breathing. &lt;/span&gt;&lt;span&gt;During &lt;/span&gt;&lt;span&gt;REM &lt;/span&gt;&lt;span&gt;sleep, &lt;/span&gt;&lt;span&gt;skeletal &lt;/span&gt;&lt;span&gt;muscles &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;paralyzed, &lt;/span&gt;&lt;span&gt;but &lt;/span&gt;&lt;span&gt;emotional &lt;/span&gt;&lt;span&gt;bursts &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;limbic &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;make &lt;/span&gt;&lt;span&gt;breathing &lt;/span&gt;&lt;span&gt;irregular.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;Every &lt;/span&gt;&lt;span&gt;30 &lt;/span&gt;&lt;span&gt;seconds, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;classification &lt;/span&gt;&lt;span&gt;engine &lt;/span&gt;&lt;span&gt;calculates &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Coefficient &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;Variation &lt;/span&gt;&lt;span&gt;across &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;respiration &lt;/span&gt;&lt;span&gt;buffer:&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span style="font-size:150%;"&gt;C&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;o&lt;span style="font-size:150%;"&gt;V&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;R&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&amp;nbsp;&lt;span style="font-size:150%;"&gt;=&amp;nbsp;&amp;sigma;RR/ BB&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;where&amp;nbsp;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;strong&gt;&lt;span class="mord mathnormal"&gt;&amp;sigma;&lt;/span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;R&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;​&lt;/span&gt;&lt;/span&gt; is the standard deviation of breath-to-breath intervals and&amp;nbsp;&lt;strong&gt;BB&lt;/strong&gt;&amp;nbsp;is their mean.​&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;&lt;pre class="ui-code" data-mode="text"&gt;# Hierarchical classification tree from slemon_app/python/sleep_classifier.py
def classify_30s_epoch(features):
    # Rule 1: Sustained actigraphy or gross radar disturbance indicates Wake
    if features.mean_disturbance &amp;gt; 50 or features.mean_dyn_accel &amp;gt; 0.10:
        return &amp;quot;WAKE&amp;quot;

    # Rule 2: Absence of vital signs indicates an empty bed
    if features.breath_count &amp;lt; 2 and features.hr_valid_ratio &amp;lt; 0.3:
        return &amp;quot;WAKE&amp;quot;

    # Rule 3: Split between regular NREM sleep and irregular REM/N1 sleep
    if features.resp_cov &amp;gt; 0.12:
        rem_score = 0
        if features.twitch_count &amp;gt;= 2:          rem_score += 2
        if features.hr_cov &amp;gt; 0.04:              rem_score += 1
        if features.mean_disturbance &amp;lt; 10:      rem_score += 1
        if features.time_since_sleep_onset &amp;gt; 60: rem_score += 1
        
        return &amp;quot;REM&amp;quot; if rem_score &amp;gt;= 4 else &amp;quot;N1&amp;quot;
        
    else:
        depth_score = 0
        if features.resp_rate &amp;lt; 14.0:             depth_score += 1
        if features.resp_cov &amp;lt; 0.05:              depth_score += 1
        if features.mean_hr &amp;lt; features.hr_floor:  depth_score += 1
        if features.hr_cov &amp;gt; 0.06:                depth_score += 1
        if features.mean_disturbance &amp;lt; 5.0:       depth_score += 1
        if features.epochs_still &amp;gt; 10:            depth_score += 1
        
        return &amp;quot;N3&amp;quot; if depth_score &amp;gt;= 4 else &amp;quot;N2&amp;quot;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;To eliminate temporary signal noise, classifications pass through a 5-epoch (2.5-minute) rolling majority window that filters out physiologically impossible transitions, such as jumping directly from active Wake into deep N3 sleep.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="user-content-acoustic-brainwave-entrainment-and-the-waking-sequence" class=""&gt;&lt;b&gt;&lt;span&gt;Acoustic &lt;/span&gt;&lt;span&gt;Brainwave &lt;/span&gt;&lt;span&gt;Entrainment &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Waking &lt;/span&gt;&lt;span&gt;Sequence&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p class=""&gt;&lt;span&gt;To &lt;/span&gt;&lt;span&gt;help &lt;/span&gt;&lt;span&gt;users &lt;/span&gt;&lt;span&gt;fall &lt;/span&gt;&lt;span&gt;asleep &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;wake &lt;/span&gt;&lt;span&gt;up &lt;/span&gt;&lt;span&gt;naturally, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;incorporates &lt;/span&gt;&lt;span&gt;acoustic &lt;/span&gt;&lt;span&gt;brainwave &lt;/span&gt;&lt;span&gt;entrainment &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;binaural &lt;/span&gt;&lt;span&gt;beats, &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;demonstrated &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;J. &lt;/span&gt;&lt;span&gt;D. &lt;/span&gt;&lt;span&gt;Lane &lt;/span&gt;&lt;span&gt;et &lt;/span&gt;&lt;span&gt;al. &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;&lt;em&gt;&amp;quot;Binaural Auditory Beats Affect Vigilance Performance and Mood&amp;quot;&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(Physiology &lt;/span&gt;&lt;span&gt;&amp;amp; &lt;/span&gt;&lt;span&gt;Behavior, &lt;/span&gt;&lt;span&gt;1998).&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;When &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;slightly &lt;/span&gt;&lt;span&gt;different &lt;/span&gt;&lt;span&gt;pure &lt;/span&gt;&lt;span&gt;audio &lt;/span&gt;&lt;span&gt;tones &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;presented &lt;/span&gt;&lt;span&gt;separately &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;each &lt;/span&gt;&lt;span&gt;ear, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;brainstem &lt;/span&gt;&lt;span&gt;perceives &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;phantom &lt;/span&gt;&lt;span&gt;modulation &lt;/span&gt;&lt;span&gt;equal &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;frequency &lt;/span&gt;&lt;span&gt;difference:&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class=""&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-s"&gt;&lt;span class="block my-2 overflow-x-auto text-center"&gt;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span style="font-size:150%;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;Delta;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;= &lt;span style="font-size:150%;"&gt;|&lt;strong&gt;f&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-size:150%;"&gt;left&amp;nbsp;&lt;span style="font-size:150%;"&gt;-&amp;nbsp;&lt;strong&gt;f&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;right&amp;nbsp;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;|&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;For &lt;/span&gt;&lt;span&gt;instance, &lt;/span&gt;&lt;span&gt;playing &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;200 &lt;/span&gt;&lt;span&gt;Hz &lt;/span&gt;&lt;span&gt;sine &lt;/span&gt;&lt;span&gt;wave &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;left &lt;/span&gt;&lt;span&gt;ear &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;204 &lt;/span&gt;&lt;span&gt;Hz &lt;/span&gt;&lt;span&gt;sine &lt;/span&gt;&lt;span&gt;wave &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;right &lt;/span&gt;&lt;span&gt;ear &lt;/span&gt;&lt;span&gt;produces &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;apparent &lt;/span&gt;&lt;span&gt;4 &lt;/span&gt;&lt;span&gt;Hz &lt;/span&gt;&lt;span&gt;Theta &lt;/span&gt;&lt;span&gt;beat.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&lt;em&gt;Sleep Onset Induction:&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;When &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;detects &lt;/span&gt;&lt;span&gt;prolonged &lt;/span&gt;&lt;span&gt;N1 &lt;/span&gt;&lt;span&gt;restlessness, &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;plays &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;soft &lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&amp;Delta;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2.5&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;Hz&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Delta &lt;/span&gt;&lt;span&gt;beat &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;150 &lt;/span&gt;&lt;span&gt;Hz &lt;/span&gt;&lt;span&gt;carrier &lt;/span&gt;&lt;span&gt;tone &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;encourage &lt;/span&gt;&lt;span&gt;slow-wave &lt;/span&gt;&lt;span&gt;relaxation.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;em&gt;The Smart Waking Window:&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Within &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;user-selected &lt;/span&gt;&lt;span&gt;wake &lt;/span&gt;&lt;span&gt;window &lt;/span&gt;&lt;span&gt;(for &lt;/span&gt;&lt;span&gt;example, &lt;/span&gt;&lt;span&gt;6:30 &lt;/span&gt;&lt;span&gt;AM &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;7:00 &lt;/span&gt;&lt;span&gt;AM), &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;classifier &lt;/span&gt;&lt;span&gt;evaluates &lt;/span&gt;&lt;span&gt;each &lt;/span&gt;&lt;span&gt;30-second &lt;/span&gt;&lt;span&gt;epoch. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;moment &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;detects &lt;/span&gt;&lt;span&gt;N1 &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;N2 &lt;/span&gt;&lt;span&gt;Light &lt;/span&gt;&lt;span&gt;Sleep, &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;begins &lt;/span&gt;&lt;span&gt;waking &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;user.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;em&gt;Frequency Ramp:&lt;/em&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;waking &lt;/span&gt;&lt;span&gt;sequence &lt;/span&gt;&lt;span&gt;starts &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;Alpha &lt;/span&gt;&lt;span&gt;tone&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;&lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&amp;Delta;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;10&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;Hz&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;10 &lt;/span&gt;&lt;span&gt;percent &lt;/span&gt;&lt;span&gt;volume, &lt;/span&gt;&lt;span&gt;transitioning &lt;/span&gt;&lt;span&gt;smoothly &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;minutes &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;alert &lt;/span&gt;&lt;span&gt;Beta &lt;/span&gt;&lt;span&gt;frequenc&lt;/span&gt;&lt;span&gt;&lt;span class="katex"&gt;y &lt;span class="katex-html"&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&amp;Delta;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;16&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;Hz&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;60 &lt;/span&gt;&lt;span&gt;percent &lt;/span&gt;&lt;span&gt;volume.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="user-content-live-bench-demonstrations-serial-logs-web-dashboard-and-display-updates" class=""&gt;&lt;b&gt;&lt;span&gt;Live &lt;/span&gt;&lt;span&gt;Bench &lt;/span&gt;&lt;span&gt;Demonstrations: &lt;/span&gt;&lt;span&gt;Serial &lt;/span&gt;&lt;span&gt;Logs, &lt;/span&gt;&lt;span&gt;Web &lt;/span&gt;&lt;span&gt;Dashboard, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;Updates&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p class=""&gt;&lt;span&gt;To &lt;/span&gt;&lt;span&gt;verify &lt;/span&gt;&lt;span&gt;our &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;integration, &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;ran &lt;/span&gt;&lt;span&gt;functional &lt;/span&gt;&lt;span&gt;tests &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;my &lt;/span&gt;&lt;span&gt;bench &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;confirm &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;raw &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;streams &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;properly &lt;/span&gt;&lt;span&gt;captured &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;microcontrollers, &lt;/span&gt;&lt;span&gt;formatted, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;displayed &lt;/span&gt;&lt;span&gt;across &lt;/span&gt;&lt;span&gt;our &lt;/span&gt;&lt;span&gt;visual &lt;/span&gt;&lt;span&gt;interfaces.&lt;/span&gt;&lt;/p&gt;
&lt;h4 id="user-content-serial-monitor-telemetry-output" class=""&gt;&lt;b&gt;&lt;span&gt;Serial &lt;/span&gt;&lt;span&gt;Monitor &lt;/span&gt;&lt;span&gt;Telemetry &lt;/span&gt;&lt;span&gt;Output&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p class=""&gt;&lt;span&gt;When &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Arduino &lt;/span&gt;&lt;span&gt;Uno &lt;/span&gt;&lt;span&gt;Q &lt;/span&gt;&lt;span&gt;boots &lt;/span&gt;&lt;span&gt;up, &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;Zephyr &lt;/span&gt;&lt;span&gt;firmware &lt;/span&gt;&lt;span&gt;immediately &lt;/span&gt;&lt;span&gt;performs &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;internal &lt;/span&gt;&lt;span&gt;bus &lt;/span&gt;&lt;span&gt;scan &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;confirm &lt;/span&gt;&lt;span&gt;connected &lt;/span&gt;&lt;span&gt;peripherals, &lt;/span&gt;&lt;span&gt;synchronizes &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;radar &lt;/span&gt;&lt;span&gt;receiver &lt;/span&gt;&lt;span&gt;state &lt;/span&gt;&lt;span&gt;machine, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;begins &lt;/span&gt;&lt;span&gt;printing &lt;/span&gt;&lt;span&gt;periodic &lt;/span&gt;&lt;span&gt;debug &lt;/span&gt;&lt;span&gt;telemetry &lt;/span&gt;&lt;span&gt;packets:&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;[BOOT] Arduino Uno Q Multi-Core Slemon Engine Starting...
[I2C] Scanning bus D20/D21... Found 0x50 (MAX30208 Digital Temp)
[RADAR] Serial1 bound at 256000 baud. Waiting for frame sync...
[RADAR] Sync established! Gate=2 | Range=142cm | MoveEnergy=18 | StaticEnergy=64
[BREATH] Instantaneous Respiration: 15.6 BPM | Intensity=128.4 | Filtered=OK
[TEMP] MAX30208 Core Temperature: 24.25 C
[ROUTER_BRIDGE] Telemetry packet dispatched to Linux python core.
[PALNO] BLE Central Connected to ESP32 Wearable (RSSI: -64 dBm)
[PALNO] HR=72 BPM | SpO2=98% | Accel=[0.02g, 0.01g, 0.99g]&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;This confirmed that the D20/D21 pin orientation was correct, the MAX30208 was successfully reading temperature down to two decimal places, and the radar was actively tracking range and reflected gate energies without dropping frames.&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_24-165323.png" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;&lt;span&gt;3.5 &lt;/span&gt;&lt;span&gt;Inch &lt;/span&gt;&lt;span&gt;Display &lt;/span&gt;&lt;span&gt;Refresh&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&amp;nbsp;In the video demonstration below, you can see the screen cycling through its operational views:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/WhatsApp-Video-2026_2D00_10_2D00_24-at-21-_2800_online_2D00_video_2D00_cutter.com_2900_.mp4"&gt;community.element14.com/.../WhatsApp-Video-2026_2D00_10_2D00_24-at-21-_2800_online_2D00_video_2D00_cutter.com_2900_.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;&lt;b&gt;Live Web UI Dashboard and Movement Detection&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p class=""&gt;The Python service running on the Uno Q&amp;#39;s Qualcomm Linux core hosts a lightweight Socket.IO server on port 7000. Accessing &lt;code class="whitespace-pre-wrap"&gt;http://&amp;lt;uno-q-ip&amp;gt;:7000&lt;/code&gt; from any browser on the local network loads our real-time monitoring interface.&lt;/p&gt;
&lt;p class=""&gt;In this demonstration, you can see how the web dashboard captures and displays movement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When sitting still in front of the radar, the distance-normalized intensity signal forms steady, cyclical waves corresponding to chest movement, with the estimated breaths per minute remaining stable.&lt;/li&gt;
&lt;li&gt;When physical movement occurs&amp;mdash;such as shifting in a chair or moving hands in front of the unit&amp;mdash;the dashboard immediately registers the surge in moving energy across the radar gates.&lt;/li&gt;
&lt;li&gt;The web interface dynamically flags the movement event, showing how motion disturbance is separated from genuine micro-chest breathing deflections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_25-093830.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1k5ojvpio0"&gt;&lt;b&gt;Clinical Data Logging: Wi-Fi Integration with NI LabVIEW&lt;/b&gt;&lt;/h3&gt;
&lt;p class=""&gt;For in-depth analysis and long-term sleep logging, the bedside unit connects to National Instruments LabVIEW over Wi-Fi.&lt;/p&gt;
&lt;p class=""&gt;The Python service runs an internal TCP server on port 5005. Once LabVIEW connects across the local network, the server streams clean JSON telemetry packets every 2 seconds:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="json"&gt;{
  &amp;quot;timestamp&amp;quot;: 1729792014.2,
  &amp;quot;respiration_bpm&amp;quot;: 15.4,
  &amp;quot;radar_gate&amp;quot;: 2,
  &amp;quot;radar_distance_cm&amp;quot;: 138,
  &amp;quot;ambient_temp_c&amp;quot;: 24.15,
  &amp;quot;heart_rate_bpm&amp;quot;: 64,
  &amp;quot;spo2_percent&amp;quot;: 98,
  &amp;quot;wrist_motion_g&amp;quot;: 0.018,
  &amp;quot;classified_stage&amp;quot;: &amp;quot;N2&amp;quot;,
  &amp;quot;sleep_depth_score&amp;quot;: 3
}&lt;/pre&gt;&lt;/p&gt;
&lt;div class="relative whitespace-pre-wrap word-break-all my-2 rounded-xl bg-muted border"&gt;
&lt;div class="min-h-7 relative box-border flex flex-row items-center justify-between rounded-t border-b border-border px-2 py-0.5"&gt;
&lt;div class="font-sans text-sm text-muted-foreground"&gt;&lt;/div&gt;
&lt;div class="flex flex-row gap-2 justify-end"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="p-3"&gt;
&lt;div class="code-block w-full text-xs cursor-text  "&gt;
&lt;div class="flex flex-col w-full"&gt;
&lt;div class="code-line " data-index="0" data-line-number="1" data-line-start="1" data-line-end="1"&gt;
&lt;div class="line-content"&gt;On the LabVIEW side, standard TCP Open Connection and TCP Read blocks pass this stream into an Unflatten From JSON node, updating real-time waveform charts, historical trend displays, and saving test data into National Instruments .tdms files. I am finishing the visual layout of the LabVIEW front panel and will share complete screenshots and .vi files in the final challenge summary!&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p class=""&gt;&lt;span&gt;&lt;span class="katex-base"&gt;&lt;span class="mord"&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="user-content-final-thoughts-and-next-steps" class=""&gt;&lt;b&gt;Final Thoughts and Next Steps&lt;/b&gt;&lt;/h3&gt;
&lt;p class=""&gt;Building Palno and Slemon has been a rewarding challenge in embedded sensor fusion&amp;mdash;from parsing high-speed mmWave radar frames on an STM32 core to bridging live telemetry into Python and streaming it over Wi-Fi.&lt;/p&gt;
&lt;p class=""&gt;The next and final post will bring everything together for the challenge finale:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Complete screenshots of the multi-channel LabVIEW front panel showing overnight trend lines.&lt;/li&gt;
&lt;li&gt;Building the final enclosure and the wearable..&lt;/li&gt;
&lt;li&gt;Full GitHub repository release containing all schematics, code, and documentation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class=""&gt;Thank you for reading and following along with the build! I would love to hear your feedback, suggestions, and thoughts in the comments below.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitaRF - Part 8 - Assembling the PCB with Stencil, Paste and a Hot Plate</title><link>https://community.element14.com/thread/57376?ContentTypeID=0</link><pubDate>Fri, 23 Oct 2026 18:51:10 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:2e3019a4-f9bb-4604-b178-ba5cbdddd2a3</guid><dc:creator>arvindsa</dc:creator><slash:comments>8</slash:comments><comments>https://community.element14.com/thread/57376?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57376/vitarf---part-8---assembling-the-pcb-with-stencil-paste-and-a-hot-plate/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p style="text-align:left;"&gt;&lt;strong&gt;Recap:&lt;/strong&gt; I am building a wireless vitals sensor node (heart rate, SpO₂, temperature) that reports over BLE into Home Assistant as a smart way to keep watch over our loved ones, built up in three phases &amp;mdash; DK bring-up, a custom miniaturized nRF52832 PCB, then a Matter over Thread proof of concept.&lt;/p&gt;
&lt;p&gt;Past Posts&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57254/vitarf---part-1---the-plan" data-e14adj="t"&gt;VitaRF - Part 1 - The Plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57279/vitarf---part-2---interface-max30102-on-nrf52" data-e14adj="t"&gt;VitaRF - Part 2 - Interface MAX30102 on NRF52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57291/vitarf---part-3---interfacing-max30208-on-nrf52" data-e14adj="t"&gt;VitaRF - Part 3 - Interfacing MAX30208 on NRF52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57293/vitarf---part-4---sending-sensor-data-to-home-assistant-via-ble-on-nrf52" data-e14adj="t"&gt;VitaRF - Part 4 - Sending Sensor Data to Home Assistant via BLE on NRF52&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57317/vitarf---part-5---matter-over-thread-on-nrf54l15-with-home-assistant" data-e14adj="t"&gt;VitaRF - Part 5 - Matter over Thread on nRF54L15 with Home Assistant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57331/vitarf---part-6---nrf52-based-heart-rate-temperature-wearable-pcb-for-home-assistant" data-e14adj="t"&gt;VitaRF - Part 6 - An nRF52-Based Heart-Rate &amp;amp; Temperature Wearable PCB for Home Assistant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57337/vitarf---part-7---adding-a-philips-wiz-smart-bulb-to-home-assistant" data-e14adj="t"&gt;VitaRF - Part 7 - Adding a Philips WiZ Smart Bulb to Home Assistant&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x900/__key/communityserver-discussions-components-files/458/01_2D00_bare_2D00_boards_2D00_from_2D00_jlcpcb.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k5l1e1qb0"&gt;Paste, place, reflow&lt;/h2&gt;
&lt;p&gt;This is the whole process in one video: applying the paste through the stencil, placing the components, and the reflow on the MHP50.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/vitarf_2D00_post8_2D00_final.mp4"&gt;community.element14.com/.../vitarf_2D00_post8_2D00_final.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Music by &lt;a href="https://pixabay.com/users/nastelbom-48128234/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=music&amp;amp;utm_content=617071" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Dmitrii Spis&lt;/a&gt; from &lt;a href="https://pixabay.com/music//?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=music&amp;amp;utm_content=617071" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Pixabay&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x900/__key/communityserver-discussions-components-files/458/02_2D00_assembled_2D00_board_2D00_closeup_2D00_npm1300.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x900/__key/communityserver-discussions-components-files/458/03_2D00_assembled_2D00_board_2D00_with_2D00_buzzer.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;I will explain the drivers and the final integration code in the upcoming post.&lt;/p&gt;
&lt;h2 id="mcetoc_1k5l1hbuj1"&gt;Final Notes&lt;/h2&gt;
&lt;p&gt;Assembling multiple boards tests your patience, and it is a good way to practice staying calm and making precise movements. The PCB design came out flawlessly, with no mistakes identified yet. Stay tuned for the next post. The Video is made using EffectCraft and FilmCraft. It&amp;#39;s not adobe. But again, I have no need to spend on adobe when Open source works well. Thanks to Jorat for the reminder.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol</title><link>https://community.element14.com/thread/57372?ContentTypeID=0</link><pubDate>Fri, 23 Oct 2026 05:39:01 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ca53e6f4-0099-4932-a7d8-7069f6555a8e</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57372?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;1. Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The MAX30208EVSYS evaluation system combines the MAX30208 digital temperature sensor with a flexible sensor PCB, an interface board, and a MAX32630FTHR microcontroller platform. It provides a convenient environment for evaluating temperature measurements, configuring the sensor, and collecting experimental data.&lt;br /&gt;&lt;br /&gt;However, the usefulness of the evaluation system depends not only on the sensor itself, but also on the reliability of the communication path between the hardware and the PC application.&lt;br /&gt;&lt;br /&gt;The communication architecture provides an interesting case study in embedded-system design. It connects a PC-based graphical user interface (GUI) to a microcontroller, which communicates with the temperature sensor over an I&amp;sup2;C bus. In the software version examined for this analysis, the host-to-device interface uses text-based commands rather than requiring the user to construct binary protocol frames manually.&lt;br /&gt;&lt;br /&gt;This article examines the communication architecture, serial-interface configuration, command syntax, response parsing, and potential software issues identified during the evaluation process. Details of the text protocol are based on analysis of the particular application version examined and should not be assumed to apply to every firmware or GUI release.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;2. System Architecture&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The communication path can be represented as follows:&lt;br /&gt;&lt;br /&gt;PC application &amp;rarr; USB virtual serial port &amp;rarr; MAX32630FTHR firmware &amp;rarr; I&amp;sup2;C bus &amp;rarr; MAX30208 sensor&lt;br /&gt;&lt;br /&gt;The main elements are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PC/host layer: Runs the manufacturer&amp;#39;s GUI or a custom diagnostic application.&lt;/li&gt;
&lt;li&gt;USB serial interface: Provides the communication channel between the PC and the microcontroller board.&lt;/li&gt;
&lt;li&gt;MAX32630FTHR: Runs the firmware that handles host commands and communicates with the sensor.&lt;/li&gt;
&lt;li&gt;MAX30208 interface board: Provides the electrical connections between the microcontroller and the sensor flex PCB.&lt;/li&gt;
&lt;li&gt;MAX30208 sensor: Measures temperature and provides digital measurement data through I&amp;sup2;C.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The MAX32630FTHR is more than a passive USB-to-I&amp;sup2;C converter: its firmware implements the device-side communication and control functions required by the evaluation software.&lt;br /&gt;&lt;br /&gt;The MAX30208 itself uses a standard I&amp;sup2;C interface. Its main features include 16-bit temperature output, a 32-sample FIFO, programmable temperature alarms, and configurable I&amp;sup2;C addressing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;3. Serial Interface Configuration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the application version examined, the host software initializes a virtual serial connection through the .NET SerialPort interface.&lt;br /&gt;&lt;br /&gt;The configuration is:&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span&gt;Parameter&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span&gt;Observed setting&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Baud rate&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;115200 bit/s&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Data bits&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;8&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Parity&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;None&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Stop bits&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Handshaking&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;None&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;DTR&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Enabled&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;RTS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Enabled&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Read timeout&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;5000 ms&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Write timeout&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;5000 ms&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;These settings correspond to a conventional 115200-8-N-1 serial configuration.&lt;br /&gt;&lt;br /&gt;The analyzed application also appears to identify the evaluation board using Windows device information and USB identifiers. The values observed in the tested setup were:&lt;br /&gt;&lt;br /&gt;VID: 0B6A&lt;br /&gt;&lt;br /&gt;PID: 0042&lt;br /&gt;&lt;br /&gt;These identifiers should be treated as observations from the tested hardware and software configuration, not as guaranteed identifiers for every revision of the evaluation system. Windows device enumeration and the exact identification method may vary with the firmware, driver, or board configuration.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;4. Text-Based Command Interface&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the analyzed application, commands are transmitted from the host to the microcontroller as text strings terminated by a carriage return (\r). The firmware interprets the commands and performs the corresponding operations, including sensor discovery, temperature acquisition, register access, and logging configuration.&lt;br /&gt;&lt;br /&gt;The following table summarizes the commands identified during the software analysis. The syntax and semantics should be verified against the firmware version used for testing.&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span&gt;Command or example&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span&gt;Observed purpose&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;s\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Search for connected devices&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;t 0\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Request a temperature reading from device index 0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;t 0 F\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Request readings for a specified device range or group, according to the analyzed implementation&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;r 0 10\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Read a register from device index 0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;w 0 10 5A\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Write a value to a register&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;g 0 0\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Read a register array or group of registers&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;i 10\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Configure a logging or sampling interval&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;d 0\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Configure the device-selection mask used for logging&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code dir="ltr"&gt;&lt;span&gt;f\r&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Query microSD-card status&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The exact argument order, numeric bases, whitespace requirements, and response formats are implementation-specific. In particular, register addresses and values may be represented in hexadecimal even when device indices or other fields use decimal notation.&lt;br /&gt;&lt;br /&gt;A text-based interface is useful for debugging because commands can be inspected without a dedicated binary-protocol analyzer. Where the firmware supports direct terminal access, a serial terminal can be used to send commands and inspect responses. The serial settings and command syntax must match the firmware currently loaded on the board.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;5. Response Framing and Host-Side Parsing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The analyzed software receives responses from the microcontroller as text and processes the returned fields in the host application. The response-handling code uses delimiters and regular expressions to extract values from the received strings.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This regular expression matches text enclosed in square brackets. It can be used to extract fields from responses such as:&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;[0] [24.570] [0]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The example above illustrates a possible temperature-response structure:&lt;br /&gt;&lt;br /&gt;[0] &amp;mdash; device index;&lt;br /&gt;&lt;br /&gt;[24.570] &amp;mdash; temperature value in degrees Celsius;&lt;br /&gt;&lt;br /&gt;[0] &amp;mdash; status or result field.&lt;br /&gt;&lt;br /&gt;The precise meaning and number of fields must be confirmed against the actual response generated by the tested firmware. Whitespace, delimiters, and additional fields should not be inferred solely from a single example.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;5.1 Device Discovery&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The analyzed host application sends the s command to discover connected devices. The response is then parsed to obtain device-related information used to initialize software objects.&lt;br /&gt;&lt;br /&gt;The code examined appears to process fields representing a logical device index, an address or identifier, and a value labelled as a ROM code.&lt;br /&gt;&lt;br /&gt;Care is required when interpreting these fields. The MAX30208 has a configurable 7-bit I&amp;sup2;C address in the range 0x50 to 0x53 under its standard address configurations. A reported value such as decimal 90 (hexadecimal 0x5A) would not be a valid standard MAX30208 7-bit I&amp;sup2;C address. It should therefore not be labelled as the sensor&amp;#39;s physical I&amp;sup2;C address without further verification.&lt;br /&gt;&lt;br /&gt;Similarly, the MAX30208 supports a unique ROM ID, but the precise structure and representation of that ID in the GUI&amp;#39;s response must be confirmed from the implementation. A field described as a ROM code should not automatically be interpreted as a standard Dallas/Maxim 64-bit ROM identifier without evidence from the relevant firmware or source code.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;5.2 Temperature Acquisition&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The analyzed application requests temperature data using a command such as t 0\r.&lt;br /&gt;&lt;br /&gt;A returned value like 24.570 is an example of a temperature represented as text in degrees Celsius. If the firmware uses a period as the decimal separator, the host application must parse that string using a compatible numeric format.&lt;br /&gt;&lt;br /&gt;This is especially important on systems configured for locales that normally use a comma as the decimal separator, including the default Polish Windows regional format.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;6. Regional Number Formatting and the FormatException Issue&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;During evaluation, the PC application was observed to start when the sensor was disconnected but to crash after the sensor was connected. The reported exception was:&lt;br /&gt;&lt;br /&gt;System.FormatException: Input string was not in a correct format&lt;br /&gt;&lt;br /&gt;One possible cause is a mismatch between the numeric format transmitted by the firmware and the format expected by the host application.&lt;br /&gt;&lt;br /&gt;For example, the same decimal value can be represented as 24.570 or 24,570, depending on the locale. If the firmware sends a period-delimited decimal string but the application parses it using incompatible culture settings, conversion to a floating-point value may fail.&lt;br /&gt;&lt;br /&gt;In .NET, a robust implementation should explicitly define the expected number format when parsing protocol data. If the firmware protocol specifies a period as the decimal separator, the host application can use CultureInfo.InvariantCulture, together with appropriate input validation and exception handling.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;using System.Globalization;

string rawTemperature = &amp;quot;24.570&amp;quot;;

if (double.TryParse(
        rawTemperature,
        NumberStyles.Float,
        CultureInfo.InvariantCulture,
        out double temperature))
{
    // Use the parsed temperature value.
}
else
{
    // Report invalid or unexpected protocol data.
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This example demonstrates the recommended parsing approach; it does not establish that the same code change has been applied to the manufacturer&amp;#39;s GUI.&lt;br /&gt;&lt;br /&gt;Changing the Windows regional format to English (United States) may be a useful diagnostic workaround. If the application works with that setting and fails under Polish regional settings, the result would support the decimal-separator hypothesis. It would not, by itself, exclude other parsing or device-initialization problems.&lt;br /&gt;&lt;br /&gt;A permanent fix should make the protocol&amp;#39;s numeric representation explicit, validate received fields, and handle malformed or incomplete responses without terminating the application.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;7. Engineering Value of the Protocol&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A text-based command interface can make an embedded evaluation platform easier to inspect and debug. It allows engineers to examine individual operations, test register access, and build custom data-acquisition tools without first implementing a binary protocol decoder.&lt;br /&gt;&lt;br /&gt;For the VitalSense project, this architecture offers several practical opportunities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Custom Python diagnostics: Send supported commands, collect temperature readings, and save measurements to CSV.&lt;/li&gt;
&lt;li&gt;Custom Qt application: Implement a desktop interface for live data display, logging, configuration, and experimental analysis.&lt;/li&gt;
&lt;li&gt;Protocol validation: Check response framing, malformed data, timeouts, and error reporting.&lt;/li&gt;
&lt;li&gt;Sensor characterization: Record repeatability, response time, and the influence of sensor placement and thermal contact.&lt;/li&gt;
&lt;li&gt;Regional-format testing: Verify that the host application behaves consistently across Windows locale settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any custom implementation should preserve the command syntax and response format expected by the firmware and should not assume that all commands listed here are supported by every firmware revision.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;8. Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The MAX30208EVSYS evaluation system illustrates how a sensor with a standard I&amp;sup2;C interface can be integrated into a PC-based evaluation workflow through a microcontroller and a USB serial communication channel.&lt;br /&gt;&lt;br /&gt;Examining the host software and the text-based command interface can help engineers understand the data path, develop custom diagnostic tools, and identify potential integration problems. The reported FormatException also highlights an important general principle: communication protocols should define numeric formats explicitly, and host applications should parse incoming data independently of the operating system&amp;#39;s regional settings.&lt;br /&gt;&lt;br /&gt;For VitalSense, this provides a useful starting point for developing a custom acquisition and analysis application. The next step is to validate the observed protocol against actual device responses and the corresponding firmware version before relying on it for automated measurements or long-term data logging.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;References&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Analog Devices, MAX30208 Digital Temperature Sensor Datasheet.&lt;/li&gt;
&lt;li&gt;Analog Devices, MAX30208 Evaluation System User Guide.&lt;/li&gt;
&lt;li&gt;Observations from the specific MAX30208EVSYS hardware, firmware, and PC application version examined during this project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;MAX30208EVSYS Python Reader Script&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="hljs-string"&gt;Description: This script implements a direct communication protocol with the MAX30208EVSYS evaluation kit, bypassing the official Windows GUI. It establishes a serial connection through the USB-to-UART bridge (MAX32630FTHR) and communicates using text-based commands terminated with a carriage return (&amp;#39;\r&amp;#39;). Key Features: - Initializes the serial port according to firmware requirements (115200 baud, 8 data bits, no parity, 1 stop bit, DTR/RTS enabled). - Sends control commands like &amp;#39;s&amp;#39; (search devices) and &amp;#39;t0&amp;#39; (read temperature) - Uses regular expressions to parse bracket-notated data frames received from the microcontroller (e.g., [0] [24.570] [0])&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="hljs-string"&gt;&lt;pre class="ui-code" data-mode="text"&gt;import re
import time
import serial


class MAX30208Reader:

  def __init__(self, port_name, baud_rate=115200):
    self.port_name = port_name
    self.baud_rate = baud_rate
    self.serial_port = None

  def connect(self):
    &amp;quot;&amp;quot;&amp;quot;Initialization and opening of the serial port according to firmware parameters.&amp;quot;&amp;quot;&amp;quot;
    try:
      self.serial_port = serial.Serial(
          port=self.port_name,
          baudrate=self.baud_rate,
          bytesize=serial.EIGHTBITS,
          parity=serial.PARITY_NONE,
          stopbits=serial.STOPBITS_ONE,
          timeout=5,  # 5-second timeout for read and write operations[cite: 3]
      )

      self.serial_port.dtr = True
      self.serial_port.rts = True

      time.sleep(0.015)  # Equivalent to Thread.Sleep(15) after opening port in C#[cite: 3]
      self.serial_port.reset_input_buffer()
      print(f&amp;quot;Successfully connected to port {self.port_name}&amp;quot;)
      return True
    except Exception as e:
      print(f&amp;quot;Error while opening port {self.port_name}: {e}&amp;quot;)
      return False

  def disconnect(self):
    &amp;quot;&amp;quot;&amp;quot;Closing the serial connection[cite: 3].&amp;quot;&amp;quot;&amp;quot;
    if self.serial_port and self.serial_port.is_open:
      self.serial_port.close()
      print(&amp;quot;Disconnected from device.&amp;quot;)

  def _send_command(self, command):
    &amp;quot;&amp;quot;&amp;quot;Sending a text command terminated with a carriage return (\r)[cite: 3].&amp;quot;&amp;quot;&amp;quot;
    if self.serial_port and self.serial_port.is_open:
      full_command = command + &amp;quot;\r&amp;quot;
      self.serial_port.write(full_command.encode(&amp;quot;utf-8&amp;quot;))

  def _read_response(self):
    &amp;quot;&amp;quot;&amp;quot;Reading the response line and clearing it of control characters[cite: 3].&amp;quot;&amp;quot;&amp;quot;
    if self.serial_port and self.serial_port.is_open:
      line = self.serial_port.readline().decode(&amp;quot;utf-8&amp;quot;, errors=&amp;quot;ignore&amp;quot;)
      return line.replace(&amp;quot;\r&amp;quot;, &amp;quot;&amp;quot;).replace(&amp;quot;\n&amp;quot;, &amp;quot;&amp;quot;)
    return &amp;quot;&amp;quot;

  def find_devices(self):
    &amp;quot;&amp;quot;&amp;quot;Searching for devices on the I2C bus (&amp;#39;s&amp;#39; command) and clearing buffer lines[cite: 3].&amp;quot;&amp;quot;&amp;quot;
    self._send_command(&amp;quot;s&amp;quot;)
    header_response = self._read_response()
    print(f&amp;quot;Controller response: {header_response}&amp;quot;)

    # Read additional lines returned by the controller for each found device
    match = re.search(r&amp;quot;(\d+)&amp;quot;, header_response)
    if match:
      num_devices = int(match.group(1))
      for _ in range(num_devices):
        dev_line = self._read_response()
        print(f&amp;quot;  -&amp;gt; Device info line: {dev_line}&amp;quot;)

  def get_temperature(self, device_index=0):
    &amp;quot;&amp;quot;&amp;quot;Reading temperature for the indicated device index (&amp;#39;t&amp;#39; command)[cite: 3].&amp;quot;&amp;quot;&amp;quot;
    self._send_command(f&amp;quot;t{device_index}&amp;quot;)
    response = self._read_response()

    # Parsing the protocol response based on square brackets[cite: 3]
    # Example response format: [0] [24.570] [0]
    match_collection = re.findall(r&amp;quot;\[(.*?)\]&amp;quot;, response)

    if len(match_collection) == 3:
      dev_idx = int(match_collection[0], 16)
      temperature = float(match_collection[1])
      status = int(match_collection[2])
      return {&amp;quot;device_index&amp;quot;: dev_idx, &amp;quot;temperature_c&amp;quot;: temperature, &amp;quot;status&amp;quot;: status}

    return None


# --- Example script usage ---
if __name__ == &amp;quot;__main__&amp;quot;:
  PORT_COM = &amp;quot;COM21&amp;quot;

  sensor_reader = MAX30208Reader(PORT_COM)

  if sensor_reader.connect():
    # Scan for devices (correctly flushes descriptive lines from the buffer)
    sensor_reader.find_devices()

    # Short pause before reading temperature
    time.sleep(0.5)

    # Continuous temperature reading from device index 0 in a loop
    try:
      print(&amp;quot;\nStarting temperature reading (press Ctrl+C to abort)...&amp;quot;)
      while True:
        data = sensor_reader.get_temperature(0)
        if data:
          print(
              f&amp;quot;Device: {data[&amp;#39;device_index&amp;#39;]} | Temperature:&amp;quot;
              f&amp;quot; {data[&amp;#39;temperature_c&amp;#39;]} &amp;#176;C | Status: {data[&amp;#39;status&amp;#39;]}&amp;quot;
          )
        else:
          print(&amp;quot;Warning: Failed to read a valid data frame.&amp;quot;)
        time.sleep(1)
    except KeyboardInterrupt:
      print(&amp;quot;\nInterrupted by user.&amp;quot;)
    finally:
      sensor_reader.disconnect()&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="hljs-string"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="hljs-string"&gt;&lt;span class="HwtZe" lang="en"&gt;&lt;span class="jCAhz ChMk0b"&gt;&lt;span class="ryNqvb"&gt;The result of this script&amp;#39;s execution is as follows:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="hljs-string"&gt;&lt;span class="HwtZe" lang="en"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/script.jpg" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 4 : MAX30208EVSYS Evaluation System – Technical Overview &amp; Operation</title><link>https://community.element14.com/thread/57371?ContentTypeID=0</link><pubDate>Fri, 23 Oct 2026 04:59:46 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:595caa7c-6b24-48fc-a4e3-faff31e40b94</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57371?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;MAX30208EVSYS Evaluation Kit: Hardware, Sensor Specifications, and GUI Software&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The MAX30208EVSYS evaluation system from Analog Devices provides a hardware and software platform for evaluating the MAX30208 digital temperature sensor. The sensor is designed for applications such as wearable temperature monitors, healthcare patches, and human-body thermometers.&lt;/p&gt;
&lt;p&gt;The system consists of three main hardware elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MAX30208 sensor flex PCB: A flexible printed circuit board carrying the MAX30208 sensor in a 10-pin LGA package.&lt;/li&gt;
&lt;li&gt;MAX3020x interface board: Provides accessible test points, configuration jumpers, and connections between the sensor and the microcontroller board.&lt;/li&gt;
&lt;li&gt;MAX32630FTHR microcontroller board: Runs the firmware required to communicate with the PC GUI and supplies power to the interface board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/MAX30208EVSYS.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/MAX32630FTHR.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The system connects to a Windows PC through the micro-USB connector on the MAX32630FTHR board. The supplied firmware enables the evaluation software to configure the sensor, acquire temperature measurements, and access device registers.&lt;br /&gt;&lt;br /&gt;The flexible sensor PCB has a low thermal mass, which supports a fast thermal response and allows the sensor to be positioned away from the main interface electronics. However, the measured temperature still depends on thermal contact, mounting, environmental conditions, and the measurement procedure. The flex PCB does not, by itself, guarantee accurate skin-temperature or clinical body-temperature measurements.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;Technical Specifications of the MAX30208 Sensor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Temperature accuracy: &amp;plusmn;0.1&amp;deg;C from +30&amp;deg;C to +50&amp;deg;C; &amp;plusmn;0.15&amp;deg;C from 0&amp;deg;C to +70&amp;deg;C, according to the sensor datasheet.&lt;br /&gt;&lt;br /&gt;Operating temperature range: 0&amp;deg;C to +70&amp;deg;C. The datasheet also specifies that the device can withstand a wider temperature range of &amp;minus;40&amp;deg;C to +85&amp;deg;C without damage; this should not be interpreted as the specified measurement-accuracy range.&lt;br /&gt;&lt;br /&gt;Resolution: 16-bit, corresponding to 0.005&amp;deg;C per digital output step. Resolution is not the same as measurement accuracy.&lt;br /&gt;&lt;br /&gt;FIFO: A 32-sample buffer for temperature readings, allowing the host controller to retrieve stored samples.&lt;br /&gt;&lt;br /&gt;Communication interface: I&amp;sup2;C, supporting four address configurations using the GPIO pin states at the I&amp;sup2;C start condition.&lt;br /&gt;&lt;br /&gt;GPIO0: Can be configured as an interrupt output for selected status conditions, including programmable high- and low-temperature alarms.&lt;br /&gt;&lt;br /&gt;GPIO1: Can be configured as an external temperature-conversion trigger.&lt;br /&gt;&lt;br /&gt;The sensor&amp;#39;s &amp;plusmn;0.1&amp;deg;C specification describes component-level performance under the conditions defined by the manufacturer. It does not, on its own, demonstrate that a complete thermometer meets clinical accuracy requirements or complies with medical-device standards.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;MAX30208 EV Kit GUI Software&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Analog Devices provides a Windows application for evaluating the MAX30208 without requiring the user to develop custom firmware for the initial tests.&lt;br /&gt;&lt;br /&gt;According to the evaluation-system documentation, the GUI provides the following functions:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1. Temperature Monitoring&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The application displays temperature readings from the connected sensor and provides controls for relevant device settings. The documentation does not describe a built-in real-time temperature-trend graph or a dashboard of minimum, maximum, and average statistics.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/EV-Kit.jpg" /&gt;&lt;br /&gt;&lt;strong&gt;2. Data Logging&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The GUI supports exporting measurement samples to a comma-separated values (CSV) file. This allows recorded data to be analyzed using tools such as Microsoft Excel, MATLAB, or Python.&lt;br /&gt;&lt;br /&gt;The evaluation system also supports logging to a microSD card when configured for standalone operation with a compatible card and battery.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3. Register Map&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The Register Map tab allows users to read individual MAX30208 registers, read all registers, and modify register bit settings. This is useful for exploring sensor configuration, measurement control, status flags, and other device functions.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/EV-Kit-2.jpg" /&gt;&lt;br /&gt;&lt;strong&gt;4. Temperature Alarms and Interrupt Configuration&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The MAX30208 supports programmable high- and low-temperature thresholds. When the relevant status and interrupt settings are enabled, the GPIO0 pin can signal a selected alarm condition. These functions can be configured through the device registers; the exact controls available in the GUI should be confirmed against the installed software version.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;Relevance to the VitalSense Project&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For VitalSense, the MAX30208EVSYS provides a useful starting point for characterizing temperature measurements, recording sensor data, exploring register-level configuration, and developing a custom acquisition and analysis application.&lt;br /&gt;&lt;br /&gt;Further work should evaluate repeatability, response time, thermal contact, sensor placement, and agreement with a suitable reference thermometer. The results should be reported as experimental measurements rather than assumed clinical performance.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;Troubleshooting the MAX30208EVSYS GUI: A Possible Regional Decimal-Separator Issue&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;During evaluation of the MAX30208EVSYS kit, I encountered a software issue involving the interaction between the hardware and the PC application. The GUI launches successfully when the sensor is disconnected, but crashes shortly after the sensor is connected.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The exception reported is:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;code dir="ltr"&gt;&lt;span&gt;System.FormatException: Input string was not in a correct format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;One possible explanation is a regional number-formatting mismatch in the GUI software. In Windows configurations that use a comma as the decimal separator, such as the default Polish regional format, an application that parses a decimal value using incompatible formatting assumptions may fail. For example, the strings &lt;/span&gt;&lt;code dir="ltr"&gt;&lt;span&gt;24.57&lt;/span&gt;&lt;/code&gt;&lt;span&gt; and &lt;/span&gt;&lt;code dir="ltr"&gt;&lt;span&gt;24,57&lt;/span&gt;&lt;/code&gt;&lt;span&gt; can be interpreted differently depending on the parsing method and culture settings.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The fact that the application starts without the sensor but crashes when the sensor is connected suggests that the error may occur during device initialization or temperature-data processing. However, the exception alone does not establish the exact root cause.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Workaround to test&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol start="1" data-spread="false"&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Close the MAX30208 EV Kit application.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Open &lt;/span&gt;&lt;strong&gt;&lt;span&gt;Windows Settings &amp;rarr; Time &amp;amp; language &amp;rarr; Language &amp;amp; region&lt;/span&gt;&lt;/strong&gt;&lt;span&gt; (or the equivalent Regional Settings panel in your Windows version).&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Temporarily select &lt;/span&gt;&lt;strong&gt;&lt;span&gt;English (United States)&lt;/span&gt;&lt;/strong&gt;&lt;span&gt; as the regional format, or change the decimal-symbol setting to a period if Windows allows this independently.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Restart the application, connect the evaluation system, and check whether the crash still occurs.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Restore your preferred regional settings after testing if necessary.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the application works under the alternative regional format and fails again under the original settings, this would support the decimal-separator hypothesis.&lt;/p&gt;
&lt;p&gt;The issue would then appear to be related to the PC software&amp;#39;s handling of regional number formats rather than necessarily indicating a fault in the MAX30208 sensor itself. A permanent software fix would be to parse numeric values using an explicitly defined culture that matches the data format, with appropriate validation and error handling.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;What is 3M 8810 and how does it affect the temperature reading of the MAX30208 sensor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;3M 8810 is a 0.25 mm thick thermally conductive double-sided tape made from an acrylic polymer filled with ceramic particles. It is designed to mechanically bond components while creating a thermal path to dissipate heat between a heat source and a cooling element (such as a chassis or heatsink).&lt;br /&gt;Using this tape directly and significantly impacts how the MAX30208 sensor (a clinically accurate temperature sensor with &amp;plusmn;0.1&amp;deg;C accuracy) registers the temperature of the ambient environment or the target object.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;How does 3M 8810 tape affect the MAX30208 sensor readings&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1. Sensor Specificity: MAX30208 (Inverted Design)&lt;/strong&gt;&lt;br /&gt;Most digital temperature sensors measure heat through thermal pads and ground pins on the bottom of the package (via the PCB). The MAX30208 measures temperature primarily from the top of its package (top-side), making it ideal for measuring human body temperature in wearable devices. To achieve accurate measurements, the target object must contact the top of the sensor package. Placing 3M 8810 tape there introduces specific physical consequences.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2. Introduction of Thermal Resistance (Measurement Error)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Although 3M 8810 is a thermally conductive material, its thermal conductivity is 0.6 W/m-K. At a thickness of 0.25 mm, this generates a measurable thermal impedance of approximately 5.8 &amp;deg;C&amp;middot;cm&amp;sup2;/W.&lt;br /&gt;Effect: The tape acts as a very thin layer of insulation. If the target object changes temperature, the sensor hidden behind the tape will register a temperature slightly lower (or higher, if the environment is cooling down) than the object&amp;#39;s actual temperature. This creates a thermal offset (a steady-state error) that must be calibrated in the firmware.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3. Increased Response Time (Thermal Inertia)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The bare MAX30208 sensor responds to temperature changes incredibly fast (the response time of an unsoldered sensor is only about 0.5 s).&lt;br /&gt;Effect: Adding a layer of acrylic adhesive and ceramics (3M 8810) introduces a barrier with a specific thermal mass. This causes the sensor to require more time to stabilize its reading after a sudden change in the object&amp;#39;s temperature. Rapid, dynamic temperature spikes may be flattened out or completely missed.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;4. Positive Effect: Elimination of Air Pockets&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Air is a terrible conductor of heat (approx. 0.026 W/m-K). If you place the sensor directly against a rigid, rough surface, microscopic air gaps will distort the reading far more than the tape would.&lt;br /&gt;Effect: 3M 8810 tape is compliant and features good &amp;quot;wet-out&amp;quot; capabilities (the ability to flow into and fill microscopic surface irregularities). Replacing these micro-air gaps with thermally conductive tape stabilizes and improves the repeatability of readings compared to a dry, unstable mechanical contact.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;Summary of Impact Metrics&lt;/span&gt;&lt;/p&gt;
&lt;div data-sfc-cp="" data-sfc-root="c" data-ved="2ahUKEwim7e-3qtmXAxU2A9sEHWx9D6sQ-q4QegYIAAgYEAA" data-hveid="CAAIGBAA" data-complete="true" data-processed="true" data-sfc-inited="2"&gt;
&lt;table data-animation-nesting="" data-sae=""&gt;
&lt;tbody&gt;
&lt;tr data-visible="1" data-sfc-cp="" data-sfc-root="c" data-ved="2ahUKEwim7e-3qtmXAxU2A9sEHWx9D6sQw4oVegYIAAgYEAE" data-complete="true"&gt;
&lt;th colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Impact Parameter&lt;/th&gt;
&lt;th colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Change with 3M 8810&lt;/th&gt;
&lt;th colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Goal &amp;amp; Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;tr data-visible="1" data-sfc-cp="" data-sfc-root="c" data-ved="2ahUKEwim7e-3qtmXAxU2A9sEHWx9D6sQw4oVegYIAAgYEAI" data-complete="true"&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Absolute Accuracy&lt;/td&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Degraded (introduces a small error/offset)&lt;/td&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Requires software calibration of the temperature delta.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-visible="1" data-sfc-cp="" data-sfc-root="c" data-ved="2ahUKEwim7e-3qtmXAxU2A9sEHWx9D6sQw4oVegYIAAgYEAM" data-complete="true"&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Response Time&lt;/td&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Extended (greater response delay)&lt;/td&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Acceptable for slow processes (e.g., body temperature measurement).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-visible="1" data-sfc-cp="" data-sfc-root="c" data-ved="2ahUKEwim7e-3qtmXAxU2A9sEHWx9D6sQw4oVegYIAAgYEAQ" data-complete="true"&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Reading Stability&lt;/td&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Significantly improved (eliminates air and vibration impact)&lt;/td&gt;
&lt;td colspan="undefined" data-sfc-cp="" data-sfc-root="c" data-complete="true"&gt;Key advantage &amp;ndash; prevents sudden measurement noise.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;If you are designing a medical or wearable device based on the MAX30208 and require its factory &amp;plusmn;0.1&amp;deg;C accuracy, you must account for the temperature drop across the 3M 8810 tape or use a thinner material with higher conductivity (such as dedicated copper and gold-plated electrodes making direct contact with the package top).&lt;/p&gt;
&lt;div data-sfc-cp="" data-sfc-root="c" data-hveid="CAAIHBAA" data-complete="true" data-processed="true"&gt;Below is a chart illustrating how the use of 3M 8810 thermally conductive tape affects the temperature reading of the MAX30208 sensor during a sudden temperature spike of the target object (e.g., when applied to skin at a stable temperature of 37&amp;deg;C).&lt;/div&gt;
&lt;div data-sfc-cp="" data-sfc-root="c" data-complete="true" data-processed="true" data-sfc-inited="2"&gt;&lt;/div&gt;
&lt;div data-animation-nesting="" data-sfc-cp="" data-wiz-attrbind="aria-level=pVSdbd_50/fLk2Md" data-sfc-root="c" data-complete="true" data-processed="true" data-sae=""&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Tape.jpg" /&gt;&lt;/div&gt;
&lt;div data-animation-nesting="" data-sfc-cp="" data-wiz-attrbind="aria-level=pVSdbd_50/fLk2Md" data-sfc-root="c" data-complete="true" data-processed="true" data-sae=""&gt;&lt;/div&gt;
&lt;div data-animation-nesting="" data-sfc-cp="" data-wiz-attrbind="aria-level=pVSdbd_50/fLk2Md" data-sfc-root="c" data-complete="true" data-processed="true" data-sae=""&gt;Key Takeaways from the Chart:&lt;/div&gt;
&lt;ul data-sfc-cp="" data-sfc-root="c" data-hveid="CAAIHxAA" data-complete="true" data-processed="true"&gt;
&lt;li data-sfc-cp="" data-sfc-root="c" data-hveid="CAAIHxAB" data-complete="true" data-sae=""&gt;Thermal Inertia (Delay): Without the tape (ideal contact), the sensor reacts almost instantly. The 3M 8810 tape layer causes the measurement curve to rise more gradually&amp;mdash;the sensor needs a few more seconds to register the full change.&lt;/li&gt;
&lt;li data-sfc-cp="" data-sfc-root="c" data-hveid="CAAIHxAE" data-complete="true" data-sae=""&gt;Thermal Offset (Shift Error): Due to the thermal resistance of the tape, the measurement line with 3M 8810 stabilizes at a level slightly lower than the actual temperature of the object. This difference is a constant error that needs to be corrected (added) in the microcontroller code handling the sensor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reference: Analog Devices, MAX30208 Evaluation System documentation and MAX30208 &amp;plusmn;0.1&amp;deg;C Accurate, I&amp;sup2;C Digital Temperature Sensor datasheet.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing</title><link>https://community.element14.com/thread/57370?ContentTypeID=0</link><pubDate>Fri, 23 Oct 2026 04:16:24 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:d20b1fa1-cd68-4d5d-a28b-ab4c90ce24a7</guid><dc:creator>jelektro</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57370?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;span style="font-size:200%;"&gt;Top Alternatives to the MAXREFDES117# for Heart Rate &amp;amp; SpO2 Sensing&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;Designing wearable devices or health-monitoring prototypes often starts with photoplethysmography (PPG)&amp;mdash;the optical measurement of blood volume changes to detect heart rate (HR) and blood oxygen saturation (SpO2).&lt;br /&gt;&lt;br /&gt;For years, the Analog Devices / Maxim Integrated MAXREFDES117# Reference Design Board has been a go-to benchmark for engineers and makers. Measuring a tiny 12.7 &amp;times; 12.7 mm with pads designed for wearable integration (and even sewing into textiles with conductive thread), it packs the MAX30102 sensor, onboard power regulation, and I2C level shifting into an ultra-compact package.&lt;br /&gt;&lt;br /&gt;However, depending on whether you are building a commercial wearable, setting up a rapid prototype, or looking for medical-grade precision, several strong alternatives exist on the market.&lt;br /&gt;&lt;br /&gt;Here is a comprehensive breakdown of the top competing solutions and alternatives to the MAXREFDES117#.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;span style="font-size:150%;"&gt;1. Direct Drop-In Hardware Alternatives (MAX30102-Based)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If your firmware is already written for the MAX30102 chip and you simply need a different physical form factor or easier prototyping options, these modules keep the same underlying silicon.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;strong&gt;MikroElektronika Oximeter 5 Click&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Core Sensor: MAX30102&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Form Factor: mikroBUS Click board (42.9 &amp;times; 25.4 mm)&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Key Advantage: Breadboard-free hardware integration and ready-to-use software support.&lt;br /&gt;&lt;br /&gt;While the MAXREFDES117# focuses on wearable miniaturization, MIKROE&amp;rsquo;s Oximeter 5 Click targets rapid benchtop evaluation. It interfaces seamlessly via the standardized mikroBUSTm header, features onboard voltage translation for 3.3V and 5V microcontrollers, and integrates directly with MIKROE&amp;#39;s mikroSDK software ecosystem.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;br /&gt;&lt;strong&gt;Generic MAX30102 Breakout Boards (e.g., Waveshare, Generic PCBs)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Core Sensor: MAX30102&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Form Factor: Standard 2.54 mm (0.1&amp;quot;) header PCB&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Key Advantage: Cost-effective and breadboard-friendly.&lt;br /&gt;&lt;br /&gt;Generic breakout boards sacrifice the ultra-compact round design and textile-friendly pads of the MAXREFDES117# in favor of standard goldpin headers. They are significantly less expensive and ideal for early-stage proof-of-concept testing on breadboards or Arduino-based setups.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;span style="font-size:150%;"&gt;2. Upgraded Sensor Hubs &amp;amp; Enhanced Maxim/ADI Modules&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Moving beyond raw sensor outputs, these alternatives offer updated optical hardware or onboard processing to handle the heavy computational math for you.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;strong&gt;SparkFun Pulse Oximeter &amp;amp; Heart Rate Sensor (SEN-15219)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Core Sensor: MAX30101 + MAX32664 Biometric Sensor Hub&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Form Factor: Qwiic-compatible breakout board&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Key Advantage: Onboard digital signal processing (DSP) and motion artifact filtering.&lt;br /&gt;&lt;br /&gt;The biggest limitation of the MAXREFDES117# is that your main host MCU (e.g., STM32, ESP32, or AVR) must execute complex algorithms to extract clean HR and SpO2 values from noisy raw PPG data.&lt;br /&gt;&lt;br /&gt;SparkFun solves this by combining the upgraded MAX30101 sensor (which adds a green LED alongside red and IR for better wrist-tracking stability) with the MAX32664 Sensor Hub. This onboard co-processor runs proprietary firmware that filters out motion noise in real time and calculates heart rate, SpO2, and signal quality&amp;mdash;delivering ready-to-use digital values directly over I2C.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;br /&gt;&lt;strong&gt;SparkFun Particle Sensor Breakout (MAX30105)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Core Sensor: MAX30105&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Form Factor: Standard SparkFun breakout / Qwiic&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Key Advantage: Multi-purpose optical sensing (PPG + particle/smoke detection).&lt;br /&gt;&lt;br /&gt;Equipped with red, IR, and green LEDs, the MAX30105 offers register-level compatibility with PPG measurement routines while expanding versatility to include ambient particle detection (smoke/dust) and optical proximity sensing.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;3. Alternative Silicon Vendors (TI, AMS Osram, Silicon Labs)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are developing a custom PCB from scratch and want to evaluate IC alternatives outside the Analog Devices / Maxim ecosystem, consider these industry-leading silicon alternatives:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;table data-path-to-node="32"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Solution / Board&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Manufacturer&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Image&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Key Features &amp;amp; Target Application&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,1,0,0"&gt;&lt;b data-path-to-node="32,1,0,0" data-index-in-node="0"&gt;&lt;a href="https://www.ti.com/tool/AFE4404EVM" data-path-to-node="32,1,0,0" data-index-in-node="0" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;EVM-AFE4404&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,1,1,0"&gt;&lt;b data-path-to-node="32,1,1,0" data-index-in-node="0"&gt;Texas Instruments&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/HR3.jpg" /&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,1,3,0"&gt;&lt;b data-path-to-node="32,1,3,0" data-index-in-node="0"&gt;Medical-Grade Precision:&lt;/b&gt; Highly flexible Analog Front-End (AFE) providing superior noise rejection, dynamic ambient light cancellation, and ultra-precise LED driver control. Ideal for clinical-grade devices.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,2,0,0"&gt;&lt;b data-path-to-node="32,2,0,0" data-index-in-node="0"&gt;&lt;a href="https://www.google.com/search?q=https://ams-osram.com/products/sensors/biosensors/ams-as7050-medical-health-sensor" data-path-to-node="32,2,0,0" data-index-in-node="0" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;AS7050 / AS7038&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,2,1,0"&gt;&lt;b data-path-to-node="32,2,1,0" data-index-in-node="0"&gt;AMS Osram&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/AS7038.jpg" /&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,2,3,0"&gt;&lt;b data-path-to-node="32,2,3,0" data-index-in-node="0"&gt;Multi-Parametric Biosensing:&lt;/b&gt; Supports simultaneous PPG (heart rate &amp;amp; &lt;span class="math-inline" data-index-in-node="69"&gt;SpO2&lt;/span&gt;), ECG (electrocardiogram), and EDA (galvanic skin response/stress monitoring) on a single integrated solution.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,3,0,0"&gt;&lt;b data-path-to-node="32,3,0,0" data-index-in-node="0"&gt;&lt;a href="https://www.silabs.com/sensors" data-path-to-node="32,3,0,0" data-index-in-node="0" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Si117x / Si118x&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,3,1,0"&gt;&lt;b data-path-to-node="32,3,1,0" data-index-in-node="0"&gt;Silicon Labs&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Si117x_2D00_Si118x.jpg" /&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="32,3,3,0"&gt;&lt;b data-path-to-node="32,3,3,0" data-index-in-node="0"&gt;Ultra-Low Power Wearables:&lt;/b&gt; Engineered specifically for wrist-based wearables, featuring built-in low-power algorithms optimized for long battery life in smartwatches and fitness trackers.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;br /&gt;&lt;span style="font-size:200%;"&gt;Alternatives to the MAX30208EVSYS Evaluation System&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The MAX30208EVSYS is a professional evaluation system from Analog Devices (formerly Maxim Integrated) designed to test the MAX30208&amp;mdash;an ultra-high accuracy (+/- 0.1&amp;#39;C in the medical range of 30&amp;#39;C to 50&amp;#39;C) digital temperature sensor. The system includes a microcontroller motherboard (MAX32630FTHR) and a flex PCB extension housing the sensor, allowing developers to easily attach it to human skin or conduct thermal flow analysis in wearable designs.&lt;br /&gt;&lt;br /&gt;When evaluating alternatives to the MAX30208EVSYS, two distinct aspects should be considered: alternative evaluation boards/kits and alternative medical-grade (+/-0.1&amp;#39;C) temperature sensor ICs.&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;1. Alternative Development Kits &amp;amp; Evaluation Boards&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are looking for a complete kit or breakout board to prototype body temperature sensing:&lt;/p&gt;
&lt;p style="font-weight:normal;line-height:100%;margin-bottom:0cm;"&gt;&lt;br /&gt;&lt;strong&gt;MikroElektronika Thermo 22 Click / MIKROE Temp Sensors&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Design: mikroBUS&amp;nbsp; form-factor expansion boards featuring integrated high-precision temperature sensors.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Advantage over EVSYS: Instead of using a proprietary evaluation system with the MAX32630FTHR board, MIKROE Click boards plug directly into any standard host board (STM32 Nucleo, ESP32, Raspberry Pi) via the universal mikroBUS&amp;nbsp; socket. They come supported by turnkey mikroSDK software libraries.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Texas Instruments TMP117EVM (Evaluation Module)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Main Sensor: TI TMP117 (+/- 0.1&amp;#39;C accuracy from -20&amp;#39;C to +50&amp;#39;C).&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Overview: Texas Instruments&amp;#39; official evaluation board featuring a detachable sensor breakout section.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Advantage over EVSYS: The TI EVM provides a USB interface with a ready-to-use PC GUI and EEPROM emulation. The detachable breakout section is tiny and has low thermal mass, making it easy to integrate into wearable medical patch prototypes.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;SparkFun / Adafruit High-Precision Temp Breakouts (e.g., PCT2075 / TMP117)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Overview: Low-cost i2c breakout boards with Qwiic / STEMMA QT connectors.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Advantage over EVSYS: The MAX30208EVSYS is relatively costly and geared toward industrial/medical evaluations. Adafruit/SparkFun breakout boards cost a fraction of the price and offer plug-and-play compatibility with Arduino and CircuitPython environments.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:150%;"&gt;2. Alternative Silicon ICs (Medical-Grade Temperature Sensors)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are designing a custom PCB from scratch and need an alternative to the MAX30208 sensor chip itself:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;table data-path-to-node="17"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Sensor&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Manufacturer&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Accuracy&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Interface&lt;/strong&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;strong&gt;Key Features &amp;amp; Advantage over MAX30208&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,1,0,0"&gt;&lt;b data-path-to-node="17,1,0,0" data-index-in-node="0"&gt;TMP117&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,1,1,0"&gt;Texas Instruments&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,1,2,0"&gt;&lt;b data-path-to-node="17,1,2,0" data-index-in-node="0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;+/- 0.1&amp;#39;C&lt;/span&gt;&lt;/b&gt; (from &lt;span class="math-inline" data-index-in-node="28"&gt;-20&amp;#39;C&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="49"&gt;+50&amp;#39;C&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,1,3,0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;i2c&lt;/span&gt; / SMBus&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,1,4,0"&gt;&lt;b data-path-to-node="17,1,4,0" data-index-in-node="0"&gt;Medical Standards Compliance (ASTM E1112 / ISO 80601).&lt;/b&gt; Meets clinical standards out of the box without requiring post-assembly calibration. Offers +/-&lt;span class="math-inline" data-index-in-node="147"&gt;&amp;nbsp;0.1&amp;#39;C&amp;nbsp;&lt;/span&gt;accuracy over a wider temperature span than the MAX30208.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,2,0,0"&gt;&lt;b data-path-to-node="17,2,0,0" data-index-in-node="0"&gt;MAX30205&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,2,1,0"&gt;Analog Devices&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,2,2,0"&gt;&lt;b data-path-to-node="17,2,2,0" data-index-in-node="0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;+/- 0.1&amp;#39;C&lt;/span&gt;&lt;/b&gt; (&lt;span class="math-inline" data-index-in-node="23"&gt;+37&amp;#39;C to +&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="44"&gt;39&amp;#39;C&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,2,3,0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;i2c&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,2,4,0"&gt;The predecessor to the MAX30208 in a TDFN package. Widely used in traditional digital clinical thermometers and medical wristbands.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,3,0,0"&gt;&lt;b data-path-to-node="17,3,0,0" data-index-in-node="0"&gt;STS35-DIS&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,3,1,0"&gt;Sensirion&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,3,2,0"&gt;&lt;b data-path-to-node="17,3,2,0" data-index-in-node="0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;+/- 0.1 &amp;#39;C&lt;/span&gt;&lt;/b&gt; (&lt;span class="math-inline" data-index-in-node="23"&gt;+20&amp;#39;C&lt;/span&gt; to &lt;span class="math-inline" data-index-in-node="44"&gt;+60&amp;#39;C&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,3,3,0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;i2c&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,3,4,0"&gt;Swiss-engineered sensor featuring high measurement repeatability and ultra-low power consumption. Includes an internal heating element for self-diagnostics.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,4,0,0"&gt;&lt;b data-path-to-node="17,4,0,0" data-index-in-node="0"&gt;AS6221&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,4,1,0"&gt;AMS Osram&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,4,2,0"&gt;&lt;b data-path-to-node="17,4,2,0" data-index-in-node="0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;+/- 0.09&amp;#39;C&lt;/span&gt;&lt;/b&gt; (&lt;span class="math-inline" data-index-in-node="24"&gt;+20&amp;#39;C&amp;nbsp;&lt;/span&gt;to &lt;span class="math-inline" data-index-in-node="45"&gt;+42&amp;#39;C&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,4,3,0"&gt;&lt;span class="math-inline" data-index-in-node="0"&gt;i2c&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style="border:1px solid #c4c7c5;padding:8px 12px;"&gt;&lt;span data-path-to-node="17,4,4,0"&gt;Industry-leading low power consumption (&lt;span class="math-inline" data-index-in-node="40"&gt;$6\,\mu\text{A}$&lt;/span&gt; at 4 samples/s) combined with extreme precision, specifically designed for smartwatches and medical patches.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 2 : Sponsored Kit Overview</title><link>https://community.element14.com/thread/57369?ContentTypeID=0</link><pubDate>Fri, 23 Oct 2026 03:25:49 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:90025c9f-4057-42dd-93f4-53a9da020ac9</guid><dc:creator>jelektro</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57369?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The Sponsored Kit designed for the Smart Home &amp;amp; Healthcare Challenge on the element14 platform consists of key components from renowned manufacturers (Analog Devices and 3M), along with additional prototyping accessories and branded swag.&lt;br /&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko1.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko2.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The following overview describes the main components, their key characteristics, and their potential applications in the development of the VitalSense physiological-monitoring research platform.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1. Analog Devices MAX30208EVSYS# Evaluation System&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quantity in kit: 1&lt;br /&gt;&lt;br /&gt;Description and main specifications: An evaluation system for the MAX30208 digital temperature sensor. The sensor is specified for &amp;plusmn;0.1&amp;deg;C accuracy over the 30&amp;deg;C to 50&amp;deg;C temperature range. The evaluation system includes a MAX30208 sensor interface board, a MAX32630FTHR microcontroller board, and a flexible PCB carrying the sensor.&lt;br /&gt;&lt;br /&gt;Project application: The system will serve as the starting point for evaluating temperature acquisition, sensor response, and measurement repeatability. Its compact sensor assembly and low thermal mass make it relevant to wearable and body-temperature-monitoring research. The accuracy of the complete measurement setup will depend on sensor placement, thermal contact, environmental conditions, and the measurement procedure.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko4.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko5.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;2. Analog Devices MAXREFDES117# Reference Design&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quantity in kit: 1&lt;br /&gt;&lt;br /&gt;Description and main specifications: A low-power optical heart-rate and pulse-oximetry reference design based on the MAX30102 sensor, with integrated red and infrared LEDs and supporting electronics.&lt;br /&gt;&lt;br /&gt;Project application: The module will be used to investigate photoplethysmography (PPG), heart-rate estimation, and SpO₂ estimation. The reference design includes example source code and a basic algorithm for these measurements. It can be integrated with compatible development platforms, including Arduino-based systems, and adapted to other microcontrollers where suitable drivers and interfaces are implemented.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko6.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;3. 3M EM25TP-0050 EMI Absorber Material&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quantity in kit:&amp;nbsp;&lt;span&gt;1 piece (&lt;/span&gt;&lt;span class="math-inline" data-index-in-node="26"&gt;340mm x 340mm x 0.05mm&amp;nbsp;&lt;/span&gt;&lt;span&gt;sheet,&lt;/span&gt;&lt;span&gt; EM25TP series)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Description and main specifications: A thin, flexible electromagnetic interference (EMI) absorber material from the 3M EM25TP family. The EM25TP family is designed to absorb electromagnetic energy over specified frequency ranges and can also provide magnetic-field shielding in applicable frequency ranges.&lt;br /&gt;&lt;br /&gt;Project application: The material will be investigated as a potential aid in reducing selected electromagnetic interference in sensitive electronic prototypes. It may be useful when evaluating interference from wireless modules, switching circuits, and other electronic components. Its effectiveness will depend on the interference frequency, material placement, and overall system design.&lt;br /&gt;&lt;br /&gt;The absorber will be treated as an experimental EMI-mitigation measure rather than a universal solution for electrical noise or measurement errors.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko7.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;4. 3M 8810 Thermally Conductive Adhesive Transfer Tape&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quantity in kit: 1 roll, 3M 8810 series.&lt;br /&gt;&lt;br /&gt;Description and main specifications: A thermally conductive adhesive transfer tape intended to provide an adhesive interface between suitable components and heat-dissipating surfaces.&lt;br /&gt;&lt;br /&gt;Project application: The tape may be useful for selected thermal-management and mechanical-assembly experiments involving electronic components and enclosures. In the VitalSense project, its use near temperature sensors will be evaluated carefully because thermal coupling, heat flow, and contact conditions can influence the measured temperature.&lt;br /&gt;&lt;br /&gt;The tape will not be assumed to improve body-temperature measurement accuracy without experimental evidence.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/ko8.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;5. Multicomp MCBB830K Solderless Breadboard&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Quantity in kit: 1&lt;br /&gt;&lt;br /&gt;Description and main specifications: A solderless prototyping breadboard, providing 830 connection points.&lt;br /&gt;&lt;br /&gt;Project application: The breadboard will support rapid prototyping of low-voltage circuits, including sensor interfaces &lt;span&gt;(such as the MAX30208 or MAXREFDES117)&lt;/span&gt;, microcontroller connections, and signal-conditioning experiments. It allows components to be connected and rearranged without soldering.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Community Swag and Accessories (element14 Branded Swag)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Basketball Cup&lt;/li&gt;
&lt;li&gt;Sticker and Pin (with element14 branding) - Community swag for challenge participants, perfect for decorating project enclosure or workspace.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The sponsored kit provides a useful starting point for developing and evaluating a physiological-monitoring research platform. The Analog Devices components support temperature sensing and optical PPG experiments, while the 3M materials offer opportunities to investigate electromagnetic interference mitigation and thermal assembly. The solderless breadboard supports rapid hardware prototyping.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Within VitalSense, these resources will be used to investigate sensor integration, data acquisition, signal processing, thermal behavior, and measurement repeatability. The objective is to develop and experimentally evaluate a modular prototype for physiological monitoring, rather than to assume clinical performance from component specifications alone.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The results will help identify practical design considerations for future wearable, smart-home, and portable healthcare-monitoring prototypes.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>VitalSense – Part 1: System Concept and Architecture</title><link>https://community.element14.com/thread/57368?ContentTypeID=0</link><pubDate>Fri, 23 Oct 2026 02:13:42 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:f7d4ec63-9a28-4fad-ae59-8ee090f60324</guid><dc:creator>jelektro</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57368?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span class="" style="font-size:150%;" data-path-to-node="2,0"&gt;Table of Contents&lt;br /&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57368/vitalsense-part-1-system-concept-and-architecture" data-e14adj="t"&gt;Part 1: System Concept and Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57369/vitalsense-part-2-sponsored-kit-overview" data-e14adj="t"&gt;Part 2 : Sponsored Kit Overview&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57370/vitalsense-part-3-alternatives-for-heart-rate-spo2-and-temperature-sensing" data-e14adj="t"&gt;Part 3 : Alternatives for Heart Rate, SpO₂, and Temperature Sensing&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57371/vitalsense-part-4-max30208evsys-evaluation-system-technical-overview-operation" data-e14adj="t"&gt;Part 4 : MAX30208EVSYS Evaluation System &amp;ndash; Technical Overview &amp;amp; Operation&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57372/vitalsense-part-5-reverse-engineering-the-max30208evsys-communication-protocol" data-e14adj="t"&gt;Part 5 : Reverse-Engineering the MAX30208EVSYS Communication Protocol&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57381/vitalsense-part-6-communicating-with-the-max30208evsys-in-labview" data-e14adj="t"&gt;Part 6 : Communicating with the MAX30208EVSYS in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57382/vitalsense-part-7-building-a-cross-platform-qt6-desktop-application-for-the-max30208evsys-temperature-sensor" data-e14adj="t"&gt;Part 7 : Building a Cross-Platform Qt6 Desktop Application for the MAX30208EVSYS Temperature Sensor&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57383/vitalsense-part-8-stm32-pulse-oximeter-heart-rate-monitor-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 8 : STM32 Pulse Oximeter &amp;amp; Heart Rate Monitor (MAXREFDES117 + USB CDC)&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57389/vitalsense-part-9-maxrefdes117-json-data-acquisition-via-usb-cdc-in-labview" data-e14adj="t"&gt;Part 9 : MAXREFDES117 &amp;ndash; JSON Data Acquisition via USB-CDC in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57384/vitalsense-part-10-building-a-real-time-sensor-data-visualizer-for-maxrefdes117-usb-cdc" data-e14adj="t"&gt;Part 10 : Building a Real-Time Sensor Data Visualizer for MAXREFDES117 / USB CDC&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57385/vitalsense-part-11-research-workstation-system-architecture" data-e14adj="t"&gt;Part 11 : Research Workstation System Architecture&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57390/vitalsense-part-12-combined-pulse-oximeter-temperature-monitoring-system-in-labview" data-e14adj="t"&gt;Part 12 : Combined Pulse Oximeter &amp;amp; Temperature Monitoring System in LabVIEW&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57386/vitalsense-part-13-dual-port-biomedical-telemetry-dashboard---integrating-stm32-maxrefdes117-and-max30208evsys-in-c-and-qt" data-e14adj="t"&gt;Part 13 : Dual-Port Biomedical Telemetry Dashboard - Integrating STM32 (MAXREFDES117) and MAX30208EVSYS in C++ and Qt&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="" data-path-to-node="2,0"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Project Overview and Objectives&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As part of my project for the element14 Smart Home Healthcare Challenge, I am investigating how high-accuracy sensing, digital signal processing, and embedded computing can be combined to develop flexible systems for physiological monitoring.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;The project is built around two evaluation platforms from Analog Devices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MAX30208EVSYS &amp;mdash; a temperature-sensing evaluation system based on the MAX30208 digital temperature sensor, specified for &amp;plusmn;0.1&amp;deg;C accuracy over the 30&amp;deg;C to 50&amp;deg;C range.&lt;/li&gt;
&lt;li&gt;MAXREFDES117 &amp;mdash; an optical heart-rate and pulse-oximetry reference design based on the MAX30102 sensor, featuring red and infrared LEDs and example algorithms for heart-rate and SpO₂ estimation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My first objective is to develop a PC-based diagnostic research station that acquires temperature and photoplethysmography (PPG) data through two independent USB-connected interfaces. A dedicated application written in C++/Qt or National Instruments LabVIEW will support signal acquisition, digital filtering, real-time waveform visualization, data logging, and algorithm evaluation.&lt;br /&gt;&lt;br /&gt;The second stage explores three complementary embedded architectures: an nRF52840-based Bluetooth Low Energy telemedicine node, an ultra-low-power TI MSP430-based measurement device, and a Seeed Studio Wio Terminal providing a standalone graphical interface and Wi-Fi connectivity.&lt;br /&gt;&lt;br /&gt;By comparing these platforms, I aim to evaluate their measurement performance, signal-processing capabilities, energy consumption, connectivity, and suitability for different physiological-monitoring scenarios. The project will establish an experimental foundation for future portable healthcare prototypes, with measurement accuracy and system performance assessed through documented validation procedures.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Technical Architecture, Implementation Plan, and Validation Strategy&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;1. Main Architecture - Diagnostic Station (PC + C++/Qt / LabVIEW)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;1.1. element14 Kits and Modules&lt;/p&gt;
&lt;ul data-path-to-node="23"&gt;
&lt;li&gt;
&lt;p data-path-to-node="23,0,0"&gt;Temperature measurement kit: &lt;span&gt;MAX30208EVSYS# &lt;/span&gt;&lt;span&gt;evaluation &lt;/span&gt;&lt;span&gt;system, &lt;/span&gt;&lt;span&gt;connected &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;PC &lt;/span&gt;&lt;span&gt;via &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;its &lt;/span&gt;&lt;span&gt;supported &lt;/span&gt;&lt;span&gt;evaluation &lt;/span&gt;&lt;span&gt;interface &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;software &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;firmware &lt;/span&gt;&lt;span&gt;configuration.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="23,1,0"&gt;Heart rate and SpO2 measurement kit: &lt;span&gt;MAXREFDES117# &lt;/span&gt;&lt;span&gt;optical &lt;/span&gt;&lt;span&gt;reference &lt;/span&gt;&lt;span&gt;design, &lt;/span&gt;&lt;span&gt;interfaced &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;acquires &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;streams &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;PC &lt;/span&gt;&lt;span&gt;via &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;Virtual &lt;/span&gt;&lt;span&gt;COM &lt;/span&gt;&lt;span&gt;Port &lt;/span&gt;&lt;span&gt;(VCP) &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;USB-to-UART &lt;/span&gt;&lt;span&gt;bridge.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1.2 PC Connection Method and Software Layer&lt;/p&gt;
&lt;p data-path-to-node="26"&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;workstation &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;designed &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;receive &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;through &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;independent &lt;/span&gt;&lt;span&gt;USB-connected &lt;/span&gt;&lt;span&gt;interfaces:&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="27"&gt;
&lt;li&gt;
&lt;p data-path-to-node="27,0,0"&gt;&lt;span&gt;Channel 1 &amp;mdash; Temperature:&lt;/span&gt; &lt;span&gt;MAX30208EVSYS# &lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;evaluation &lt;/span&gt;&lt;span&gt;firmware/software &lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;measurements.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="27,0,0"&gt;&lt;span&gt;Channel 2 &amp;mdash; PPG and SpO₂:&lt;/span&gt; &lt;span&gt;MAXREFDES117# &lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;(VCP/UART) &lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;optical &lt;/span&gt;&lt;span&gt;samples &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;calculated &lt;/span&gt;&lt;span&gt;parameters, &lt;/span&gt;&lt;span&gt;where &lt;/span&gt;&lt;span&gt;supported &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;firmware.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alternative A: C++ / Qt Application (Cross-Platform)&lt;/p&gt;
&lt;p&gt;&lt;span&gt;A &lt;/span&gt;&lt;span&gt;multi-threaded &lt;/span&gt;&lt;span&gt;application &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;code&gt;&lt;span&gt;QThread&lt;/span&gt;&lt;/code&gt;&lt;span&gt;, &lt;/span&gt;&lt;code&gt;&lt;span&gt;QSerialPort&lt;/span&gt;&lt;/code&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;plotting &lt;/span&gt;&lt;span&gt;library &lt;/span&gt;&lt;span&gt;such &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;QCustomPlot &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;provide &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;cross-platform &lt;/span&gt;&lt;span&gt;software &lt;/span&gt;&lt;span&gt;architecture &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;Windows &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Linux, &lt;/span&gt;&lt;span&gt;including &lt;/span&gt;&lt;span&gt;Raspberry &lt;/span&gt;&lt;span&gt;Pi &lt;/span&gt;&lt;span&gt;OS, &lt;/span&gt;&lt;span&gt;subject &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;availability &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;compatible &lt;/span&gt;&lt;span&gt;drivers &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;libraries.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;proposed &lt;/span&gt;&lt;span&gt;application &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;include:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;Independent &lt;/span&gt;&lt;span&gt;data-acquisition &lt;/span&gt;&lt;span&gt;workers &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;channels.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Real-time &lt;/span&gt;&lt;span&gt;visualization &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;optical &lt;/span&gt;&lt;span&gt;waveforms.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Digital &lt;/span&gt;&lt;span&gt;filtering &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;signal-quality &lt;/span&gt;&lt;span&gt;assessment.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Heart-rate &lt;/span&gt;&lt;span&gt;estimation &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;SpO₂ &lt;/span&gt;&lt;span&gt;estimation, &lt;/span&gt;&lt;span&gt;where &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;required &lt;/span&gt;&lt;span&gt;algorithm &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;calibration &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;available.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Timestamped &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;logging &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;CSV &lt;/span&gt;&lt;span&gt;export.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Connection-status &lt;/span&gt;&lt;span&gt;indicators &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;measurement-error &lt;/span&gt;&lt;span&gt;reporting.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alternative B: National Instruments LabVIEW Application&lt;/p&gt;
&lt;p&gt;&lt;span&gt;LabVIEW &lt;/span&gt;&lt;span&gt;provides &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;established &lt;/span&gt;&lt;span&gt;graphical &lt;/span&gt;&lt;span&gt;programming &lt;/span&gt;&lt;span&gt;environment &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;measurement &lt;/span&gt;&lt;span&gt;engineering, &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;acquisition, &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;processing, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;real-time &lt;/span&gt;&lt;span&gt;visualization.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Communication layer &amp;mdash; NI-VISA&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Configure &lt;/span&gt;&lt;span&gt;independent &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;sessions &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;sources.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Use &lt;/span&gt;&lt;span&gt;VISA &lt;/span&gt;&lt;span&gt;functions &lt;/span&gt;&lt;span&gt;such &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;VISA Configure Serial Port&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;VISA Read&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;VISA Write&lt;/span&gt; &lt;span&gt;where &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;devices &lt;/span&gt;&lt;span&gt;expose &lt;/span&gt;&lt;span&gt;compatible &lt;/span&gt;&lt;span&gt;serial &lt;/span&gt;&lt;span&gt;interfaces.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Implement &lt;/span&gt;&lt;span&gt;appropriate &lt;/span&gt;&lt;span&gt;framing, &lt;/span&gt;&lt;span&gt;parsing, &lt;/span&gt;&lt;span&gt;timeout &lt;/span&gt;&lt;span&gt;handling, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;communication-error &lt;/span&gt;&lt;span&gt;detection.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;Software architecture &amp;mdash; Producer/Consumer design pattern&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Producer loops:&lt;/span&gt; &lt;span&gt;Independent &lt;/span&gt;&lt;span&gt;acquisition &lt;/span&gt;&lt;span&gt;loops &lt;/span&gt;&lt;span&gt;read &lt;/span&gt;&lt;span&gt;incoming &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;two &lt;/span&gt;&lt;span&gt;interfaces &lt;/span&gt;&lt;span&gt;without &lt;/span&gt;&lt;span&gt;blocking &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;interface.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Queues:&lt;/span&gt; &lt;span&gt;Buffered &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;transferred &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;processing &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;loops.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Consumer loops:&lt;/span&gt; &lt;span&gt;Validate, &lt;/span&gt;&lt;span&gt;timestamp, &lt;/span&gt;&lt;span&gt;process, &lt;/span&gt;&lt;span&gt;visualize, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;store &lt;/span&gt;&lt;span&gt;measurements.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;Signal processing and digital filters&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Apply &lt;/span&gt;&lt;span&gt;suitable &lt;/span&gt;&lt;span&gt;digital &lt;/span&gt;&lt;span&gt;filtering, &lt;/span&gt;&lt;span&gt;such &lt;/span&gt;&lt;span&gt;as &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;Butterworth &lt;/span&gt;&lt;span&gt;band-pass &lt;/span&gt;&lt;span&gt;filter, &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;reduce &lt;/span&gt;&lt;span&gt;selected &lt;/span&gt;&lt;span&gt;noise &lt;/span&gt;&lt;span&gt;components &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;signal.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Use &lt;/span&gt;&lt;span&gt;peak &lt;/span&gt;&lt;span&gt;detection &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;inter-beat &lt;/span&gt;&lt;span&gt;interval &lt;/span&gt;&lt;span&gt;analysis &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;estimate &lt;/span&gt;&lt;span&gt;heart &lt;/span&gt;&lt;span&gt;rate.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Assess &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;quality &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;identify &lt;/span&gt;&lt;span&gt;motion-related &lt;/span&gt;&lt;span&gt;artifacts.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Estimate &lt;/span&gt;&lt;span&gt;SpO₂ &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;suitable &lt;/span&gt;&lt;span&gt;algorithm &lt;/span&gt;&lt;span&gt;based &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;red &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;infrared &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;signals &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;appropriate &lt;/span&gt;&lt;span&gt;calibration &lt;/span&gt;&lt;span&gt;model.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;User interface &amp;mdash; Front Panel&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Waveform &lt;/span&gt;&lt;span&gt;Chart &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Waveform &lt;/span&gt;&lt;span&gt;Graph &lt;/span&gt;&lt;span&gt;elements &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;live &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;visualization.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Numeric &lt;/span&gt;&lt;span&gt;indicators, &lt;/span&gt;&lt;span&gt;gauges, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;status &lt;/span&gt;&lt;span&gt;indicators &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;measurement &lt;/span&gt;&lt;span&gt;results.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Configurable &lt;/span&gt;&lt;span&gt;sampling &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;settings.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Measurement-session &lt;/span&gt;&lt;span&gt;management &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;diagnostics.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Data &lt;/span&gt;&lt;span&gt;export &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;TDMS &lt;/span&gt;&lt;span&gt;(Technical &lt;/span&gt;&lt;span&gt;Data &lt;/span&gt;&lt;span&gt;Management &lt;/span&gt;&lt;span&gt;Streaming) &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;CSV &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;subsequent &lt;/span&gt;&lt;span&gt;research &lt;/span&gt;&lt;span&gt;analysis.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;1.3. Comparison of Similar Solutions in Portable Medical Diagnostics&lt;/p&gt;
&lt;table data-path-to-node="35"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td&gt;Feature / Parameter&lt;/td&gt;
&lt;td&gt;VitalSense prototype (MAX30208 + STM32 + LabVIEW/Qt)&lt;/td&gt;
&lt;td&gt;Standard Fingertip Pulse Oximeter&lt;/td&gt;
&lt;td&gt;Commercial Smartbands (e.g., Apple Watch, Fitbit)&lt;/td&gt;
&lt;td&gt;Industrial Patient Monitors (e.g., Philips)&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Temp. Accuracy&lt;/td&gt;
&lt;td&gt;Outstanding (+/-0.1&amp;#39;C - medical grade)&lt;/td&gt;
&lt;td&gt;No temperature measurement&lt;/td&gt;
&lt;td&gt;Low/Estimated (skin temperature, uncalibrated)&lt;/td&gt;
&lt;td&gt;High (+/-0.1&amp;#39;C, continuous probes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Access&lt;/td&gt;
&lt;td&gt;Full access to raw PPG data and registers (LabVIEW/Qt)&lt;/td&gt;
&lt;td&gt;No data access&lt;/td&gt;
&lt;td&gt;Restricted (closed cloud APIs)&lt;/td&gt;
&lt;td&gt;Integrated with hospital HL7/DICOM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research Environment&lt;/td&gt;
&lt;td&gt;High flexibility (LabVIEW for rapid prototyping and DSP analysis)&lt;/td&gt;
&lt;td&gt;No modification options&lt;/td&gt;
&lt;td&gt;Closed ecosystem&lt;/td&gt;
&lt;td&gt;Dedicated clinical software&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-path-to-node="37"&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;2. Portable Autonomous Device Concepts (Architecture Triad)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;second &lt;/span&gt;&lt;span&gt;part &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;VitalSense &lt;/span&gt;&lt;span&gt;explores &lt;/span&gt;&lt;span&gt;three &lt;/span&gt;&lt;span&gt;complementary &lt;/span&gt;&lt;span&gt;embedded &lt;/span&gt;&lt;span&gt;architectures. &lt;/span&gt;&lt;span&gt;Each &lt;/span&gt;&lt;span&gt;concept &lt;/span&gt;&lt;span&gt;prioritizes &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;different &lt;/span&gt;&lt;span&gt;combination &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;energy &lt;/span&gt;&lt;span&gt;efficiency, &lt;/span&gt;&lt;span&gt;connectivity, &lt;/span&gt;&lt;span&gt;processing &lt;/span&gt;&lt;span&gt;capability, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;interaction.&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="38"&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,0,0"&gt;&lt;span&gt;Concept &lt;/span&gt;&lt;span&gt;1: &lt;/span&gt;&lt;span&gt;Personal &lt;/span&gt;&lt;span&gt;Telemedicine &lt;/span&gt;&lt;span&gt;Node &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;Cloud &lt;/span&gt;&lt;span&gt;Connectivity &lt;/span&gt;&lt;span&gt;(nRF52840)&lt;/span&gt;&lt;/p&gt;
&lt;ul data-path-to-node="38,0,1"&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Platform:&lt;/span&gt; &lt;span&gt;Nordic &lt;/span&gt;&lt;span&gt;Semiconductor &lt;/span&gt;&lt;span&gt;nRF52840, &lt;/span&gt;&lt;span&gt;initially &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;nRF52840-DK &lt;/span&gt;&lt;span&gt;development &lt;/span&gt;&lt;span&gt;kit. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;integrates &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;64 &lt;/span&gt;&lt;span&gt;MHz &lt;/span&gt;&lt;span&gt;Arm &lt;/span&gt;&lt;span&gt;Cortex-M4F &lt;/span&gt;&lt;span&gt;processor &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;FPU, &lt;/span&gt;&lt;span&gt;256 &lt;/span&gt;&lt;span&gt;KB &lt;/span&gt;&lt;span&gt;RAM, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;1 &lt;/span&gt;&lt;span&gt;MB &lt;/span&gt;&lt;span&gt;Flash.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Role:&lt;/span&gt; &lt;span&gt;Acquire &lt;/span&gt;&lt;span&gt;physiological &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;data, &lt;/span&gt;&lt;span&gt;perform &lt;/span&gt;&lt;span&gt;local &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;processing, &lt;/span&gt;&lt;span&gt;estimate &lt;/span&gt;&lt;span&gt;heart &lt;/span&gt;&lt;span&gt;rate, &lt;/span&gt;&lt;span&gt;assess &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;quality, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;support &lt;/span&gt;&lt;span&gt;SpO₂ &lt;/span&gt;&lt;span&gt;estimation &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;appropriate &lt;/span&gt;&lt;span&gt;algorithm.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Communication:&lt;/span&gt; &lt;span&gt;Bluetooth &lt;/span&gt;&lt;span&gt;Low &lt;/span&gt;&lt;span&gt;Energy &lt;/span&gt;&lt;span&gt;(Bluetooth &lt;/span&gt;&lt;span&gt;5.0) &lt;/span&gt;&lt;span&gt;connects &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;device &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;smartphone &lt;/span&gt;&lt;span&gt;application.&lt;/span&gt;&lt;/p&gt;
&lt;span&gt;&lt;/span&gt;
&lt;p&gt;&lt;span&gt;Potential &lt;/span&gt;&lt;span&gt;standard &lt;/span&gt;&lt;span&gt;GATT &lt;/span&gt;&lt;span&gt;services &lt;/span&gt;&lt;span&gt;include:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Heart Rate Service (HRS):&lt;/span&gt; &lt;span&gt;For &lt;/span&gt;&lt;span&gt;heart-rate &lt;/span&gt;&lt;span&gt;measurements.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Health Thermometer Service (HTS):&lt;/span&gt; &lt;span&gt;For &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;measurements, &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;measurement &lt;/span&gt;&lt;span&gt;type &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;units &lt;/span&gt;&lt;span&gt;appropriately &lt;/span&gt;&lt;span&gt;defined.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Planned safety and notification features&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;smartphone &lt;/span&gt;&lt;span&gt;application &lt;/span&gt;&lt;span&gt;could &lt;/span&gt;&lt;span&gt;evaluate &lt;/span&gt;&lt;span&gt;configurable &lt;/span&gt;&lt;span&gt;thresholds, &lt;/span&gt;&lt;span&gt;indicate &lt;/span&gt;&lt;span&gt;abnormal &lt;/span&gt;&lt;span&gt;readings, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;notify &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;designated &lt;/span&gt;&lt;span&gt;caregiver. &lt;/span&gt;&lt;span&gt;If &lt;/span&gt;&lt;span&gt;supported &lt;/span&gt;&lt;span&gt;by &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;phone, &lt;/span&gt;&lt;span&gt;operating &lt;/span&gt;&lt;span&gt;system, &lt;/span&gt;&lt;span&gt;permissions, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;network &lt;/span&gt;&lt;span&gt;availability, &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;could &lt;/span&gt;&lt;span&gt;also &lt;/span&gt;&lt;span&gt;initiate &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;SMS &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;other &lt;/span&gt;&lt;span&gt;emergency &lt;/span&gt;&lt;span&gt;notification.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,1,0"&gt;Concept 2: Ultra-Low-Power Field Rescue Device (TI MSP430)&lt;/p&gt;
&lt;ul data-path-to-node="38,1,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,1,1,0,0"&gt;&lt;span&gt;Platform:&lt;/span&gt; &lt;span&gt;Texas &lt;/span&gt;&lt;span&gt;Instruments &lt;/span&gt;&lt;span&gt;MSP430G2553, &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;MSP-EXP430G2ET &lt;/span&gt;&lt;span&gt;development &lt;/span&gt;&lt;span&gt;platform. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;MCU &lt;/span&gt;&lt;span&gt;has &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;16-bit &lt;/span&gt;&lt;span&gt;architecture, &lt;/span&gt;&lt;span&gt;512 &lt;/span&gt;&lt;span&gt;bytes &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;RAM, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;16 &lt;/span&gt;&lt;span&gt;KB &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;Flash &lt;/span&gt;&lt;span&gt;memory.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,1,1,1,0"&gt;Design Philosophy: Prioritizing hardware simplicity, reliability, and ultra-low power consumption. Fully autonomous device intended for emergency field missions and long-term home healthcare.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,1,1,2,0"&gt;&lt;span&gt;Power management:&lt;/span&gt; &lt;span&gt;The &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;spend &lt;/span&gt;&lt;span&gt;most &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;its &lt;/span&gt;&lt;span&gt;idle &lt;/span&gt;&lt;span&gt;time &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;low-power &lt;/span&gt;&lt;span&gt;state, &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;LPM3 &lt;/span&gt;&lt;span&gt;considered &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;suitable &lt;/span&gt;&lt;span&gt;clock &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;peripheral &lt;/span&gt;&lt;span&gt;configurations.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Proposed operation&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;patient &lt;/span&gt;&lt;span&gt;activates &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;device &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;push-button.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;controller &lt;/span&gt;&lt;span&gt;wakes &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;initializes &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;required &lt;/span&gt;&lt;span&gt;peripherals.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;acquired &lt;/span&gt;&lt;span&gt;through &lt;/span&gt;&lt;span&gt;compatible &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;interfaces.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Heart &lt;/span&gt;&lt;span&gt;rate &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;other &lt;/span&gt;&lt;span&gt;supported &lt;/span&gt;&lt;span&gt;parameters &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;estimated.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;results &lt;/span&gt;&lt;span&gt;are &lt;/span&gt;&lt;span&gt;displayed &lt;/span&gt;&lt;span&gt;locally, &lt;/span&gt;&lt;span&gt;if &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;suitable &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;implemented.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;controller &lt;/span&gt;&lt;span&gt;returns &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;low-power &lt;/span&gt;&lt;span&gt;state &lt;/span&gt;&lt;span&gt;after &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;measurement &lt;/span&gt;&lt;span&gt;session.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,2,0"&gt;Concept 3: Autonomous Diagnostic Monitor with Advanced HMI (Wio Terminal)&lt;/p&gt;
&lt;ul data-path-to-node="38,2,1"&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,2,1,0,0"&gt;&lt;span&gt;Platform:&lt;/span&gt; &lt;span&gt;Seeed &lt;/span&gt;&lt;span&gt;Studio &lt;/span&gt;&lt;span&gt;Wio &lt;/span&gt;&lt;span&gt;Terminal, &lt;/span&gt;&lt;span&gt;based &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Microchip &lt;/span&gt;&lt;span&gt;ATSAMD51P19 &lt;/span&gt;&lt;span&gt;microcontroller: &lt;/span&gt;&lt;span&gt;Arm &lt;/span&gt;&lt;span&gt;Cortex-M4F &lt;/span&gt;&lt;span&gt;at &lt;/span&gt;&lt;span&gt;120 &lt;/span&gt;&lt;span&gt;MHz, &lt;/span&gt;&lt;span&gt;512 &lt;/span&gt;&lt;span&gt;KB &lt;/span&gt;&lt;span&gt;Flash, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;192 &lt;/span&gt;&lt;span&gt;KB &lt;/span&gt;&lt;span&gt;RAM. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;platform &lt;/span&gt;&lt;span&gt;includes &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;2.4-inch, &lt;/span&gt;&lt;span&gt;320 &lt;/span&gt;&lt;span&gt;&amp;times; &lt;/span&gt;&lt;span&gt;240-pixel &lt;/span&gt;&lt;span&gt;color &lt;/span&gt;&lt;span&gt;TFT &lt;/span&gt;&lt;span&gt;display, &lt;/span&gt;&lt;span&gt;navigation &lt;/span&gt;&lt;span&gt;buttons, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;RTL8720DN &lt;/span&gt;&lt;span&gt;wireless &lt;/span&gt;&lt;span&gt;module &lt;/span&gt;&lt;span&gt;supporting &lt;/span&gt;&lt;span&gt;Wi-Fi &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Bluetooth &lt;/span&gt;&lt;span&gt;Low &lt;/span&gt;&lt;span&gt;Energy.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,2,1,1,0"&gt;&lt;span&gt;Design philosophy:&lt;/span&gt; &lt;span&gt;Combine &lt;/span&gt;&lt;span&gt;local &lt;/span&gt;&lt;span&gt;visualization &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;interactive &lt;/span&gt;&lt;span&gt;controls &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;portable &lt;/span&gt;&lt;span&gt;embedded &lt;/span&gt;&lt;span&gt;computing &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;wireless &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;communication.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="38,2,1,2,0"&gt;&lt;span&gt;Role:&lt;/span&gt; &lt;span&gt;Acquire &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;through &lt;/span&gt;&lt;span&gt;compatible &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;interfaces. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;processing &lt;/span&gt;&lt;span&gt;capacity &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;ATSAMD51P19 &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;be &lt;/span&gt;&lt;span&gt;evaluated &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;local &lt;/span&gt;&lt;span&gt;filtering, &lt;/span&gt;&lt;span&gt;parameter &lt;/span&gt;&lt;span&gt;estimation, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;live &lt;/span&gt;&lt;span&gt;waveform &lt;/span&gt;&lt;span&gt;rendering.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;HMI and connectivity&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Standalone mode:&lt;/span&gt; &lt;span&gt;Display &lt;/span&gt;&lt;span&gt;current &lt;/span&gt;&lt;span&gt;measurements, &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;quality, &lt;/span&gt;&lt;span&gt;connection &lt;/span&gt;&lt;span&gt;status, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;stored &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;heart-rate &lt;/span&gt;&lt;span&gt;trends &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;integrated &lt;/span&gt;&lt;span&gt;screen &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;navigation &lt;/span&gt;&lt;span&gt;controls.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;IoT mode:&lt;/span&gt; &lt;span&gt;Send &lt;/span&gt;&lt;span&gt;selected &lt;/span&gt;&lt;span&gt;measurements &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;local &lt;/span&gt;&lt;span&gt;gateway &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;cloud &lt;/span&gt;&lt;span&gt;service &lt;/span&gt;&lt;span&gt;over &lt;/span&gt;&lt;span&gt;Wi-Fi &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;MQTT, &lt;/span&gt;&lt;span&gt;subject &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;implementation &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;required &lt;/span&gt;&lt;span&gt;network &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;application &lt;/span&gt;&lt;span&gt;protocols.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Comparative Summary of the Three Portable Concepts&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;table data-path-to-node="41"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;td&gt;Feature&lt;/td&gt;
&lt;td&gt;Concept 1: nRF52840&lt;/td&gt;
&lt;td&gt;Concept 2: MSP430&lt;/td&gt;
&lt;td&gt;Concept 3: Wio Terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary Focus&lt;/td&gt;
&lt;td&gt;Mobile connectivity, SOS alarms, cloud&lt;/td&gt;
&lt;td&gt;Multi-year battery life, ultra-low power&lt;/td&gt;
&lt;td&gt;Local live visualization (LCD), IoT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User Interface&lt;/td&gt;
&lt;td&gt;Smartphone Screen (Mobile App)&lt;/td&gt;
&lt;td&gt;Simple segment/OLED display&lt;/td&gt;
&lt;td&gt;Integrated 2.4&amp;quot; TFT Screen + Joystick&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Battery Life&lt;/td&gt;
&lt;td&gt;Days / Weeks (depending on BLE intervals)&lt;/td&gt;
&lt;td&gt;Years (0.7 uA sleep current)&lt;/td&gt;
&lt;td&gt;Hours / Days (depending on LCD backlight)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connectivity&lt;/td&gt;
&lt;td&gt;Bluetooth 5.0 Low Energy&lt;/td&gt;
&lt;td&gt;None (Full Air-Gap)&lt;/td&gt;
&lt;td&gt;Wi-Fi (MQTT) + Bluetooth 5.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signal Processing&lt;/td&gt;
&lt;td&gt;Medium/High (Cortex-M4F 64MHz)&lt;/td&gt;
&lt;td&gt;Basic (16-bit MSP430 16MHz)&lt;/td&gt;
&lt;td&gt;Very High (Cortex-M4F 120MHz)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;3. Project Schedule and Milestones&lt;/span&gt;&lt;/p&gt;
&lt;ol start="1" data-path-to-node="44"&gt;
&lt;li&gt;
&lt;p data-path-to-node="44,0,0"&gt;Phase I: Hardware Integration and Sensor Validation&lt;/p&gt;
&lt;ul data-path-to-node="44,0,1"&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Set &lt;/span&gt;&lt;span&gt;up &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;MAX30208EVSYS# &lt;/span&gt;&lt;span&gt;evaluation &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;verify &lt;/span&gt;&lt;span&gt;its &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;path &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;PC.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Interface &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;MAXREFDES117# &lt;/span&gt;&lt;span&gt;reference &lt;/span&gt;&lt;span&gt;design &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;STM32 &lt;/span&gt;&lt;span&gt;microcontroller.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Implement &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;transmission &lt;/span&gt;&lt;span&gt;using &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;suitable &lt;/span&gt;&lt;span&gt;VCP/UART &lt;/span&gt;&lt;span&gt;interface.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Verify &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;readings, &lt;/span&gt;&lt;span&gt;sample &lt;/span&gt;&lt;span&gt;formats, &lt;/span&gt;&lt;span&gt;timing, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;stability.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="44,1,0"&gt;Phase II: Diagnostic Station Application Development (C++/Qt or LabVIEW)&lt;/p&gt;
&lt;ul data-path-to-node="44,1,1"&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Configure &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;required &lt;/span&gt;&lt;span&gt;USB &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;serial &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;sessions.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Develop &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;graphical &lt;/span&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;interface &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;visualization.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Implement &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;buffering, &lt;/span&gt;&lt;span&gt;timestamps, &lt;/span&gt;&lt;span&gt;error &lt;/span&gt;&lt;span&gt;handling, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;measurement &lt;/span&gt;&lt;span&gt;logging.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Develop &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;evaluate &lt;/span&gt;&lt;span&gt;digital &lt;/span&gt;&lt;span&gt;filtering, &lt;/span&gt;&lt;span&gt;heart-rate &lt;/span&gt;&lt;span&gt;estimation, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;SpO₂ &lt;/span&gt;&lt;span&gt;estimation &lt;/span&gt;&lt;span&gt;algorithms &lt;/span&gt;&lt;span&gt;where &lt;/span&gt;&lt;span&gt;supported.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="44,2,0"&gt;Phase III: Portable Concept Implementation&lt;/p&gt;
&lt;ul data-path-to-node="44,2,1"&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Develop &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;nRF52840-based &lt;/span&gt;&lt;span&gt;BLE &lt;/span&gt;&lt;span&gt;monitoring &lt;/span&gt;&lt;span&gt;prototype.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Evaluate &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;feasibility &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;MSP430-based &lt;/span&gt;&lt;span&gt;low-power &lt;/span&gt;&lt;span&gt;implementation.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Develop &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;Wio &lt;/span&gt;&lt;span&gt;Terminal &lt;/span&gt;&lt;span&gt;graphical &lt;/span&gt;&lt;span&gt;interface &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;wireless &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;functions.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Document &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;differences &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;integration, &lt;/span&gt;&lt;span&gt;software &lt;/span&gt;&lt;span&gt;complexity, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;energy &lt;/span&gt;&lt;span&gt;requirements.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p data-path-to-node="44,3,0"&gt;Phase IV: Final Testing and Validation&lt;/p&gt;
&lt;ul data-path-to-node="44,3,1"&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Evaluate &lt;/span&gt;&lt;span&gt;acquisition &lt;/span&gt;&lt;span&gt;stability, &lt;/span&gt;&lt;span&gt;missing &lt;/span&gt;&lt;span&gt;samples, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;communication &lt;/span&gt;&lt;span&gt;errors.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Compare &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;readings &lt;/span&gt;&lt;span&gt;against &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;appropriate &lt;/span&gt;&lt;span&gt;reference &lt;/span&gt;&lt;span&gt;instrument &lt;/span&gt;&lt;span&gt;under &lt;/span&gt;&lt;span&gt;documented &lt;/span&gt;&lt;span&gt;test &lt;/span&gt;&lt;span&gt;conditions.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Compare &lt;/span&gt;&lt;span&gt;heart-rate &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;SpO₂ &lt;/span&gt;&lt;span&gt;estimates &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;suitable &lt;/span&gt;&lt;span&gt;reference &lt;/span&gt;&lt;span&gt;equipment, &lt;/span&gt;&lt;span&gt;recognizing &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;limitations &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;non-clinical &lt;/span&gt;&lt;span&gt;validation.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Measure &lt;/span&gt;&lt;span&gt;power &lt;/span&gt;&lt;span&gt;consumption &lt;/span&gt;&lt;span&gt;during &lt;/span&gt;&lt;span&gt;standby, &lt;/span&gt;&lt;span&gt;acquisition, &lt;/span&gt;&lt;span&gt;processing, &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;operation, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;wireless &lt;/span&gt;&lt;span&gt;transmission.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Evaluate &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;quality &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;effect &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;motion &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;sensor &lt;/span&gt;&lt;span&gt;placement.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;span&gt;Document &lt;/span&gt;&lt;span&gt;limitations, &lt;/span&gt;&lt;span&gt;repeatability, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;conditions &lt;/span&gt;&lt;span&gt;under &lt;/span&gt;&lt;span&gt;which &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;results &lt;/span&gt;&lt;span&gt;were &lt;/span&gt;&lt;span&gt;obtained.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span&gt;VitalSense &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;experimental &lt;/span&gt;&lt;span&gt;research &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;development &lt;/span&gt;&lt;span&gt;project. The &lt;/span&gt;&lt;span&gt;results &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;help &lt;/span&gt;&lt;span&gt;determine &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;practical &lt;/span&gt;&lt;span&gt;capabilities &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;limitations &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;each &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;platform &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;guide &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;development &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;future &lt;/span&gt;&lt;span&gt;portable &lt;/span&gt;&lt;span&gt;physiological-monitoring &lt;/span&gt;&lt;span&gt;prototypes. VitalSense &lt;/span&gt;&lt;span&gt;explores &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;modular &lt;/span&gt;&lt;span&gt;approach &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;physiological &lt;/span&gt;&lt;span&gt;monitoring, &lt;/span&gt;&lt;span&gt;combining &lt;/span&gt;&lt;span&gt;temperature &lt;/span&gt;&lt;span&gt;sensing, &lt;/span&gt;&lt;span&gt;optical &lt;/span&gt;&lt;span&gt;PPG &lt;/span&gt;&lt;span&gt;acquisition, &lt;/span&gt;&lt;span&gt;digital &lt;/span&gt;&lt;span&gt;signal &lt;/span&gt;&lt;span&gt;processing, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;embedded &lt;/span&gt;&lt;span&gt;computing.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;PC-based &lt;/span&gt;&lt;span&gt;diagnostic &lt;/span&gt;&lt;span&gt;station &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;provide &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;flexible &lt;/span&gt;&lt;span&gt;environment &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;acquiring &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;analyzing &lt;/span&gt;&lt;span&gt;measurements, &lt;/span&gt;&lt;span&gt;while &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;three &lt;/span&gt;&lt;span&gt;portable &lt;/span&gt;&lt;span&gt;concepts &lt;/span&gt;&lt;span&gt;will &lt;/span&gt;&lt;span&gt;enable &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;comparative &lt;/span&gt;&lt;span&gt;study &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;wireless &lt;/span&gt;&lt;span&gt;connectivity, &lt;/span&gt;&lt;span&gt;low-power &lt;/span&gt;&lt;span&gt;operation, &lt;/span&gt;&lt;span&gt;local &lt;/span&gt;&lt;span&gt;processing, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;interaction.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Palno &amp; Slemon #3 Building the Algorithm</title><link>https://community.element14.com/thread/57366?ContentTypeID=0</link><pubDate>Thu, 22 Oct 2026 16:22:14 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:2997b5b1-61a8-49bb-8dca-90d351b61152</guid><dc:creator>Qbit</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/57366?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57366/palno-slemon-3-building-the-algorithm/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Hi, I hope you are doing well, and I am really sorry for the delay&amp;nbsp; in posting this part, I was a little lost and busy with other work. But I will give my best finishing this project and making it reliable.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:150%;"&gt;A Quick Recap&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;I was working on project&amp;nbsp; that uses&amp;nbsp; data from multiple resources like breathing data from the radar module,&amp;nbsp; heart beat rate , blood oxygen level to detect&amp;nbsp; the stage of sleep you are in to help you wake up at the right time so you wouldn`t feel tired after you wake up, because wake you up at the right time.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;These are the past posts:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57301/palno-slemon-1-introduction" data-e14adj="t"&gt;Palno &amp;amp; Slemon #1 Introduction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57315/palno-slemon-2-1-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.1 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57324/palno-slemon-2-2-configuring-and-validating" data-e14adj="t"&gt;Palno &amp;amp; Slemon #2.2 Configuring and Validating&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Algorithm&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;We need to go there in two places:
&lt;ol&gt;
&lt;li&gt;In the radar module&lt;/li&gt;
&lt;li&gt;In the heart rate and blood oxygen level sensor&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;First,&amp;nbsp; radar module. I have thought of using a model to detect breath but I wasn&amp;#39;t successful as&amp;nbsp; it gave me terrible results, as I will show you soon.&amp;nbsp;&lt;/p&gt;
We already have the algorithm from the resources provided by the analog devices but I would like to explain how it works.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:150%;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;The Radar (HLK-LD2410)&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/hlk.png" /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;(Primarily this is the one I am using.)&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;I would also like to share the part of the journey of making it, though I had not used it, finally, because it was really terrible.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;Firstly I tried training the model but in the future I will see that it will become a terrible waste of time.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;I first decided to collect data for that. As I am using esp32 for test purposes, I use its web capabilities to collect data and control pause and resume via the web interface. Do it a little bit.Then I collect a little bit of data, at least 93 samples: 46 for breathing data and 47 for normal data, like the background, when we hold the breath and train. We save it as a CSV, which is also timestamped.I also used Python with PySerial to communicate with the ESP32 and capture the data. From the web interface when the button switched on, it saves the data of the given time and stamps it with a time tag in milliseconds, assigns all the values, and saves it as CSV.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_09_2D00_13-231641.png" /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;(This is the representation of a CSV dataset I made but it is not the same as what I used.)&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;There were many axes, like all the data the data module can give, so I don&amp;#39;t show the graph here in the web interface because it will crash. It could crash and it is ready to. I had to use AI for this because I don&amp;#39;t have a lot of time to finish it all up.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_18-193247.png" /&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;Screenshot of the web interface hosted on the ESP32&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;Sadly I was not able to use it because I was not able to capture a lot of sensible data. Though I have enough computing power on the Arduino Q for the project, the 100 samples (approximately) I collected are not enough to train that complex model, as I will show you later in the graph. This is because there were nearly a lot of delays and distortion during the collection of data. The sensor is good at its job collecting a lot of data and training a model with a lot of axes requires the equivalent amount of data.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_21-222156.png" /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;I know this completely looks terrible and I really have wasted 4 to 5 days doing this.&lt;br /&gt;&lt;br /&gt;Firstly I had got accuracy pretty well 50%, not that pretty well but better than 0%. I know, 50% was not that usable though. I thought after doing some more improvements I will really improve it but that wasn&amp;#39;t the case. I even distorted the 50% and fell into 0%. Absolutely terrible.&lt;br /&gt;&lt;br /&gt;This is how I lean towards the algorithm, with the stress that I had to it finish in 2 days.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;pre class="ui-code" data-mode="text"&gt;
3	30	100	30	0	100	100	34	10	9	10	2	11	8	100	100	80	41	41	28	1	1
3	53	100	30	0	100	100	100	11	9	2	5	8	5	100	100	80	42	42	29	1	1
3	66	100	53	0	100	100	100	19	10	8	11	9	13	100	100	82	44	45	31	1	1
3	72	100	66	0	100	100	100	33	8	10	11	8	13	100	100	85	48	48	34	1	1
3	73	100	72	31	99	100	53	19	13	9	8	9	7	100	100	89	52	51	38	1	1
3	75	100	73	34	36	100	31	2	10	12	8	9	8	100	100	92	55	54	41	1	1
3	67	79	75	36	35	79	14	3	5	8	10	9	7	100	100	95	58	56	44	1	1
3	71	55	67	38	19	55	11	6	3	6	9	8	8	100	100	98	61	58	47	1	1
3	41	94	71	37	90	94	9	10	1	3	8	5	7	100	100	99	64	61	49	1	1
3	72	100	41	40	42	100	18	9	3	8	6	5	9	100	100	100	67	63	52	1	1
3	62	100	72	40	100	100	18	7	3	10	4	3	10	100	100	100	70	65	54	1	1
3	66	100	62	41	57	100	16	9	2	9	4	2	9	100	100	100	73	68	57	1	1
3	62	62	66	41	37	62	12	9	3	6	4	2	8	100	100	100	75	70	59	1	1
3	63	100	62	41	79	100	21	4	4	4	5	3	4	100	100	100	78	72	61	1	1&lt;/pre&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;This is the raw data I was getting from the sensors.&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_20-194656.png" /&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;Visually&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;The ESP32 was communicating to the Radar using a serial connection at a 256,000 baud rate.&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define LD2410_BAUD 256000
#define RX_PIN 16
#define TX_PIN 17
#define MAX_GATES 9

// Frame parser state: header -&amp;gt; length -&amp;gt; payload -&amp;gt; footer
enum { ST_HDR, ST_LEN, ST_DATA, ST_FOOT } rxSt = ST_HDR;

void setup() {
  Serial.begin(115200);
  Serial2.begin(LD2410_BAUD, SERIAL_8N1, RX_PIN, TX_PIN);
  // Engineering mode is enabled later by sending &amp;#39;n&amp;#39;
}

// Non-blocking: consumes whatever bytes are waiting on UART2
static void readRadar() {
  while (Serial2.available()) {
    uint8_t b = Serial2.read();
    switch (rxSt) {
      case ST_HDR:   /* slide a 4-byte window until F4 F3 F2 F1 (data)
                        or FD FC FB FA (command ACK) matches */      break;
      case ST_LEN:   /* read 2-byte little-endian payload length */   break;
      case ST_DATA:  /* collect &amp;#39;length&amp;#39; payload bytes */             break;
      case ST_FOOT:  /* collect F8 F7 F6 F5, then parseData() */      break;
    }
  }
}

// Decode one engineering-mode frame (d points at the payload)
static void parseData() {
  const uint8_t* d = fb + 6;
  if (d[1] != 0xAA) return;                      // data marker

  g_state   = d[2];
  g_movDist = d[3] | (d[4] &amp;lt;&amp;lt; 8);                // cm
  g_movEn   = d[5];
  g_staDist = d[6] | (d[7] &amp;lt;&amp;lt; 8);                // cm
  g_detDist = d[9] | (d[10] &amp;lt;&amp;lt; 8);               // cm

  if (d[0] == 0x01) {                            // engineering frame
    uint8_t idx = 13;
    for (uint8_t i = 0; i &amp;lt;= g_maxMov; i++) g_movG[i] = d[idx++];  // MG0..MG8
    for (uint8_t i = 0; i &amp;lt;= g_maxSta; i++) g_staG[i] = d[idx++];  // SG0..SG8
    g_light = d[idx++];
    g_out   = d[idx];
  }
  newData = true;
}

// One row per frame, 20 Hz
static void outputLine() {
  Serial.print(g_state);   Serial.print(&amp;#39;\t&amp;#39;);
  Serial.print(g_movDist); Serial.print(&amp;#39;\t&amp;#39;);
  Serial.print(g_movEn);   Serial.print(&amp;#39;\t&amp;#39;);
  Serial.print(g_staDist); Serial.print(&amp;#39;\t&amp;#39;);
  Serial.print(g_detDist); Serial.print(&amp;#39;\t&amp;#39;);
  for (uint8_t i = 0; i &amp;lt; MAX_GATES; i++) { Serial.print(g_movG[i]); Serial.print(&amp;#39;\t&amp;#39;); }
  for (uint8_t i = 3; i &amp;lt; MAX_GATES; i++) { Serial.print(g_staG[i]); Serial.print(&amp;#39;\t&amp;#39;); }
  Serial.print(g_light); Serial.print(&amp;#39;\t&amp;#39;);
  Serial.println(g_out);
}&lt;/pre&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;This is the simplified version of the code I used for the ESP32 to send data over serial to the computer and also to take received data from the radar.&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt; The radar streams binary frames continuously, so the firmware runs a small state machine that finds the frame header, reads the length, collects the payload and footer, and then decodes the fields. In engineering mode each frame carries the target state, moving and static distances, the energy of each of the nine range gates, and the light and OUT pin values. The sketch prints these as one tab-separated row at 20 Hz, which is the raw data above and the input to the CSV logger. The 22 columns are State, MovDist, MovEnergy, StaDist, DetDist, MG0&amp;ndash;MG8, SG3&amp;ndash;SG8, Light and OutPin.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:150%;"&gt;The real algorithm&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:150%;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;After the failure in creating the impulse, I had to work on the algorithm.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;In order to create the algorithm first, I have to look for patterns while I&amp;#39;m breathing from the data. The best way a human can do that is visually. So I looked at the visual data.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_22-144519.png" /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;I recorded the data. Keeping in mind that it detects breathing while sleeping, I made as minimalist a movement as possible to detect only the movement of breathing, along with the background noise (as it will be there while sleeping also). I captured it and after staring at it for a while, I noticed some patterns.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/data.png" /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;So as you can see, while breathing we also inhale and exhale and the duration while we do that at the peaks is not that much different. In between the zeroth values, while we are moving towards the next breathing process, there is a noticeable difference that we can use to detect the n number of breaths.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;And we can also see the wave format in the crust, in the gate energies. By that&amp;nbsp; we can also detect the intensity and the distance and as per the distance we can also get the accurate value of breaths per minute.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;And the code was very long because we have to manage the communication especially too and also while plotting it all and showing all the graphs. After implementation the code I developed was fairly long, I think really long. I won&amp;#39;t be able to write it without using AI and I think if I do I will need a week or two.If you want to take a look at it, you can see it below.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;pre class="ui-code" data-mode="python"&gt;&amp;quot;&amp;quot;&amp;quot;
LD2410 Real-Time mmWave Monitor &amp;amp; Breath Counter (Algorithm 1)
=============================================================
Connects to ESP32 over serial, prompts the user to send &amp;#39;n&amp;#39; to
start streaming, verifies incoming radar data, opens a fast real-time
graph window, and runs the breath counting algorithm (Algorithm 1):

Algorithm 1 Logic:
  1. Trigger / Arming: Waits until moving energy is &amp;gt;= 100 continuously
     for the first 3 seconds (TRIGGER_DURATION_SEC = 3.0s).
  2. Breath Counting: Once armed, counts breath pulses when non-zero peaks
     are separated by &amp;gt;= 25 consecutive zero values (energy &amp;lt;= baseline).
  3. Loop &amp;amp; Stop: Loops and increments breath count until moving energy
     reaches constant 100 for 3 seconds (STOP_DURATION_SEC = 3.0s).
     When constant 100 for 3.0s is met, the session concludes.
     If moving energy &amp;gt;= 100 for 3.0s occurs again, it re-arms and loops.

Requirements:
    pip install pyserial matplotlib numpy

Usage:
    python ld2410_plotter.py                      # auto-detect port
    python ld2410_plotter.py COM3                 # specific port
    python ld2410_plotter.py COM3 --auto-start    # send &amp;#39;n&amp;#39; without prompt

Controls in Plot Window:
    [+] / [=] / [UP]  : Increase Breath Baseline noise floor live (+1)
    [-] / [_] / [DOWN]: Decrease Breath Baseline noise floor live (-1)
    [Mouse Drag]      : Drag the &amp;#39;Baseline (Noise Floor)&amp;#39; slider at the bottom
    [b]               : Reset / Re-arm Breath Counter
    [n]               : Send &amp;#39;n&amp;#39; (Start / Resume streaming)
    [x]               : Send &amp;#39;x&amp;#39; (Pause streaming)
    [1] - [5]         : Set sensitivity presets (1=5/5 ... 5=75/75)
    [v]               : Read firmware version
    [p]               : Read radar parameters
    [q] or [ESC]      : Quit
&amp;quot;&amp;quot;&amp;quot;

import sys
import os
import time
import argparse
import threading
import collections

import serial
import serial.tools.list_ports
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.gridspec import GridSpec
from matplotlib.widgets import Slider

# ─────────────────────── USER CONFIGURATION (ALTER VARIABLES HERE) ────────────────────────
# You can freely alter any of these variables directly to adjust radar and breath detection behavior:

# ── 1. Breath Detection &amp;amp; Baseline Tuning ──
SAMPLE_BASELINE              = 15.0     # Breath detection noise floor / baseline (Moving Energy 0-100).
                                        # Values &amp;lt;= SAMPLE_BASELINE are treated as silence/pause (zeros);
                                        # Values &amp;gt; SAMPLE_BASELINE are detected as breathing motion peaks.
                                        # NOTE: You can also adjust this LIVE in the plot window via
                                        # the on-screen slider or [+] / [-] / [UP] / [DOWN] keys!

MIN_ZERO_GAP                 =  15.0
MIN_ZERO_GAP  = SAMPLE_BASELINE 
                                        # Minimum consecutive zero values required between peaks (default: 25).
                                        # Difference between two peaks is &amp;gt; 25 and all 25 or more values
                                        # in between are zero (&amp;lt;= SAMPLE_BASELINE).

# ── 2. Trigger &amp;amp; Stop Durations (3s at 100 Trigger &amp;amp; Exit Loop) ──
TRIGGER_ENERGY_REQ           = 100.0    # Energy required to arm (moving energy not less than 100).
TRIGGER_DURATION_SEC         = 3.0      # Moving energy must be &amp;gt;= 100 for first 3 seconds to start counting.
STOP_DURATION_SEC            = 3.0      # Loops until moving energy reaches constant 100 for 3 seconds to stop.

# ── 3. Radar &amp;amp; Display Window Settings ──
BAUD_RATE                    = 115200   # Serial communication baud rate (ESP32 defaults to 115200).
HISTORY                      = 200      # Rolling waveform buffer size (200 samples @ 20Hz = 10.0 seconds).
UPDATE_MS                    = 40       # Matplotlib GUI refresh interval in milliseconds (~25 FPS).
DARK_BG                      = True     # True: Dark mode (#111111); False: Light mode.
GATE_DIST_M                  = 0.75     # Radar gate resolution in metres (0.75m per gate).
MAX_GATES                    = 9        # Total number of distance gates (0 to 8).

# Column indices (0-based) for the 22 columns received from ESP32
COL_STATE    = 0
COL_MOVDIST  = 1
COL_MOVEN    = 2
COL_STADIST  = 3
COL_DETDIST  = 4
COL_MG_START = 5         # MG0..MG8  → indices 5..13
COL_SG_START = 14        # SG3..SG8  → indices 14..19
COL_LIGHT    = 20
COL_OUTPIN   = 21
TOTAL_COLS   = 22

# ─────────────────────── Serial auto-detect ───────────────────

def find_esp32_port():
    &amp;quot;&amp;quot;&amp;quot;Return the most likely ESP32 COM port, or None.&amp;quot;&amp;quot;&amp;quot;
    ESP_VIDS = {0x10C4, 0x1A86, 0x0403}   # CP2102, CH340, FTDI
    ports = serial.tools.list_ports.comports()
    for p in ports:
        if p.vid in ESP_VIDS:
            return p.device
    if ports:
        return ports[0].device
    return None

# ─────────────────────── Breath Counter (Algorithm 1) ───────────────────────

class BreathCounter:
    &amp;quot;&amp;quot;&amp;quot;
    Real-Time Breath Counter Algorithm (Algorithm 1):
    1. Arming / Trigger:
       - Requires Moving Energy &amp;gt;= 100 for the first 3.0 seconds to start counting.
    2. Peak &amp;amp; Zero-Crossing Detection:
       - Once armed, increments breath count when two non-zero peaks are separated
         by &amp;gt;= 25 consecutive zero values (moving energy &amp;lt;= SAMPLE_BASELINE).
    3. Loop &amp;amp; Session Stop:
       - Loops and continues counting until moving energy reaches constant 100
         for 3.0 continuous seconds to stop.
       - Re-arms if moving energy &amp;gt;= 100 for 3.0s occurs again.
    &amp;quot;&amp;quot;&amp;quot;
    STATE_WAITING = &amp;quot;WAITING_TRIGGER&amp;quot;  # Waiting for &amp;gt;= 100 for 3s
    STATE_ACTIVE  = &amp;quot;COUNTING&amp;quot;         # Active breath counting session
    STATE_STOPPED = &amp;quot;STOPPED&amp;quot;          # Stopped after constant 100 for 3s

    def __init__(self,
                 trigger_duration=TRIGGER_DURATION_SEC,
                 stop_duration=STOP_DURATION_SEC,
                 min_zero_gap=MIN_ZERO_GAP,
                 min_trigger_energy=TRIGGER_ENERGY_REQ,
                 peak_threshold=SAMPLE_BASELINE):
        self.trigger_duration = float(trigger_duration)
        self.stop_duration = float(stop_duration)
        self.min_zero_gap = int(min_zero_gap)
        self.min_trigger_energy = float(min_trigger_energy)
        self.peak_threshold = float(peak_threshold)

        self.state = self.STATE_WAITING
        self.breath_count = 0
        self.zero_count = 0
        self.in_breath = False
        self.has_peak = False

        # Timers &amp;amp; arming flags
        self.start_100_time = None
        self.stop_100_time = None
        self.waiting_to_clear_trigger = False

        # Progress tracking
        self.trigger_progress = 0.0
        self.stop_progress = 0.0

        # Diagnostics &amp;amp; BPM
        self.last_breath_time = None
        self.last_peak_val = 0.0
        self.last_zero_interval = 0
        self.bpm = 0.0

    def reset(self):
        &amp;quot;&amp;quot;&amp;quot;Reset counter back to waiting for trigger.&amp;quot;&amp;quot;&amp;quot;
        self.state = self.STATE_WAITING
        self.breath_count = 0
        self.zero_count = 0
        self.in_breath = False
        self.has_peak = False
        self.start_100_time = None
        self.stop_100_time = None
        self.waiting_to_clear_trigger = False
        self.trigger_progress = 0.0
        self.stop_progress = 0.0
        self.last_breath_time = None
        self.last_peak_val = 0.0
        self.last_zero_interval = 0
        self.bpm = 0.0
        print(f&amp;quot;\n[BREATH] Counter reset. Waiting for Moving Energy &amp;gt;= {self.min_trigger_energy:.0f} for {self.trigger_duration:.1f}s...\n&amp;quot;)

    def process_sample(self, moving_energy: float, timestamp: float = None) -&amp;gt; bool:
        &amp;quot;&amp;quot;&amp;quot;
        Process incoming radar moving energy sample.
        Returns True if a new breath peak was detected on this sample, False otherwise.
        &amp;quot;&amp;quot;&amp;quot;
        if timestamp is None:
            timestamp = time.time()

        is_breath = False

        # ── State 1: WAITING_TRIGGER ──
        if self.state == self.STATE_WAITING:
            if moving_energy &amp;gt;= self.min_trigger_energy:
                if self.start_100_time is None:
                    self.start_100_time = timestamp
                elapsed = timestamp - self.start_100_time
                self.trigger_progress = min(1.0, elapsed / self.trigger_duration)
                if elapsed &amp;gt;= (self.trigger_duration - 1e-4):
                    self.state = self.STATE_ACTIVE
                    self.breath_count = 0
                    self.zero_count = 0
                    self.has_peak = True
                    self.waiting_to_clear_trigger = True
                    self.start_100_time = None
                    self.trigger_progress = 1.0
                    print(f&amp;quot;\n[BREATH] &amp;gt;&amp;gt;&amp;gt; TRIGGER MET! Moving Energy was &amp;gt;= {self.min_trigger_energy:.0f} for {self.trigger_duration:.1f}s. Breath counting ACTIVE! &amp;lt;&amp;lt;&amp;lt;\n&amp;quot;)
            else:
                self.start_100_time = None
                self.trigger_progress = 0.0

        # ── State 2: COUNTING ──
        elif self.state == self.STATE_ACTIVE:
            # Check stop condition: constant 100 for stop_duration (3.0s)
            if moving_energy &amp;gt;= self.min_trigger_energy:
                if not self.waiting_to_clear_trigger:
                    if self.stop_100_time is None:
                        self.stop_100_time = timestamp
                    elapsed = timestamp - self.stop_100_time
                    self.stop_progress = min(1.0, elapsed / self.stop_duration)
                    if elapsed &amp;gt;= (self.stop_duration - 1e-4):
                        self.state = self.STATE_STOPPED
                        self.stop_progress = 1.0
                        print(f&amp;quot;\n[BREATH] &amp;gt;&amp;gt;&amp;gt; SESSION COMPLETED! Constant {self.min_trigger_energy:.0f} for {self.stop_duration:.1f}s reached. Final Breath Count: {self.breath_count} &amp;lt;&amp;lt;&amp;lt;\n&amp;quot;)
                        return False
                # While energy is saturated at 100, do not count as a breath peak
                self.zero_count = 0
                return False
            else:
                self.waiting_to_clear_trigger = False
                self.stop_100_time = None
                self.stop_progress = 0.0

            # Peak &amp;amp; Zero-crossing detection based on baseline
            if moving_energy &amp;gt; self.peak_threshold:
                if not self.in_breath:
                    # Check if preceded by &amp;gt;= 25 consecutive zero values
                    if self.zero_count &amp;gt;= self.min_zero_gap:
                        self.breath_count += 1
                        self.in_breath = True
                        self.last_zero_interval = self.zero_count
                        self.last_peak_val = moving_energy

                        if self.last_breath_time is not None:
                            interval = timestamp - self.last_breath_time
                            if 1.0 &amp;lt;= interval &amp;lt;= 15.0:
                                self.bpm = 60.0 / interval

                        self.last_breath_time = timestamp
                        self.zero_count = 0
                        is_breath = True
                        bpm_str = f&amp;quot; ({self.bpm:.0f} BPM)&amp;quot; if self.bpm &amp;gt; 0 else &amp;quot;&amp;quot;
                        print(f&amp;quot;[BREATH] +1 Breath #{self.breath_count} detected!{bpm_str} (Zeros in between: {self.last_zero_interval}, Energy: {moving_energy:.0f})&amp;quot;)
                    else:
                        # Continuing current breath or sub-pulse
                        self.zero_count = 0
                        self.last_peak_val = max(self.last_peak_val, moving_energy)
                else:
                    self.zero_count = 0
                    self.last_peak_val = max(self.last_peak_val, moving_energy)
            else:
                # Value is in the baseline noise floor (&amp;lt;= peak_threshold)
                self.zero_count += 1
                if self.zero_count &amp;gt;= self.min_zero_gap:
                    self.in_breath = False

        # ── State 3: STOPPED ──
        elif self.state == self.STATE_STOPPED:
            # Re-arm loop if moving energy &amp;gt;= 100 for 3s again
            if moving_energy &amp;lt; self.min_trigger_energy:
                self.start_100_time = None
                self.trigger_progress = 0.0
            else:
                if self.start_100_time is None:
                    self.start_100_time = timestamp
                elapsed = timestamp - self.start_100_time
                if elapsed &amp;gt;= (self.trigger_duration - 1e-4):
                    print(f&amp;quot;\n[BREATH] &amp;gt;&amp;gt;&amp;gt; RE-TRIGGER MET! Starting new breath counting session... &amp;lt;&amp;lt;&amp;lt;\n&amp;quot;)
                    self.state = self.STATE_ACTIVE
                    self.breath_count = 0
                    self.zero_count = 0
                    self.has_peak = True
                    self.waiting_to_clear_trigger = True
                    self.start_100_time = None
                    self.stop_100_time = None

        return is_breath

    def get_status_summary(self):
        return {
            &amp;quot;state&amp;quot;: self.state,
            &amp;quot;count&amp;quot;: self.breath_count,
            &amp;quot;zero_count&amp;quot;: self.zero_count,
            &amp;quot;last_interval&amp;quot;: self.last_zero_interval,
            &amp;quot;trigger_progress&amp;quot;: self.trigger_progress,
            &amp;quot;stop_progress&amp;quot;: self.stop_progress,
            &amp;quot;bpm&amp;quot;: self.bpm,
            &amp;quot;peak_threshold&amp;quot;: self.peak_threshold
        }

# ─────────────────────── Data thread ──────────────────────────

class RadarReader(threading.Thread):
    &amp;quot;&amp;quot;&amp;quot;Reads serial lines in background and feeds data to thread-safe buffer.&amp;quot;&amp;quot;&amp;quot;

    def __init__(self, ser, breath_counter=None):
        super().__init__(daemon=True)
        self.ser            = ser
        self.buf            = collections.deque(maxlen=HISTORY)
        self.breath_flags   = collections.deque(maxlen=HISTORY)
        self.lock           = threading.Lock()
        self.status         = &amp;quot;Streaming&amp;quot;
        self.connected      = True
        self._stop          = False
        self.latest         = [0.0] * TOTAL_COLS
        self.packet_cnt     = 0
        self.breath_counter = breath_counter or BreathCounter()

    def stop(self):
        self._stop = True

    def send(self, cmd: str):
        &amp;quot;&amp;quot;&amp;quot;Send a single character command to ESP32.&amp;quot;&amp;quot;&amp;quot;
        if self.ser and self.ser.is_open:
            try:
                self.ser.write((cmd + &amp;#39;\n&amp;#39;).encode(&amp;#39;ascii&amp;#39;))
                self.ser.flush()
            except Exception as e:
                print(f&amp;quot;[SERIAL] Write error: {e}&amp;quot;)

    def run(self):
        while not self._stop and self.ser and self.ser.is_open:
            try:
                raw = self.ser.readline()
                if not raw:
                    continue
                line = raw.decode(&amp;#39;ascii&amp;#39;, errors=&amp;#39;ignore&amp;#39;).strip()

                if not line or line.startswith(&amp;#39;#&amp;#39;):
                    if line.startswith(&amp;#39;#&amp;#39;):
                        # Display firmware / parameters feedback
                        if any(k in line for k in (&amp;quot;FW&amp;quot;, &amp;quot;Params&amp;quot;, &amp;quot;Sens&amp;quot;, &amp;quot;MaxDist&amp;quot;, &amp;quot;STREAMING&amp;quot;)):
                            print(f&amp;quot;[ESP32] {line}&amp;quot;)
                    continue

                # Data line starts with numeric State (0, 1, 2, 3)
                if not line[0].isdigit():
                    continue

                sep = &amp;#39;,&amp;#39; if &amp;#39;,&amp;#39; in line else &amp;#39;\t&amp;#39;
                parts = line.split(sep)
                if len(parts) != TOTAL_COLS:
                    continue

                row = [float(p) for p in parts]
                is_breath = self.breath_counter.process_sample(row[COL_MOVEN])

                with self.lock:
                    self.buf.append(row)
                    self.breath_flags.append(is_breath)
                    self.latest = row
                    self.packet_cnt += 1

            except serial.SerialException as e:
                self.status = f&amp;quot;Serial error: {e}&amp;quot;
                self.connected = False
                break
            except Exception as e:
                self.status = f&amp;quot;Error: {e}&amp;quot;

# ─────────────────────── Plot Setup ───────────────────────────

STATE_LABELS = {0: &amp;quot;No Target&amp;quot;, 1: &amp;quot;Moving&amp;quot;, 2: &amp;quot;Static&amp;quot;, 3: &amp;quot;Both&amp;quot;}
STATE_COLORS = {0: &amp;#39;#555555&amp;#39;, 1: &amp;#39;#00ccff&amp;#39;, 2: &amp;#39;#ffaa00&amp;#39;, 3: &amp;#39;#ff4444&amp;#39;}

if DARK_BG:
    plt.style.use(&amp;#39;dark_background&amp;#39;)

fig = plt.figure(figsize=(15, 9.5), facecolor=&amp;#39;#111111&amp;#39; if DARK_BG else &amp;#39;#f5f5f5&amp;#39;)
fig.canvas.manager.set_window_title(&amp;#39;HLK-LD2410 Real-Time mmWave Monitor &amp;amp; Breath Counter&amp;#39;)

gs = GridSpec(4, 2, figure=fig,
              left=0.06, right=0.97,
              top=0.92, bottom=0.075,
              hspace=0.52, wspace=0.30)

ax_dist   = fig.add_subplot(gs[0, :])    # distances — full width
ax_moven  = fig.add_subplot(gs[1, :])    # moving energy + target state + breath
ax_movg   = fig.add_subplot(gs[2, :])    # per-gate moving energies MG0–MG8
ax_stag   = fig.add_subplot(gs[3, 0])    # static gate energies SG3–SG8
ax_misc   = fig.add_subplot(gs[3, 1])    # Light + Output pin

def style_ax(ax, title, ylabel=&amp;#39;&amp;#39;, ylim=None):
    ax.set_title(title, fontsize=9.5, pad=3, fontweight=&amp;#39;bold&amp;#39;,
                 color=&amp;#39;#dddddd&amp;#39; if DARK_BG else &amp;#39;#222222&amp;#39;)
    ax.set_ylabel(ylabel, fontsize=8)
    ax.tick_params(labelsize=7.5)
    ax.grid(True, alpha=0.25, linestyle=&amp;#39;:&amp;#39;)
    if ylim: ax.set_ylim(ylim)

style_ax(ax_dist,  &amp;#39;Distance Tracking (cm)&amp;#39;,            &amp;#39;cm&amp;#39;,     (0, 700))
style_ax(ax_moven, &amp;#39;Motion Energy (0-100) &amp;amp; Breath Detection (Algorithm 1)&amp;#39;, &amp;#39;Level&amp;#39;,  (0, 105))
style_ax(ax_movg,  &amp;#39;Moving Gate Energies: Gate 0 to Gate 8 (0.75m steps)&amp;#39;, &amp;#39;Energy&amp;#39;, (0, 105))
style_ax(ax_stag,  &amp;#39;Static Gate Energies: Gate 3 to Gate 8&amp;#39;, &amp;#39;Energy&amp;#39;, (0, 105))
style_ax(ax_misc,  &amp;#39;Photosensitive Light &amp;amp; OUT Pin Status&amp;#39;, &amp;#39;Value&amp;#39;)

x_data = list(range(HISTORY))

# ── Distance plot lines ──
line_movdist, = ax_dist.plot(x_data, [0]*HISTORY, color=&amp;#39;#00d4ff&amp;#39;, lw=1.5, label=&amp;#39;Moving Target Dist&amp;#39;)
line_stadist, = ax_dist.plot(x_data, [0]*HISTORY, color=&amp;#39;#ffaa00&amp;#39;, lw=1.5, label=&amp;#39;Stationary Target Dist&amp;#39;)
line_detdist, = ax_dist.plot(x_data, [0]*HISTORY, color=&amp;#39;#44ff88&amp;#39;, lw=1.2, ls=&amp;#39;--&amp;#39;, label=&amp;#39;Detection Range&amp;#39;)
ax_dist.legend(fontsize=7.5, loc=&amp;#39;upper left&amp;#39;, framealpha=0.35)

# ── Motion energy + state lines + breath detections + baseline ──
line_moven, = ax_moven.plot(x_data, [0]*HISTORY, color=&amp;#39;#ff3388&amp;#39;, lw=1.6, label=&amp;#39;Moving Energy&amp;#39;)
bar_state   = ax_moven.fill_between(x_data, 0, [0]*HISTORY, alpha=0.18, color=&amp;#39;#00aaff&amp;#39;, label=&amp;#39;State Area&amp;#39;)
line_baseline = ax_moven.axhline(
    y=SAMPLE_BASELINE, color=&amp;#39;#ffee00&amp;#39;, linestyle=&amp;#39;--&amp;#39;,
    linewidth=1.3, alpha=0.85, label=f&amp;#39;Baseline ({SAMPLE_BASELINE:.0f})&amp;#39;, zorder=4
)
line_breaths, = ax_moven.plot([], [], &amp;#39;o&amp;#39;, color=&amp;#39;#00ffff&amp;#39;, markersize=7.5,
                             markeredgecolor=&amp;#39;#ffffff&amp;#39;, markeredgewidth=1.2,
                             label=&amp;#39;Breath Peak Detected&amp;#39;, zorder=5)
ax_moven.legend(fontsize=7.5, loc=&amp;#39;upper left&amp;#39;, framealpha=0.35)

# Breath detection HUD badge on ax_moven
breath_hud = ax_moven.text(
    0.985, 0.88, &amp;#39;[Breath] Initializing...&amp;#39;,
    transform=ax_moven.transAxes, ha=&amp;#39;right&amp;#39;, va=&amp;#39;top&amp;#39;,
    fontsize=9.0, fontweight=&amp;#39;bold&amp;#39;,
    color=&amp;#39;#ffaa00&amp;#39;,
    bbox=dict(boxstyle=&amp;#39;round,pad=0.38&amp;#39;, facecolor=&amp;#39;#151c28&amp;#39; if DARK_BG else &amp;#39;#ffffff&amp;#39;,
              edgecolor=&amp;#39;#ffaa00&amp;#39;, alpha=0.9, lw=1.2)
)

# ── Moving gate energies MG0–MG8 ──
MOVG_COLORS = plt.cm.turbo(np.linspace(0.08, 0.92, MAX_GATES))
movg_lines  = []
for i in range(MAX_GATES):
    ln, = ax_movg.plot(x_data, [0]*HISTORY,
                       color=MOVG_COLORS[i], lw=1.2,
                       label=f&amp;#39;G{i} ({i*GATE_DIST_M:.2f}m)&amp;#39;)
    movg_lines.append(ln)
ax_movg.legend(fontsize=6.5, loc=&amp;#39;upper left&amp;#39;, framealpha=0.35, ncol=5)

# ── Static gate energies SG3–SG8 ──
STAG_COLORS = plt.cm.cool(np.linspace(0.15, 0.95, 6))
stag_lines  = []
for j, i in enumerate(range(3, 9)):
    ln, = ax_stag.plot(x_data, [0]*HISTORY,
                       color=STAG_COLORS[j], lw=1.2,
                       label=f&amp;#39;SG{i} ({i*GATE_DIST_M:.2f}m)&amp;#39;)
    stag_lines.append(ln)
ax_stag.legend(fontsize=6.5, loc=&amp;#39;upper left&amp;#39;, framealpha=0.35, ncol=3)

# ── Light &amp;amp; OutPin ──
line_light,  = ax_misc.plot(x_data, [0]*HISTORY, color=&amp;#39;#ffee33&amp;#39;, lw=1.3, label=&amp;#39;Light Level&amp;#39;)
line_outpin, = ax_misc.plot(x_data, [0]*HISTORY, color=&amp;#39;#33ffaa&amp;#39;, lw=1.6, ls=&amp;#39;--&amp;#39;, label=&amp;#39;OUT Pin (Occupied=100)&amp;#39;)
ax_misc.set_ylim(0, 260)
ax_misc.legend(fontsize=7.5, loc=&amp;#39;upper left&amp;#39;, framealpha=0.35)

# Inset horizontal snapshot bar chart for moving gates
bar_ax = ax_movg.inset_axes([0.91, 0.05, 0.08, 0.90])
bar_ax.set_xlim(0, 105)
bar_ax.set_ylim(-0.5, MAX_GATES - 0.5)
bar_ax.set_yticks(range(MAX_GATES))
bar_ax.set_yticklabels([f&amp;#39;G{i}&amp;#39; for i in range(MAX_GATES)], fontsize=6)
bar_ax.set_xticks([])
bar_ax.set_title(&amp;#39;Live G0-8&amp;#39;, fontsize=6.5, pad=2, color=&amp;#39;#cccccc&amp;#39; if DARK_BG else &amp;#39;#333333&amp;#39;)
bar_ax.invert_yaxis()
if DARK_BG: bar_ax.set_facecolor(&amp;#39;#1c1c1c&amp;#39;)
bars = bar_ax.barh(range(MAX_GATES), [0]*MAX_GATES, color=MOVG_COLORS, height=0.65)

# Top status header text
status_txt = fig.text(0.5, 0.965, &amp;#39;Connecting…&amp;#39;, ha=&amp;#39;center&amp;#39;, va=&amp;#39;top&amp;#39;,
                      fontsize=10, fontweight=&amp;#39;bold&amp;#39;,
                      color=&amp;#39;#aaffaa&amp;#39; if DARK_BG else &amp;#39;#008800&amp;#39;)

# Global background reader
reader = None

# Bottom interactive Slider for live Breath Baseline Noise Floor adjustment
slider_ax = fig.add_axes([0.22, 0.015, 0.56, 0.024], facecolor=&amp;#39;#202020&amp;#39; if DARK_BG else &amp;#39;#e8e8e8&amp;#39;)
baseline_slider = Slider(
    slider_ax, &amp;#39;Breath Baseline (Noise Floor):&amp;#39;,
    0.0, 70.0, valinit=SAMPLE_BASELINE, valstep=1.0,
    color=&amp;#39;#00ffcc&amp;#39;,
    initcolor=&amp;#39;none&amp;#39;,
    track_color=&amp;#39;#141414&amp;#39; if DARK_BG else &amp;#39;#cccccc&amp;#39;
)
baseline_slider.label.set_color(&amp;#39;#dddddd&amp;#39; if DARK_BG else &amp;#39;#222222&amp;#39;)
baseline_slider.label.set_fontsize(8.5)
baseline_slider.label.set_fontweight(&amp;#39;bold&amp;#39;)
baseline_slider.valtext.set_color(&amp;#39;#00ffcc&amp;#39;)
baseline_slider.valtext.set_fontsize(8.5)
baseline_slider.valtext.set_fontweight(&amp;#39;bold&amp;#39;)

def on_baseline_slider(val):
    if reader and reader.breath_counter:
        reader.breath_counter.peak_threshold = float(val)
    line_baseline.set_ydata([val, val])
    line_baseline.set_label(f&amp;#39;Baseline ({val:.0f})&amp;#39;)
    ax_moven.legend(fontsize=7.5, loc=&amp;#39;upper left&amp;#39;, framealpha=0.35)
    fig.canvas.draw_idle()

baseline_slider.on_changed(on_baseline_slider)

# ─────────────────────── Animation Update ─────────────────────

def update(_frame):
    global bar_state

    with reader.lock:
        data = list(reader.buf)
        b_flags = list(reader.breath_flags)
        latest = list(reader.latest)
        b_status = reader.breath_counter.get_status_summary()

    state  = int(latest[COL_STATE]) if latest else 0
    slabel = STATE_LABELS.get(state, &amp;#39;Unknown&amp;#39;)
    b_cnt  = b_status[&amp;#39;count&amp;#39;]
    b_st   = b_status[&amp;#39;state&amp;#39;]

    # Update top status text
    status_txt.set_text(
        f&amp;quot;State: {slabel}  │  &amp;quot;
        f&amp;quot;[Breath] Count: {b_cnt} [{b_st}]  │  &amp;quot;
        f&amp;quot;Moving: {latest[COL_MOVDIST]:.0f}cm (E:{latest[COL_MOVEN]:.0f})  │  &amp;quot;
        f&amp;quot;Static: {latest[COL_STADIST]:.0f}cm  │  &amp;quot;
        f&amp;quot;Detect: {latest[COL_DETDIST]:.0f}cm  │  &amp;quot;
        f&amp;quot;OUT: {&amp;#39;■ OCCUPIED&amp;#39; if latest[COL_OUTPIN] else &amp;#39;□ Empty&amp;#39;}&amp;quot;
    )
    status_txt.set_color(STATE_COLORS.get(state, &amp;#39;#aaaaaa&amp;#39;) if reader.connected else &amp;#39;#ff4444&amp;#39;)

    # Update breath HUD badge on ax_moven
    if b_st == BreathCounter.STATE_WAITING:
        pct = int(b_status[&amp;#39;trigger_progress&amp;#39;] * 100)
        breath_hud.set_text(f&amp;quot;[Breath] WAITING TRIGGER (Moving Energy &amp;gt;= 100 for 3s): {pct}%\nBreaths: {b_cnt}&amp;quot;)
        breath_hud.set_color(&amp;#39;#ffaa00&amp;#39;)
        breath_hud.get_bbox_patch().set_edgecolor(&amp;#39;#ffaa00&amp;#39;)
    elif b_st == BreathCounter.STATE_ACTIVE:
        stop_pct = int(b_status[&amp;#39;stop_progress&amp;#39;] * 100)
        stop_hint = f&amp;quot; │ Stop E=100: {stop_pct}%&amp;quot; if stop_pct &amp;gt; 0 else &amp;quot;&amp;quot;
        bpm_str = f&amp;quot; │ Rate: {b_status[&amp;#39;bpm&amp;#39;]:.0f} BPM&amp;quot; if b_status.get(&amp;#39;bpm&amp;#39;, 0) &amp;gt; 0 else &amp;quot;&amp;quot;
        cur_base = b_status.get(&amp;#39;peak_threshold&amp;#39;, SAMPLE_BASELINE)
        breath_hud.set_text(
            f&amp;quot;[Breath] COUNT: {b_cnt}{bpm_str}  [ACTIVE]\n&amp;quot;
            f&amp;quot;Silence: {b_status[&amp;#39;zero_count&amp;#39;]}z (req &amp;gt;= 25z) │ Last Gap: {b_status[&amp;#39;last_interval&amp;#39;]}z │ Base: {cur_base:.0f}{stop_hint}&amp;quot;
        )
        breath_hud.set_color(&amp;#39;#00ffcc&amp;#39;)
        breath_hud.get_bbox_patch().set_edgecolor(&amp;#39;#00ffcc&amp;#39;)
    elif b_st == BreathCounter.STATE_STOPPED:
        breath_hud.set_text(
            f&amp;quot;[Breath] SESSION STOPPED (Constant 100 for 3s)\n&amp;quot;
            f&amp;quot;FINAL BREATH COUNT: {b_cnt}  │  Press [B] to Reset / Re-arm&amp;quot;
        )
        breath_hud.set_color(&amp;#39;#ff5555&amp;#39;)
        breath_hud.get_bbox_patch().set_edgecolor(&amp;#39;#ff5555&amp;#39;)

    if not data:
        return

    n = len(data)
    arr = np.array(data)
    pad = HISTORY - n

    def padded(col_idx):
        return [0.0]*pad + arr[:, col_idx].tolist()

    # 1. Distances with adaptive Y-axis
    d_mov = padded(COL_MOVDIST)
    d_sta = padded(COL_STADIST)
    d_det = padded(COL_DETDIST)
    line_movdist.set_ydata(d_mov)
    line_stadist.set_ydata(d_sta)
    line_detdist.set_ydata(d_det)

    max_dist = max(arr[:, [COL_MOVDIST, COL_STADIST, COL_DETDIST]].max(), 50)
    ax_dist.set_ylim(0, max(250, max_dist * 1.15))

    # 2. Motion Energy &amp;amp; State fill &amp;amp; Breath markers
    mov_energies = padded(COL_MOVEN)
    line_moven.set_ydata(mov_energies)
    bar_state.remove()
    state_scaled = [v * 25 for v in padded(COL_STATE)]
    bar_state = ax_moven.fill_between(x_data, 0, state_scaled, alpha=0.18, color=&amp;#39;#00aaff&amp;#39;)

    padded_flags = [False] * pad + b_flags
    b_indices = [idx for idx, flg in enumerate(padded_flags) if flg]
    b_vals = [mov_energies[idx] for idx in b_indices]
    line_breaths.set_data(b_indices, b_vals)

    # 3. Moving Gate Energies MG0–MG8
    for i, ln in enumerate(movg_lines):
        ln.set_ydata(padded(COL_MG_START + i))

    if n &amp;gt; 0:
        snap = arr[-1, COL_MG_START:COL_MG_START+MAX_GATES]
        for bar, val in zip(bars, snap):
            bar.set_width(val)

    # 4. Static Gate Energies SG3–SG8
    for j, ln in enumerate(stag_lines):
        ln.set_ydata(padded(COL_SG_START + j))

    # 5. Light &amp;amp; OUT Pin
    line_light.set_ydata(padded(COL_LIGHT))
    outpin_scaled = [v * 100 for v in padded(COL_OUTPIN)]
    line_outpin.set_ydata(outpin_scaled)

# ─────────────────────── Keyboard Handler ─────────────────────

def on_key(event):
    global reader
    if not event.key:
        return

    k = event.key

    # Live baseline threshold adjustment
    if k in (&amp;#39;+&amp;#39;, &amp;#39;=&amp;#39;, &amp;#39;up&amp;#39;):
        new_val = min(70.0, baseline_slider.val + 1.0)
        baseline_slider.set_val(new_val)
        print(f&amp;quot;[BASELINE] Increased to {new_val:.0f}&amp;quot;)
        return
    elif k in (&amp;#39;-&amp;#39;, &amp;#39;_&amp;#39;, &amp;#39;down&amp;#39;):
        new_val = max(0.0, baseline_slider.val - 1.0)
        baseline_slider.set_val(new_val)
        print(f&amp;quot;[BASELINE] Decreased to {new_val:.0f}&amp;quot;)
        return

    # Reset / Re-arm breath counter
    if k in (&amp;#39;b&amp;#39;, &amp;#39;B&amp;#39;):
        reader.breath_counter.reset()
        with reader.lock:
            reader.breath_flags.clear()
            reader.breath_flags.extend([False] * len(reader.buf))
        return

    # Relay commands directly to ESP32
    if k in (&amp;#39;n&amp;#39;, &amp;#39;x&amp;#39;, &amp;#39;1&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;3&amp;#39;, &amp;#39;4&amp;#39;, &amp;#39;5&amp;#39;, &amp;#39;v&amp;#39;, &amp;#39;p&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;H&amp;#39;):
        reader.send(k)
        print(f&amp;quot;[CMD] Sent &amp;#39;{k}&amp;#39; to ESP32&amp;quot;)
    elif k in (&amp;#39;q&amp;#39;, &amp;#39;escape&amp;#39;):
        print(&amp;quot;[EXIT] Closing window...&amp;quot;)
        plt.close(fig)

fig.canvas.mpl_connect(&amp;#39;key_press_event&amp;#39;, on_key)

# ─────────────────────── Main Entry ───────────────────────────

def main():
    global reader

    parser = argparse.ArgumentParser(description=&amp;#39;HLK-LD2410 Live Plotter &amp;amp; Breath Counter (Algorithm 1)&amp;#39;)
    parser.add_argument(&amp;#39;port&amp;#39;, nargs=&amp;#39;?&amp;#39;, default=None,
                        help=&amp;#39;Serial port (e.g. COM3 or /dev/ttyUSB0)&amp;#39;)
    parser.add_argument(&amp;#39;--baud&amp;#39;, type=int, default=BAUD_RATE,
                        help=f&amp;#39;Baud rate (default {BAUD_RATE})&amp;#39;)
    parser.add_argument(&amp;#39;--auto-start&amp;#39;, action=&amp;#39;store_true&amp;#39;,
                        help=&amp;#39;Send &amp;quot;n&amp;quot; without waiting for manual console Enter&amp;#39;)
    parser.add_argument(&amp;#39;--trigger-sec&amp;#39;, type=float, default=TRIGGER_DURATION_SEC,
                        help=f&amp;#39;Seconds of moving energy &amp;gt;= 100 to start breath counting (default: {TRIGGER_DURATION_SEC})&amp;#39;)
    parser.add_argument(&amp;#39;--stop-sec&amp;#39;, type=float, default=STOP_DURATION_SEC,
                        help=f&amp;#39;Seconds of constant 100 moving energy to stop breath counting (default: {STOP_DURATION_SEC})&amp;#39;)
    parser.add_argument(&amp;#39;--min-zeros&amp;#39;, type=int, default=MIN_ZERO_GAP,
                        help=f&amp;#39;Minimum consecutive zero values between peaks (default: {MIN_ZERO_GAP})&amp;#39;)
    parser.add_argument(&amp;#39;--peak-thresh&amp;#39;, type=float, default=SAMPLE_BASELINE,
                        help=f&amp;#39;Minimum moving energy noise floor / baseline (default: {SAMPLE_BASELINE})&amp;#39;)
    args = parser.parse_args()

    port = args.port or find_esp32_port()
    if not port:
        print(&amp;quot;ERROR: No serial port detected. Connect the ESP32 or specify port (e.g. COM3).&amp;quot;)
        print(&amp;quot;Available ports:&amp;quot;, [p.device for p in serial.tools.list_ports.comports()])
        sys.exit(1)

    print(&amp;quot;\n&amp;quot; + &amp;quot;=&amp;quot; * 65)
    print(&amp;quot;   HLK-LD2410 mmWave Radar Plotter &amp;amp; Breath Counter (Alg 1)&amp;quot;)
    print(&amp;quot;=&amp;quot; * 65)
    print(f&amp;quot;Connecting to {port} @ {args.baud} baud...&amp;quot;)

    try:
        ser = serial.Serial(port, args.baud, timeout=0.5)
    except Exception as e:
        print(f&amp;quot;Failed to open port {port}: {e}&amp;quot;)
        sys.exit(1)

    # Discard any stale bootloader garbage in serial buffer
    time.sleep(1.0)
    ser.reset_input_buffer()

    # Read and print any initial startup messages from ESP32
    deadline = time.time() + 1.5
    print(&amp;quot;\n[ESP32 Startup Messages]:&amp;quot;)
    while time.time() &amp;lt; deadline:
        if ser.in_waiting:
            line = ser.readline().decode(&amp;#39;ascii&amp;#39;, errors=&amp;#39;ignore&amp;#39;).strip()
            if line:
                print(f&amp;quot;  {line}&amp;quot;)

    # Prompt user in console to send &amp;#39;n&amp;#39;
    if not args.auto_start:
        print(&amp;quot;\n&amp;quot; + &amp;quot;-&amp;quot; * 65)
        print(&amp;quot; [READY] The ESP32 is waiting for the start command &amp;#39;n&amp;#39;.&amp;quot;)
        print(&amp;quot; Press [ENTER] or type &amp;#39;n&amp;#39; to begin streaming radar data:&amp;quot;)
        print(&amp;quot;-&amp;quot; * 65)
        try:
            input(&amp;quot;&amp;gt;&amp;gt;&amp;gt; &amp;quot;)
        except (KeyboardInterrupt, EOFError):
            ser.close()
            sys.exit(0)

    # Send &amp;#39;n&amp;#39; to start streaming
    print(&amp;quot;\nSending &amp;#39;n&amp;#39; command to ESP32...&amp;quot;)
    ser.write(b&amp;#39;n\n&amp;#39;)
    ser.flush()

    # Verify that data has actually started flowing
    print(&amp;quot;Verifying data stream from ESP32...&amp;quot;)
    data_confirmed = False
    verify_deadline = time.time() + 5.0
    while time.time() &amp;lt; verify_deadline:
        if ser.in_waiting:
            line = ser.readline().decode(&amp;#39;ascii&amp;#39;, errors=&amp;#39;ignore&amp;#39;).strip()
            if line:
                if line.startswith(&amp;#39;#&amp;#39;):
                    print(f&amp;quot;  [ESP32] {line}&amp;quot;)
                elif line[0].isdigit():
                    parts = line.split(&amp;#39;\t&amp;#39;) if &amp;#39;\t&amp;#39; in line else line.split(&amp;#39;,&amp;#39;)
                    if len(parts) == TOTAL_COLS:
                        data_confirmed = True
                        print(f&amp;quot;  [OK] Valid data frame received ({TOTAL_COLS} columns)!&amp;quot;)
                        break

    if not data_confirmed:
        print(&amp;quot;\n[WARNING] Did not receive valid data frame yet, but launching plot window anyway.&amp;quot;)
        print(&amp;quot;If graph is empty, press &amp;#39;n&amp;#39; inside the plot window to resend start command.&amp;quot;)
    else:
        print(&amp;quot;\n[SUCCESS] Radar streaming active! Launching live graph window...\n&amp;quot;)

    print(&amp;quot;Keyboard shortcuts in Plot Window:&amp;quot;)
    print(&amp;quot;  [+] / [UP]        : Increase Breath Baseline Noise Floor (+1)&amp;quot;)
    print(&amp;quot;  [-] / [DOWN]      : Decrease Breath Baseline Noise Floor (-1)&amp;quot;)
    print(&amp;quot;  [Slider]          : Drag &amp;#39;Baseline&amp;#39; slider at bottom of window&amp;quot;)
    print(&amp;quot;  [b]               : Reset / re-arm Breath Counter&amp;quot;)
    print(&amp;quot;  [n]               : Start / Resume streaming&amp;quot;)
    print(&amp;quot;  [x]               : Pause streaming&amp;quot;)
    print(&amp;quot;  [1] - [5]         : Set sensitivity presets (1=5/5 ... 5=75/75)&amp;quot;)
    print(&amp;quot;  [v]               : Read firmware version&amp;quot;)
    print(&amp;quot;  [p]               : Read radar parameters&amp;quot;)
    print(&amp;quot;  [q] or [ESC]      : Quit\n&amp;quot;)

    # Sync baseline slider with user args
    if baseline_slider.val != args.peak_thresh:
        baseline_slider.set_val(args.peak_thresh)

    # Initialize BreathCounter (Algorithm 1) and background reader
    breath_counter = BreathCounter(
        trigger_duration=args.trigger_sec,
        stop_duration=args.stop_sec,
        min_zero_gap=args.min_zeros,
        peak_threshold=args.peak_thresh
    )
    reader = RadarReader(ser, breath_counter=breath_counter)
    reader.start()

    # Start matplotlib animation
    ani = animation.FuncAnimation(
        fig, update,
        interval=UPDATE_MS,
        blit=False,
        cache_frame_data=False
    )

    try:
        plt.show()
    finally:
        reader.stop()
        if ser.is_open:
            ser.close()

if __name__ == &amp;#39;__main__&amp;#39;:
    main()
&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;As it is fairly long it won&amp;#39;t be feasible to explain it all so I will be explaining it in short. This is in Python and it&amp;#39;s also good in that, on the Linux side, I can use it with some modification.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;The clock&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;The ESP32 prints one row every 50 ms, so the sample rate is 20 Hz and each sample is &amp;Delta;t = 0.05 s. The Python side works in samples, so converting between samples and seconds is the maths you&amp;rsquo;ll use most:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;time = samples &amp;times; 0.05 s        samples = time &amp;times; 20&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 1: the start signal (arming)&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;The counter sits in WAITING until E &amp;ge; 100 continuously for 3 s. That&amp;rsquo;s 3 &amp;times; 20 = 60 consecutive samples at 100. In practice you wave your hand in front of the sensor, which saturates the energy. If E drops below 100 even once, the timer resets. When the 3 s is met, it enters COUNTING with count = 0. The idea is that you tell the system &amp;ldquo;I&amp;rsquo;m now lying still, start counting&amp;rdquo; without touching the PC.&lt;/p&gt;
&lt;p dir="ltr"&gt;One detail: right after arming, &lt;code dir="ltr"&gt;waiting_to_clear_trigger&lt;/code&gt; stays true until E drops below 100. Without it, your starting wave would immediately look like a stop signal.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 2: turning energy into silence and motion&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;This is the core of it. Pick a baseline B (default 15, adjustable with the slider). Every sample is classified as:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;E[k] &amp;gt; B   &amp;rarr; motion
E[k] &amp;le; B   &amp;rarr; silence&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;A running counter z tracks how many silent samples in a row you&amp;rsquo;ve seen. Any motion sample resets it to 0, and any silent sample adds 1.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 3: counting a breath&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;A new breath is counted when two things are true at once:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;E[k] &amp;gt; B      (motion just appeared)
z &amp;ge; G         (it was preceded by at least G silent samples)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;G is &lt;code dir="ltr"&gt;MIN_ZERO_GAP&lt;/code&gt;. After a count, an &lt;code dir="ltr"&gt;in_breath&lt;/code&gt; flag stays on until a long enough silence passes, so one breath that wobbles up and down doesn&amp;rsquo;t count twice. In words: a breath is a burst of motion that comes after a proper pause.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 4: the rate&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;When a breath is counted, the code measures the time since the previous one, &amp;Delta;t_b, and ignores it unless 1 s &amp;le; &amp;Delta;t_b &amp;le; 15 s:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;BPM = 60 / &amp;Delta;t_b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;For example, a breath every 4 s gives 60/4 = 15 BPM, which is a normal resting rate. A period of 4 s is 80 samples, so a normal breath is roughly 80 samples long and the silent gap is a fraction of that.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 5: the stop signal&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;Wave again until E &amp;ge; 100 for 3 s and the state flips to STOPPED, freezing the final count. If you hold 100 for 3 s again, it re-arms and starts a fresh session. While E &amp;ge; 100 inside a session, samples are not counted as breaths, so the stop wave isn&amp;rsquo;t counted as breathing.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&amp;nbsp;The BPM and SPO2 Sensor ( MAXREFDES117)&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/umQqjyehjoFMeiPdtvS6jcXo_2D00_500x500.jpg" /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;em&gt;It is fairly tiny compared to how it looks here.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;The process of using this was fairly easy as they provide all the resources and the design files. I just needed to alter some specifications, like the pins for the I2C communication, according to my need and I am also testing this on the ESP32. For simplicity I had removed the other part of the original code so it includes some kind of adafruit, things that I don&amp;#39;t need, so I had removed.&amp;nbsp;Also the way it works is quite simple. Firstly there are two LEDs: one is IR and one is red. They emit light and there is also a sensor to detect them. The light that gets reflected back from the object, or your finger, or the skin, by that reflection, we measure the SpO2 and the BPM.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;This is the sketch I used with the algorithm. I had just modified it a little bit from the original code I got from the design files.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;Arduino.h&amp;gt;
#include &amp;quot;algorithm.h&amp;quot;
#include &amp;quot;max30102.h&amp;quot;
#include &amp;lt;Wire.h&amp;gt;

#define INT_PIN 4
#define LED_PIN 2

uint32_t aun_ir_buffer[100]; //infrared LED sensor data
uint32_t aun_red_buffer[100];  //red LED sensor data
int32_t n_ir_buffer_length; //data length
int32_t n_spo2;  //SPO2 value
int8_t ch_spo2_valid;  //indicator to show if the SPO2 calculation is valid
int32_t n_heart_rate; //heart rate value
int8_t  ch_hr_valid;  //indicator to show if the heart rate calculation is valid
uint8_t uch_dummy;


// the setup routine runs once when you press reset:
void setup() {
  Wire.begin();
  maxim_max30102_reset(); //resets the MAX30102
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  pinMode(INT_PIN, INPUT);  //pin connects to the interrupt output pin of the MAX30102
  pinMode(LED_PIN, OUTPUT);
  delay(1000);
  maxim_max30102_read_reg(REG_INTR_STATUS_1,&amp;amp;uch_dummy);  //Reads/clears the interrupt status register
  while(Serial.available()==0)  //wait until user presses a key
  {
    Serial.write(27);       // ESC command
    Serial.print(F(&amp;quot;[2J&amp;quot;));    // clear screen command
    Serial.println(F(&amp;quot;ESP32&amp;quot;));
    Serial.println(F(&amp;quot;Press any key to start conversion&amp;quot;));
    delay(1000);
  }
  uch_dummy=Serial.read();
  maxim_max30102_init();  //initialize the MAX30102
}

// the loop routine runs over and over again forever:
void loop() {
  int32_t i;
  
  n_ir_buffer_length=100;  //buffer length of 100 stores 4 seconds of samples running at 25sps

  //read the first 100 samples, and determine the signal range
  for(i=0;i&amp;lt;n_ir_buffer_length;i++)
  {
    while(digitalRead(INT_PIN)==1);  //wait until the interrupt pin asserts
    maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));  //read from MAX30102 FIFO
    
    Serial.print(F(&amp;quot;red=&amp;quot;));
    Serial.print(aun_red_buffer[i], DEC);
    Serial.print(F(&amp;quot;, ir=&amp;quot;));
    Serial.println(aun_ir_buffer[i], DEC);
  }
  //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
  maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &amp;amp;n_spo2, &amp;amp;ch_spo2_valid, &amp;amp;n_heart_rate, &amp;amp;ch_hr_valid); 

  //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
  while(1)
  {
    i=0;

    //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
    for(i=25;i&amp;lt;100;i++)
    {
      aun_red_buffer[i-25]=aun_red_buffer[i];
      aun_ir_buffer[i-25]=aun_ir_buffer[i];
    }

    //take 25 sets of samples before calculating the heart rate.
    for(i=75;i&amp;lt;100;i++)
    {
      while(digitalRead(INT_PIN)==1);
      digitalWrite(LED_PIN, !digitalRead(LED_PIN));
      maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));

      //send samples and calculation result to terminal program through UART
      Serial.print(F(&amp;quot;red=&amp;quot;));
      Serial.print(aun_red_buffer[i], DEC);
      Serial.print(F(&amp;quot;, ir=&amp;quot;));
      Serial.print(aun_ir_buffer[i], DEC);
      
      Serial.print(F(&amp;quot;, HR=&amp;quot;));
      Serial.print(n_heart_rate, DEC);
      
      Serial.print(F(&amp;quot;, HRvalid=&amp;quot;));
      Serial.print(ch_hr_valid, DEC);
      
      Serial.print(F(&amp;quot;, SPO2=&amp;quot;));
      Serial.print(n_spo2, DEC);

      Serial.print(F(&amp;quot;, SPO2Valid=&amp;quot;));
      Serial.println(ch_spo2_valid, DEC);
    }
    maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &amp;amp;n_spo2, &amp;amp;ch_spo2_valid, &amp;amp;n_heart_rate, &amp;amp;ch_hr_valid); 
  }
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;Think of this sketch as a &lt;strong&gt;sliding 4-second window&lt;/strong&gt; that the Maxim algorithm re-analyses every second. The sensor shines red and infrared light into your finger, and the sketch looks at how much light comes back. Each heartbeat pushes a little blood into the finger, which absorbs a little more light, so the signal pulses with your pulse. The code collects that wiggle, and the library function &lt;code dir="ltr"&gt;maxim_heart_rate_and_oxygen_saturation()&lt;/code&gt; turns it into HR and SpO2. (You called it DS117; the board is the MAXREFDES117#, which uses the MAX30102.)&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;The clock&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;The sensor is set up in &lt;code dir="ltr"&gt;maxim_max30102_init()&lt;/code&gt; to run at 100 samples/s with 4-sample averaging, which gives an effective rate of 25 samples/s. So:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;&amp;Delta;t = 1/25 = 0.04 s per sample
buffer = 100 samples = 4 s
slide  = 25 samples  = 1 s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;The &lt;code dir="ltr"&gt;while(digitalRead(INT_PIN)==1);&lt;/code&gt; line waits for the sensor&amp;rsquo;s interrupt pin (active low) to say &amp;ldquo;a new sample is ready&amp;rdquo;, then &lt;code dir="ltr"&gt;maxim_max30102_read_fifo()&lt;/code&gt; reads one red and one IR value.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;The sliding window&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;First, 100 samples are collected, which is the 4 s warm-up with no valid reading. After that the loop repeats forever:&lt;/p&gt;
&lt;ol dir="ltr"&gt;
&lt;li&gt;Shift the last 75 samples to the front, dropping the oldest 25.&lt;/li&gt;
&lt;li&gt;Read 25 fresh samples (1 s) into the end.&lt;/li&gt;
&lt;li&gt;Recompute HR and SpO2 on all 100.&lt;/li&gt;
&lt;/ol&gt;
&lt;p dir="ltr"&gt;Consecutive windows overlap by 75%, so the answer updates every second but is always based on the last 4 s. That is why the numbers feel stable but lag a little.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;How the library finds heart rate&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;Inside the function, the IR signal goes through four steps.&lt;/p&gt;
&lt;ol dir="ltr"&gt;
&lt;li&gt;Remove the DC part and flip the sign, so the signal is centred on zero and the pulses become peaks:&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;   x[k] = -(IR[k] - mean(IR))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ol dir="ltr" start="2"&gt;
&lt;li&gt;Smooth it with a 4-point moving average, so sensor noise doesn&amp;rsquo;t create fake peaks.&lt;/li&gt;
&lt;li&gt;Find peaks that are above a threshold (the signal mean, clamped to a range of about 30&amp;ndash;60) and at least 4 samples apart.&lt;/li&gt;
&lt;li&gt;Average the gaps between peaks:&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;   T = (sum of peak gaps) / (number of peaks &amp;minus; 1)    [in samples]
   HR = 25 &amp;times; 60 / T = 1500 / T&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;For example, if peaks are on average 20 samples apart, that is 0.8 s per beat, so HR = 1500/20 = 75 bpm. With fewer than two peaks it can&amp;rsquo;t compute a gap and sets &lt;code dir="ltr"&gt;HRvalid = 0&lt;/code&gt;.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;How it finds SpO2&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;Oxygenated and deoxygenated blood absorb red and IR light differently. For each beat, the function measures the pulsing part (AC) and the steady part (DC) of both channels and forms the &amp;ldquo;ratio of ratios&amp;rdquo;:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;R = (AC_red / DC_red) / (AC_ir / DC_ir)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;It takes the median R across the beats in the window and maps it to a percentage with Maxim&amp;rsquo;s empirical calibration curve, roughly:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;SpO2 &amp;asymp; &amp;minus;45.06&amp;middot;R&amp;sup2; + 30.354&amp;middot;R + 94.845&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;So R &amp;asymp; 0.5 gives about 99%, and R &amp;asymp; 1 gives about 80%. If R falls outside the plausible range, &lt;code dir="ltr"&gt;SpO2Valid = 0&lt;/code&gt;. That flag matters for your project: never feed a reading into the sleep-stage logic unless its valid flag is 1.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;What gets printed&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;Every sample prints &lt;code dir="ltr"&gt;red&lt;/code&gt;, &lt;code dir="ltr"&gt;ir&lt;/code&gt;, &lt;code dir="ltr"&gt;HR&lt;/code&gt;, &lt;code dir="ltr"&gt;HRvalid&lt;/code&gt;, &lt;code dir="ltr"&gt;SPO2&lt;/code&gt; and &lt;code dir="ltr"&gt;SPO2Valid&lt;/code&gt;. Because HR and SpO2 are only recomputed once per second, the same values repeat on 25 consecutive lines, and then they jump. The LED on pin 2 toggles per sample as a &amp;ldquo;loop is alive&amp;rdquo; blink.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:150%;"&gt;The Algorithm&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;It was going to be the most difficult part but it was fairly easy for me, as the developers of this have already given that in the design files. It was going to be the most difficult because we are just getting the IR and red LED readings for the detection of the emitted and reflected-back light. We have just those and we have detected the SpO2 and the BPM from this. It was going to be difficult but thankfully it doesn&amp;#39;t.&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;algorithm.h&amp;quot;
#include &amp;quot;arduino.h&amp;quot;

#if defined(ARDUINO_AVR_UNO)
//Arduino Uno doesn&amp;#39;t have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
//To solve this problem, 16-bit MSB of the sampled data will be truncated.  Samples become 16-bit data.
void maxim_heart_rate_and_oxygen_saturation(uint16_t *pun_ir_buffer, int32_t n_ir_buffer_length, uint16_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid, 
                int32_t *pn_heart_rate, int8_t *pch_hr_valid)
#else
void maxim_heart_rate_and_oxygen_saturation(uint32_t *pun_ir_buffer, int32_t n_ir_buffer_length, uint32_t *pun_red_buffer, int32_t *pn_spo2, int8_t *pch_spo2_valid, 
                int32_t *pn_heart_rate, int8_t *pch_hr_valid)
#endif
/**
* \brief        Calculate the heart rate and SpO2 level
* \par          Details
*               By detecting  peaks of PPG cycle and corresponding AC/DC of red/infra-red signal, the an_ratio for the SPO2 is computed.
*               Since this algorithm is aiming for Arm M0/M3. formaula for SPO2 did not achieve the accuracy due to register overflow.
*               Thus, accurate SPO2 is precalculated and save longo uch_spo2_table[] per each an_ratio.
*
* \param[in]    *pun_ir_buffer           - IR sensor data buffer
* \param[in]    n_ir_buffer_length      - IR sensor data buffer length
* \param[in]    *pun_red_buffer          - Red sensor data buffer
* \param[out]    *pn_spo2                - Calculated SpO2 value
* \param[out]    *pch_spo2_valid         - 1 if the calculated SpO2 value is valid
* \param[out]    *pn_heart_rate          - Calculated heart rate value
* \param[out]    *pch_hr_valid           - 1 if the calculated heart rate value is valid
*
* \retval       None
*/
{
  uint32_t un_ir_mean,un_only_once ;
  int32_t k, n_i_ratio_count;
  int32_t i, s, m, n_exact_ir_valley_locs_count, n_middle_idx;
  int32_t n_th1, n_npks, n_c_min;   
  int32_t an_ir_valley_locs[15] ;
  int32_t n_peak_interval_sum;
  
  int32_t n_y_ac, n_x_ac;
  int32_t n_spo2_calc; 
  int32_t n_y_dc_max, n_x_dc_max; 
  int32_t n_y_dc_max_idx, n_x_dc_max_idx; 
  int32_t an_ratio[5], n_ratio_average; 
  int32_t n_nume, n_denom ;

  // calculates DC mean and subtract DC from ir
  un_ir_mean =0; 
  for (k=0 ; k&amp;lt;n_ir_buffer_length ; k++ ) un_ir_mean += pun_ir_buffer[k] ;
  un_ir_mean =un_ir_mean/n_ir_buffer_length ;
    
  // remove DC and invert signal so that we can use peak detector as valley detector
  for (k=0 ; k&amp;lt;n_ir_buffer_length ; k++ )  
    an_x[k] = -1*(pun_ir_buffer[k] - un_ir_mean) ; 
    
  // 4 pt Moving Average
  for(k=0; k&amp;lt; BUFFER_SIZE-MA4_SIZE; k++){
    an_x[k]=( an_x[k]+an_x[k+1]+ an_x[k+2]+ an_x[k+3])/(int)4;        
  }
  // calculate threshold  
  n_th1=0; 
  for ( k=0 ; k&amp;lt;BUFFER_SIZE ;k++){
    n_th1 +=  an_x[k];
  }
  n_th1=  n_th1/ ( BUFFER_SIZE);
  if( n_th1&amp;lt;30) n_th1=30; // min allowed
  if( n_th1&amp;gt;60) n_th1=60; // max allowed

  for ( k=0 ; k&amp;lt;15;k++) an_ir_valley_locs[k]=0;
  // since we flipped signal, we use peak detector as valley detector
  maxim_find_peaks( an_ir_valley_locs, &amp;amp;n_npks, an_x, BUFFER_SIZE, n_th1, 4, 15 );//peak_height, peak_distance, max_num_peaks 
  n_peak_interval_sum =0;
  if (n_npks&amp;gt;=2){
    for (k=1; k&amp;lt;n_npks; k++) n_peak_interval_sum += (an_ir_valley_locs[k] -an_ir_valley_locs[k -1] ) ;
    n_peak_interval_sum =n_peak_interval_sum/(n_npks-1);
    *pn_heart_rate =(int32_t)( (FS*60)/ n_peak_interval_sum );
    *pch_hr_valid  = 1;
  }
  else  { 
    *pn_heart_rate = -999; // unable to calculate because # of peaks are too small
    *pch_hr_valid  = 0;
  }

  //  load raw value again for SPO2 calculation : RED(=y) and IR(=X)
  for (k=0 ; k&amp;lt;n_ir_buffer_length ; k++ )  {
      an_x[k] =  pun_ir_buffer[k] ; 
      an_y[k] =  pun_red_buffer[k] ; 
  }

  // find precise min near an_ir_valley_locs
  n_exact_ir_valley_locs_count =n_npks; 
  
  //using exact_ir_valley_locs , find ir-red DC andir-red AC for SPO2 calibration an_ratio
  //finding AC/DC maximum of raw

  n_ratio_average =0; 
  n_i_ratio_count = 0; 
  for(k=0; k&amp;lt; 5; k++) an_ratio[k]=0;
  for (k=0; k&amp;lt; n_exact_ir_valley_locs_count; k++){
    if (an_ir_valley_locs[k] &amp;gt; BUFFER_SIZE ){
      *pn_spo2 =  -999 ; // do not use SPO2 since valley loc is out of range
      *pch_spo2_valid  = 0; 
      return;
    }
  }
  // find max between two valley locations 
  // and use an_ratio betwen AC compoent of Ir &amp;amp; Red and DC compoent of Ir &amp;amp; Red for SPO2 
  for (k=0; k&amp;lt; n_exact_ir_valley_locs_count-1; k++){
    n_y_dc_max= -16777216 ; 
    n_x_dc_max= -16777216; 
    if (an_ir_valley_locs[k+1]-an_ir_valley_locs[k] &amp;gt;3){
        for (i=an_ir_valley_locs[k]; i&amp;lt; an_ir_valley_locs[k+1]; i++){
          if (an_x[i]&amp;gt; n_x_dc_max) {n_x_dc_max =an_x[i]; n_x_dc_max_idx=i;}
          if (an_y[i]&amp;gt; n_y_dc_max) {n_y_dc_max =an_y[i]; n_y_dc_max_idx=i;}
      }
      n_y_ac= (an_y[an_ir_valley_locs[k+1]] - an_y[an_ir_valley_locs[k] ] )*(n_y_dc_max_idx -an_ir_valley_locs[k]); //red
      n_y_ac=  an_y[an_ir_valley_locs[k]] + n_y_ac/ (an_ir_valley_locs[k+1] - an_ir_valley_locs[k])  ; 
      n_y_ac=  an_y[n_y_dc_max_idx] - n_y_ac;    // subracting linear DC compoenents from raw 
      n_x_ac= (an_x[an_ir_valley_locs[k+1]] - an_x[an_ir_valley_locs[k] ] )*(n_x_dc_max_idx -an_ir_valley_locs[k]); // ir
      n_x_ac=  an_x[an_ir_valley_locs[k]] + n_x_ac/ (an_ir_valley_locs[k+1] - an_ir_valley_locs[k]); 
      n_x_ac=  an_x[n_y_dc_max_idx] - n_x_ac;      // subracting linear DC compoenents from raw 
      n_nume=( n_y_ac *n_x_dc_max)&amp;gt;&amp;gt;7 ; //prepare X100 to preserve floating value
      n_denom= ( n_x_ac *n_y_dc_max)&amp;gt;&amp;gt;7;
      if (n_denom&amp;gt;0  &amp;amp;&amp;amp; n_i_ratio_count &amp;lt;5 &amp;amp;&amp;amp;  n_nume != 0)
      {   
        an_ratio[n_i_ratio_count]= (n_nume*100)/n_denom ; //formular is ( n_y_ac *n_x_dc_max) / ( n_x_ac *n_y_dc_max) ;
        n_i_ratio_count++;
      }
    }
  }
  // choose median value since PPG signal may varies from beat to beat
  maxim_sort_ascend(an_ratio, n_i_ratio_count);
  n_middle_idx= n_i_ratio_count/2;

  if (n_middle_idx &amp;gt;1)
    n_ratio_average =( an_ratio[n_middle_idx-1] +an_ratio[n_middle_idx])/2; // use median
  else
    n_ratio_average = an_ratio[n_middle_idx ];

  if( n_ratio_average&amp;gt;2 &amp;amp;&amp;amp; n_ratio_average &amp;lt;184){
    n_spo2_calc= uch_spo2_table[n_ratio_average] ;
    *pn_spo2 = n_spo2_calc ;
    *pch_spo2_valid  = 1;//  float_SPO2 =  -45.060*n_ratio_average* n_ratio_average/10000 + 30.354 *n_ratio_average/100 + 94.845 ;  // for comparison with table
  }
  else{
    *pn_spo2 =  -999 ; // do not use SPO2 since signal an_ratio is out of range
    *pch_spo2_valid  = 0; 
  }
}


void maxim_find_peaks( int32_t *pn_locs, int32_t *n_npks,  int32_t  *pn_x, int32_t n_size, int32_t n_min_height, int32_t n_min_distance, int32_t n_max_num )
/**
* \brief        Find peaks
* \par          Details
*               Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE
*
* \retval       None
*/
{
  maxim_peaks_above_min_height( pn_locs, n_npks, pn_x, n_size, n_min_height );
  maxim_remove_close_peaks( pn_locs, n_npks, pn_x, n_min_distance );
  *n_npks = min( *n_npks, n_max_num );
}

void maxim_peaks_above_min_height( int32_t *pn_locs, int32_t *n_npks,  int32_t  *pn_x, int32_t n_size, int32_t n_min_height )
/**
* \brief        Find peaks above n_min_height
* \par          Details
*               Find all peaks above MIN_HEIGHT
*
* \retval       None
*/
{
  int32_t i = 1, n_width;
  *n_npks = 0;
  
  while (i &amp;lt; n_size-1){
    if (pn_x[i] &amp;gt; n_min_height &amp;amp;&amp;amp; pn_x[i] &amp;gt; pn_x[i-1]){      // find left edge of potential peaks
      n_width = 1;
      while (i+n_width &amp;lt; n_size &amp;amp;&amp;amp; pn_x[i] == pn_x[i+n_width])  // find flat peaks
        n_width++;
      if (pn_x[i] &amp;gt; pn_x[i+n_width] &amp;amp;&amp;amp; (*n_npks) &amp;lt; 15 ){      // find right edge of peaks
        pn_locs[(*n_npks)++] = i;    
        // for flat peaks, peak location is left edge
        i += n_width+1;
      }
      else
        i += n_width;
    }
    else
      i++;
  }
}

void maxim_remove_close_peaks(int32_t *pn_locs, int32_t *pn_npks, int32_t *pn_x, int32_t n_min_distance)
/**
* \brief        Remove peaks
* \par          Details
*               Remove peaks separated by less than MIN_DISTANCE
*
* \retval       None
*/
{
    
  int32_t i, j, n_old_npks, n_dist;
    
  /* Order peaks from large to small */
  maxim_sort_indices_descend( pn_x, pn_locs, *pn_npks );

  for ( i = -1; i &amp;lt; *pn_npks; i++ ){
    n_old_npks = *pn_npks;
    *pn_npks = i+1;
    for ( j = i+1; j &amp;lt; n_old_npks; j++ ){
      n_dist =  pn_locs[j] - ( i == -1 ? -1 : pn_locs[i] ); // lag-zero peak of autocorr is at index -1
      if ( n_dist &amp;gt; n_min_distance || n_dist &amp;lt; -n_min_distance )
        pn_locs[(*pn_npks)++] = pn_locs[j];
    }
  }

  // Resort indices int32_to ascending order
  maxim_sort_ascend( pn_locs, *pn_npks );
}

void maxim_sort_ascend(int32_t  *pn_x, int32_t n_size) 
/**
* \brief        Sort array
* \par          Details
*               Sort array in ascending order (insertion sort algorithm)
*
* \retval       None
*/
{
  int32_t i, j, n_temp;
  for (i = 1; i &amp;lt; n_size; i++) {
    n_temp = pn_x[i];
    for (j = i; j &amp;gt; 0 &amp;amp;&amp;amp; n_temp &amp;lt; pn_x[j-1]; j--)
        pn_x[j] = pn_x[j-1];
    pn_x[j] = n_temp;
  }
}

void maxim_sort_indices_descend(  int32_t  *pn_x, int32_t *pn_indx, int32_t n_size)
/**
* \brief        Sort indices
* \par          Details
*               Sort indices according to descending order (insertion sort algorithm)
*
* \retval       None
*/ 
{
  int32_t i, j, n_temp;
  for (i = 1; i &amp;lt; n_size; i++) {
    n_temp = pn_indx[i];
    for (j = i; j &amp;gt; 0 &amp;amp;&amp;amp; pn_x[n_temp] &amp;gt; pn_x[pn_indx[j-1]]; j--)
      pn_indx[j] = pn_indx[j-1];
    pn_indx[j] = n_temp;
  }
}
&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;Think of it as detective work on a wobbly line. Each heartbeat makes the finger absorb a little more light, so the IR signal dips once per beat. The code finds those dips and measures the spacing for heart rate. At each beat it also compares how strongly the red and IR light pulse for SpO2.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 1: Make the signal easy to read&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;First it subtracts the average (the DC part) and flips the sign:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;x[k] = -(IR[k] - mean(IR))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;The flip is there because the beat shows up as a dip, and flipping turns the dip into a peak, so one peak finder can do the job. Then a 4-point moving average smooths out sensor fuzz:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;x[k] = (x[k] + x[k+1] + x[k+2] + x[k+3]) / 4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 2: The threshold&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;th = mean(x), clamped to the range 30 to 60&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;Here is the first correction. I said before that the threshold was &amp;ldquo;the signal mean, clamped&amp;rdquo;. That&amp;rsquo;s true, but we just subtracted the mean, so mean(x) is about 0. The clamp therefore pushes it up to 30 almost every time. In practice the threshold is a fixed 30 ADC counts, and any beat whose swing is smaller is invisible. If your finger pressure is light or the LED current is low, the signal shrinks and beats disappear. That is a common reason for &lt;code dir="ltr"&gt;HRvalid = 0&lt;/code&gt;.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 3: Find the peaks&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;A sample counts as a peak if it is above &lt;code dir="ltr"&gt;th&lt;/code&gt; and higher than both neighbours (for a flat top, the left edge counts). Then the code cleans up the list:&lt;/p&gt;
&lt;ol dir="ltr"&gt;
&lt;li&gt;Sort the peaks from tallest to shortest.&lt;/li&gt;
&lt;li&gt;Keep the tallest, and throw away any peak within 4 samples of one already kept.&lt;/li&gt;
&lt;li&gt;Re-sort by position and keep at most 15.&lt;/li&gt;
&lt;/ol&gt;
&lt;p dir="ltr"&gt;This is the second correction. The spacing rule is &amp;ldquo;more than 4&amp;rdquo;, so peaks must be at least 5 samples apart (0.2 s), not 4. That caps the detectable rate at 1500/5 = 300 bpm, which is far above anything real.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 4: Heart rate&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;The average gap between neighbouring peaks is the sum of the gaps divided by N&amp;minus;1. The sum telescopes, so it is just (last peak &amp;minus; first peak) / (N&amp;minus;1), and it is done in integer division. With FS = 25 samples/s:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;HR = (25 &amp;times; 60) / T = 1500 / T&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;For example, with peaks at samples 5, 25, 46, 66 and 86, the gaps add up to 81, and 81/4 = 20 after rounding down. Then HR = 1500/20 = 75 bpm, although the true average gap is 20.25 samples (74 bpm). That rounding is why the output moves in steps: T = 19, 20, 21 gives 78, 75, 71 bpm. A 4 s window can&amp;rsquo;t resolve finer than about 3 to 4 bpm.&lt;/p&gt;
&lt;p dir="ltr"&gt;If fewer than 2 peaks are found, you get &lt;code dir="ltr"&gt;HR = -999&lt;/code&gt; and &lt;code dir="ltr"&gt;HRvalid = 0&lt;/code&gt;. Otherwise the flag is 1. It only means &amp;ldquo;at least two peaks were found&amp;rdquo;, and nothing checks that the number is plausible. A noisy window could produce 200 bpm with &lt;code dir="ltr"&gt;HRvalid = 1&lt;/code&gt;.&lt;/p&gt;
&lt;p dir="ltr"&gt;&lt;strong&gt;Step 5: SpO2&lt;/strong&gt;&lt;/p&gt;
&lt;p dir="ltr"&gt;For SpO2 it reloads the raw red and IR values, because the smoothed, flipped signal has lost the amplitude information. Then, for each pair of neighbouring valleys v1 and v2 (more than 3 samples apart):&lt;/p&gt;
&lt;ul dir="ltr"&gt;
&lt;li&gt;&lt;strong&gt;DC&lt;/strong&gt; is the highest raw value between the two valleys, one for red and one for IR.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AC&lt;/strong&gt; is how far above the straight line joining the two valleys the top of the pulse sits. At the peak index p, that line is:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;base = raw[v1] + (raw[v2] &amp;minus; raw[v1]) &amp;times; (p &amp;minus; v1) / (v2 &amp;minus; v1)
AC   = raw[p] &amp;minus; base&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;Each beat then gives the &amp;ldquo;ratio of ratios&amp;rdquo;:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;R = (AC_red / DC_red) / (AC_ir / DC_ir) = (AC_red &amp;times; DC_ir) / (AC_ir &amp;times; DC_red)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;The idea is that you compare how strongly each colour pulses relative to its own brightness. Oxygenated blood absorbs less red light, so more oxygen means a smaller red pulse and a smaller R. The code stores 100&amp;middot;R as an integer and uses &lt;code dir="ltr"&gt;&amp;gt;&amp;gt;7&lt;/code&gt; shifts to avoid overflow on small ARM chips.&lt;/p&gt;
&lt;p dir="ltr"&gt;It keeps up to 5 beat ratios, sorts them, and takes the middle one (or the average of the two around the middle). This acts like a median, so one bad beat can&amp;rsquo;t wreck the answer.&lt;/p&gt;
&lt;p dir="ltr"&gt;The final conversion isn&amp;rsquo;t computed live. It is a lookup, &lt;code dir="ltr"&gt;uch_spo2_table[ratio]&lt;/code&gt;, precomputed from Maxim&amp;rsquo;s empirical curve:&lt;/p&gt;
&lt;div&gt;
&lt;div dir="ltr"&gt;
&lt;div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;SpO2 &amp;asymp; &amp;minus;45.06&amp;middot;R&amp;sup2; + 30.354&amp;middot;R + 94.845&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p dir="ltr"&gt;R = 0.5 gives about 99%, and R = 1.0 gives about 80%. The result is marked valid when 2 &amp;lt; ratio &amp;lt; 184, which means R between 0.03 and 1.83. That range is very wide, so &lt;code dir="ltr"&gt;SPO2Valid = 1&lt;/code&gt; doesn&amp;rsquo;t mean the number is believable either.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;Results&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/8255.Screenshot-2026_2D00_09_2D00_30-213227.png" /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;I was not able to achieve the full accuracy it can give because it mattered a lot under pressure and depending on the distance between the sensor and the object.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;In the next part I will be finishing from where I left off. I think I will finish it really soon and give my best.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;Please let me know your thoughts about it.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;Thank you for giving your valuable time reading it.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:inherit;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>HealthGuard #5 - Interfacing with the LabVIEW</title><link>https://community.element14.com/thread/57357?ContentTypeID=0</link><pubDate>Tue, 20 Oct 2026 07:10:34 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:a3fb5e78-5353-45f6-a3b0-4db54ba7d6f8</guid><dc:creator>taifur</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57357?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57357/healthguard-5---interfacing-with-the-labview/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span&gt;LabVIEW &lt;/span&gt;&lt;span&gt;interfacing &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;important &lt;/span&gt;&lt;span&gt;part &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;my &lt;/span&gt;&lt;span&gt;HealthGuard&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;project &lt;/span&gt;&lt;span&gt;because &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;allows &lt;/span&gt;&lt;span&gt;me &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;visualize &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;monitor &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;collected &lt;/span&gt;&lt;span&gt;health &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;real &lt;/span&gt;&lt;span&gt;time &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;computer. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;receives &lt;/span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;from &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;ESP32, &lt;/span&gt;&lt;span&gt;including &lt;/span&gt;&lt;span&gt;body &lt;/span&gt;&lt;span&gt;temperature, &lt;/span&gt;&lt;span&gt;heart &lt;/span&gt;&lt;span&gt;rate, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;SpO₂, ECG&amp;nbsp;&lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;displays &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;values &lt;/span&gt;&lt;span&gt;through &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;user-friendly &lt;/span&gt;&lt;span&gt;graphical &lt;/span&gt;&lt;span&gt;interface. &lt;/span&gt;&lt;span&gt;LabVIEW &lt;/span&gt;&lt;span&gt;also &lt;/span&gt;&lt;span&gt;allows &lt;/span&gt;&lt;span&gt;me &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;plot &lt;/span&gt;&lt;span&gt;real-time &lt;/span&gt;&lt;span&gt;graphs, &lt;/span&gt;&lt;span&gt;observe &lt;/span&gt;&lt;span&gt;changes &lt;/span&gt;&lt;span&gt;in &lt;/span&gt;&lt;span&gt;vital &lt;/span&gt;&lt;span&gt;signs, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;set &lt;/span&gt;&lt;span&gt;up &lt;/span&gt;&lt;span&gt;alarms &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;notify &lt;/span&gt;&lt;span&gt;users &lt;/span&gt;&lt;span&gt;when &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;measured &lt;/span&gt;&lt;span&gt;values &lt;/span&gt;&lt;span&gt;exceed &lt;/span&gt;&lt;span&gt;predefined &lt;/span&gt;&lt;span&gt;limits. &lt;/span&gt;&lt;span&gt;This &lt;/span&gt;&lt;span&gt;graphical &lt;/span&gt;&lt;span&gt;interface &lt;/span&gt;&lt;span&gt;makes &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;easier &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;understand &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;collected &lt;/span&gt;&lt;span&gt;data, &lt;/span&gt;&lt;span&gt;identify &lt;/span&gt;&lt;span&gt;unusual &lt;/span&gt;&lt;span&gt;changes, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;demonstrate &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;system&amp;#39;s &lt;/span&gt;&lt;span&gt;functionality. &lt;/span&gt;&lt;span&gt;By &lt;/span&gt;&lt;span&gt;integrating &lt;/span&gt;&lt;span&gt;LabVIEW &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;ESP32-based &lt;/span&gt;&lt;span&gt;monitoring &lt;/span&gt;&lt;span&gt;device, &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;create &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;more &lt;/span&gt;&lt;span&gt;interactive &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;informative &lt;/span&gt;&lt;span&gt;monitoring &lt;/span&gt;&lt;span&gt;system &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;educational &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;prototype &lt;/span&gt;&lt;span&gt;applications, &lt;/span&gt;&lt;span&gt;while &lt;/span&gt;&lt;span&gt;recognizing &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;clinical &lt;/span&gt;&lt;span&gt;use &lt;/span&gt;&lt;span&gt;requires &lt;/span&gt;&lt;span&gt;appropriate &lt;/span&gt;&lt;span&gt;medical &lt;/span&gt;&lt;span&gt;validation.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;To interface the ESP32 with LabVIEW, I used the VISA (Virtual Instrument Software Architecture) protocol to establish serial communication between the hardware and the graphical user interface. The ESP32 transmits the collected health data to LabVIEW through a serial connection at a baud rate of 9600 bps. LabVIEW receives and processes the incoming data, separates the individual values (using Scan from String block), and displays them through a user-friendly monitoring interface. Body temperature, heart rate, and SpO₂ levels are presented using both numerical indicators and meter indicators, allowing users to read the exact measurements and quickly understand the current status of each parameter. In addition, the ECG data is plotted on a real-time chart, making it possible to observe changes in the electrical activity of the heart as the data arrives from the ESP32. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The complete LabVIEW interfacing and visualization setup is shown in the screenshot below. I did not use LabView before, so it took too much time for me to make it working. The LabView official documentation was very helpful and I also watched some YouTube tutorials on it. My overall experience with LabVIEW is really good.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" style="max-height:376px;max-width:754px;"  height="376" src="https://community.element14.com/resized-image/__size/1508x752/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_20-112421.png" width="754" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The block for my primary LabVIEW interface is shown below.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Screenshot-2026_2D00_10_2D00_20-130221.png" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;But this is a draft interface; I am going to make it complete and show the full interface in my final project documentation. Without the actual sensor, I just generate random data from the ESP32, convert the data to a string, and send it to the Computer using the Serial.print() function.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;ESP32 Demo Code is given below:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;math.h&amp;gt;

// Put these global variables OUTSIDE setup() and loop()
float ecgPhase = 0.0;
float phaseStep = 0.005;
float baselineDrift = 0.0;
float noiseState = 0.0;

float generateECG() {
  // Approximately 1-second heartbeat cycle
  ecgPhase += phaseStep;
  if (ecgPhase &amp;gt;= 1.0) {
    ecgPhase -= 1.0;

    // Slight beat-to-beat variation
    phaseStep = 0.005 + random(-3, 4) * 0.00001;
  }

  float t = ecgPhase;

  // P wave
  float p = 18.0 * exp(-pow((t - 0.17) / 0.035, 2));

  // QRS complex with slightly distorted peaks
  float q = -28.0 * exp(-pow((t - 0.385) / 0.014, 2));
  float r = random(165, 221) *
            exp(-pow((t - 0.405) / 0.012, 2));
  float s = -65.0 * exp(-pow((t - 0.435) / 0.022, 2));

  // T wave
  float tw = 48.0 * exp(-pow((t - 0.68) / 0.075, 2));

  // Slow baseline movement
  baselineDrift = 12.0 * sin(2.0 * PI * t * 1.2)
                + 5.0 * sin(2.0 * PI * t * 0.4);

  // Random high-frequency noise
  float muscleNoise = random(-9, 10);

  // Mild 50 Hz mains interference (simulated)
  static int noiseSample = 0;
  float mainsNoise = 3.0 * sin(noiseSample * 1.5708);
  noiseSample++;

  // Occasional small electrode/contact disturbance
  float contactNoise = 0;
  if (random(0, 100) &amp;lt; 3) {
    contactNoise = random(-18, 19);
  }

  float ecg = 512.0 + p + q + r + s + tw
            + baselineDrift + muscleNoise
            + mainsNoise + contactNoise;

  return constrain((int)ecg, 0, 1023);
}

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);


}

void loop() {
// One simulated heartbeat, sampled over time
  
float temperature = random(3600, 3789) / 100.0;  // 20.00–40.00
int value2 = random(70, 80);                    // 50–100
int value3 = random(96, 99);                     // 30–80

int ecgValue = generateECG();

String dataString = String(temperature, 2) + &amp;quot;,&amp;quot; +
                    String(value2) + &amp;quot;,&amp;quot; +
                    String(value3) + &amp;quot;,&amp;quot; +
                    String(ecgValue);

Serial.println(dataString);

delay(10);

}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;I also recorded my screen while LabVIEW was receiving data from ESP32 board.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/Screen-Recording-2026_2D00_10_2D00_20-112511.mp4"&gt;community.element14.com/.../Screen-Recording-2026_2D00_10_2D00_20-112511.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>HealthGuard 4 - Finally Selecting the Microcontroller &amp; Power Source</title><link>https://community.element14.com/thread/57354?ContentTypeID=0</link><pubDate>Sun, 18 Oct 2026 11:21:27 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:944c5142-1641-4bf9-8683-1a613f9a3c96</guid><dc:creator>taifur</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/57354?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57354/healthguard-4---finally-selecting-the-microcontroller-power-source/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;span&gt;For &lt;/span&gt;&lt;span&gt;my &lt;/span&gt;&lt;span&gt;Health Guard project&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;selecting &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;right &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;was &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;important &lt;/span&gt;&lt;span&gt;part &lt;/span&gt;&lt;span&gt;of &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;development &lt;/span&gt;&lt;span&gt;process. &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;explored &lt;/span&gt;&lt;span&gt;several &lt;/span&gt;&lt;span&gt;platforms, &lt;/span&gt;&lt;span&gt;including &lt;/span&gt;&lt;span&gt;Arduino, &lt;/span&gt;&lt;span&gt;ESP32 &lt;/span&gt;&lt;span&gt;development &lt;/span&gt;&lt;span&gt;boards, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;Raspberry &lt;/span&gt;&lt;span&gt;Pi &lt;/span&gt;&lt;span&gt;Pico, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;carefully &lt;/span&gt;&lt;span&gt;considered &lt;/span&gt;&lt;span&gt;their &lt;/span&gt;&lt;span&gt;capabilities, &lt;/span&gt;&lt;span&gt;cost, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;suitability &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;my &lt;/span&gt;&lt;span&gt;application. &lt;/span&gt;&lt;span&gt;After &lt;/span&gt;&lt;span&gt;evaluating &lt;/span&gt;&lt;span&gt;these &lt;/span&gt;&lt;span&gt;options, &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;finally &lt;/span&gt;&lt;span&gt;chose &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;ESP32 Cheap Yellow Display (CYD)&lt;/span&gt; &lt;span&gt;for &lt;/span&gt;&lt;span&gt;practical &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;technical &lt;/span&gt;&lt;span&gt;reasons. &lt;/span&gt;&lt;span&gt;This &lt;/span&gt;&lt;span&gt;board &lt;/span&gt;&lt;span&gt;combines &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;powerful &lt;/span&gt;&lt;span&gt;ESP32 &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;with &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;built-in &lt;/span&gt;&lt;span&gt;2.8-inch &lt;/span&gt;&lt;span&gt;TFT &lt;/span&gt;&lt;span&gt;color &lt;/span&gt;&lt;span&gt;display, &lt;/span&gt;&lt;span&gt;making &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;an &lt;/span&gt;&lt;span&gt;ideal &lt;/span&gt;&lt;span&gt;choice &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;my &lt;/span&gt;&lt;span&gt;project. &lt;/span&gt;&lt;span&gt;Since &lt;/span&gt;&lt;span&gt;Health &lt;/span&gt;&lt;span&gt;Guard &lt;/span&gt;&lt;span&gt;is &lt;/span&gt;&lt;span&gt;designed &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;monitor &lt;/span&gt;&lt;span&gt;vital &lt;/span&gt;&lt;span&gt;health &lt;/span&gt;&lt;span&gt;parameters, &lt;/span&gt;&lt;span&gt;I &lt;/span&gt;&lt;span&gt;need &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;that &lt;/span&gt;&lt;span&gt;can &lt;/span&gt;&lt;span&gt;present &lt;/span&gt;&lt;span&gt;real-time &lt;/span&gt;&lt;span&gt;measurements &lt;/span&gt;&lt;span&gt;clearly &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;intuitively. &lt;/span&gt;&lt;span&gt;The &lt;/span&gt;&lt;span&gt;CYD &lt;/span&gt;&lt;span&gt;allows &lt;/span&gt;&lt;span&gt;me &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;body &lt;/span&gt;&lt;span&gt;temperature, &lt;/span&gt;&lt;span&gt;pulse &lt;/span&gt;&lt;span&gt;rate, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;blood &lt;/span&gt;&lt;span&gt;oxygen &lt;/span&gt;&lt;span&gt;saturation &lt;/span&gt;&lt;span&gt;(SpO₂), &lt;/span&gt;&lt;span&gt;while &lt;/span&gt;&lt;span&gt;also &lt;/span&gt;&lt;span&gt;plotting &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;live &lt;/span&gt;&lt;span&gt;electrocardiogram &lt;/span&gt;&lt;span&gt;(ECG) &lt;/span&gt;&lt;span&gt;waveform &lt;/span&gt;&lt;span&gt;on &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;same &lt;/span&gt;&lt;span&gt;screen. &lt;/span&gt;&lt;span&gt;Integrating &lt;/span&gt;&lt;span&gt;the &lt;/span&gt;&lt;span&gt;microcontroller &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;into &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;single, &lt;/span&gt;&lt;span&gt;affordable &lt;/span&gt;&lt;span&gt;board &lt;/span&gt;&lt;span&gt;reduces &lt;/span&gt;&lt;span&gt;hardware &lt;/span&gt;&lt;span&gt;complexity, &lt;/span&gt;&lt;span&gt;minimizes &lt;/span&gt;&lt;span&gt;wiring, &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span&gt;saves &lt;/span&gt;&lt;span&gt;space. &lt;/span&gt;&lt;span&gt;Most &lt;/span&gt;&lt;span&gt;importantly, &lt;/span&gt;&lt;span&gt;it &lt;/span&gt;&lt;span&gt;provides &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;practical, &lt;/span&gt;&lt;span&gt;cost-effective &lt;/span&gt;&lt;span&gt;platform &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;developing &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;compact &lt;/span&gt;&lt;span&gt;health-monitoring &lt;/span&gt;&lt;span&gt;device &lt;/span&gt;&lt;span&gt;without &lt;/span&gt;&lt;span&gt;requiring &lt;/span&gt;&lt;span&gt;a &lt;/span&gt;&lt;span&gt;separate &lt;/span&gt;&lt;span&gt;display &lt;/span&gt;&lt;span&gt;module &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;additional &lt;/span&gt;&lt;span&gt;display-driving &lt;/span&gt;&lt;span&gt;hardware.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The ESP32 Cheap Yellow Display (CYD) offers sufficient I/O connectivity for my Health Guard project. It provides GPIO pins that I can configure for I&amp;sup2;C communication to connect two sensors for measuring vital health parameters. In addition, I can connect the ECG module using one analog input to acquire the ECG signal and two GPIO pins to monitor the module&amp;rsquo;s lead-off detection signals. This combination of interfaces allows me to integrate all three sensor modules with the ESP32 while using the built-in 2.8-inch TFT display to present real-time measurements and ECG waveforms. I will carefully assign the GPIO pins to avoid conflicts with the display, touch controller, and other onboard peripherals.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" style="max-height:435px;max-width:700px;"  height="435" src="https://community.element14.com/resized-image/__size/1400x870/__key/communityserver-discussions-components-files/458/FXWE2X1MJOYI8WW.jpg" width="700" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;For powering my Health Guard project, I selected an 18650 Li-ion rechargeable battery combined with a 5V UPS module. The battery provides a compact and rechargeable power source, while the UPS module boosts the battery&amp;rsquo;s nominal 3.7V output to a regulated 5V supply that can power the ESP32 CYD board through its 5V input. The module also incorporates battery-charging functionality, allowing me to recharge the battery without removing it from the device. This integrated power solution simplifies the overall design, reduces additional circuitry, and makes Health Guard more portable and convenient for everyday use.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:538px;max-width:581px;"  height="538" src="https://community.element14.com/resized-image/__size/1162x1076/__key/communityserver-discussions-components-files/458/F4L0CRQMJOYRWTX.jpg" width="581" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I added a sliding power switch to turn the Health Guard device on and off conveniently. I connected the switch, 5V UPS power module, and ESP32 CYD board using thin jumper wires and soldered the connections to establish the power circuit. This arrangement provides a simple and compact wiring solution, allowing me to control the device&amp;rsquo;s power without disconnecting the battery.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>HealthGuard #3 - Interfacing  Analog Devices single-lead ECG front end</title><link>https://community.element14.com/thread/57352?ContentTypeID=0</link><pubDate>Fri, 16 Oct 2026 09:28:42 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:263cbeb9-99e4-418e-8754-d8673bae0979</guid><dc:creator>taifur</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57352?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57352/healthguard-3---interfacing-analog-devices-single-lead-ecg-front-end/rss?ContentTypeId=0</wfw:commentRss><description>&lt;h1 id="mcetoc_1k51n1ere0"&gt;What is AD8232?&lt;/h1&gt;
&lt;p&gt;The AD8232 is an integrated signal conditioning block for ECG and other biopotential measurement applications. It is designed to extract, amplify, and filter small biopotential signals in the presence of noisy conditions, such as those created by motion or remote electrode placement. This design allows for an ultralow-power analog-to-digital converter (ADC) or an embedded microcontroller to acquire the output signal easily. The AD8232 can implement a two-pole high-pass filter for eliminating motion artifacts and the electrode half-cell potential. This filter is tightly coupled with the instrumentation architecture of the amplifier to allow both large gain and high-pass filtering in a single stage, thereby saving space and cost. An uncommitted operational amplifier enables the AD8232 to create a three-pole low-pass filter to remove additional noise.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To improve common-mode rejection of the line frequencies in the system and other undesired interferences, the AD8232 includes an amplifier for driven lead applications, such as right leg drive (RLD). The AD8232 includes a fast restore function that reduces the duration of otherwise long settling tails of the high-pass filters. After an abrupt signal change that rails the amplifier (such as a leads off condition), the AD8232 automatically adjusts to a higher filter cutoff. This feature allows the AD8232 to recover quickly, and therefore, to take valid measurements soon after connecting the electrodes to the subject.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1k51n4uk51"&gt;&lt;span&gt;The AD8232 SparkFun&amp;nbsp;Module&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;The AD8232 SparkFun Single Lead Heart Rate Monitor is a cost-effective board used to measure the electrical activity of the heart. This electrical activity can be charted as an ECG or Electrocardiogram and output as an analog reading. ECGs can be extremely noisy, the AD8232 Single Lead Heart Rate Monitor acts as an op amp to help obtain a clear signal from the PR and QT Intervals easily.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/12650_2D00_01.jpg" /&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/12650_2D00_03.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The AD8232 Heart Rate Monitor breaks out nine connections from the IC that you can solder pins, wires, or other connectors to. SDN, LO+, LO-, OUTPUT, 3.3V, GND provide essential pins for operating this monitor with an Arduino or other development board. Also provided on this board are RA (Right Arm), LA (Left Arm), and RL (Right Leg) pins to attach and use your own custom sensors. Additionally, there is an LED indicator light that will pulsate to the rhythm of a heart beat. Biomedical Sensor Pads and Sensor Cable are required to use the heart monitor.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I used the following Cable and Pad with the sensor module.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/12970_2D00_00.jpg" /&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/12969_2D00_00.jpg" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;For primary testing, I used an Arduino Mega board, and the sensor connections to the Arduino board are shown in the following image. I used thin jumper wires to solder the sensor module to the Arduino board.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:488px;max-width:619px;"  height="488" src="https://community.element14.com/resized-image/__size/1238x976/__key/communityserver-discussions-components-files/458/1.jpg" width="619" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:375px;max-width:619px;"  height="375" src="https://community.element14.com/resized-image/__size/1238x750/__key/communityserver-discussions-components-files/458/2.jpg" width="619" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The following connection is made:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I&amp;nbsp;connected five of the board&amp;#39;s nine pins to your Arduino. The five pins you need are labeled &lt;strong&gt;GND&lt;/strong&gt;, &lt;strong&gt;3.3v&lt;/strong&gt;, &lt;strong&gt;OUTPUT&lt;/strong&gt;, &lt;strong&gt;LO-&lt;/strong&gt;, and &lt;strong&gt;LO+&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;center&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Board Label&lt;/td&gt;
&lt;td&gt;Pin Function&lt;/td&gt;
&lt;td&gt;Arduino Connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;GND&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Ground&lt;/td&gt;
&lt;td&gt;&lt;b&gt;GND&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;3.3v&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;3.3v Power Supply&lt;/td&gt;
&lt;td&gt;&lt;b&gt;3.3v&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;OUTPUT&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Output Signal&lt;/td&gt;
&lt;td&gt;&lt;b&gt;A6&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;LO-&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Leads-off Detect -&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;48&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;LO+&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Leads-off Detect +&lt;/td&gt;
&lt;td&gt;&lt;b&gt;50&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;SDN&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Shutdown&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Not used&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;h3 id="mcetoc_1k51o930n2"&gt;Sensor Pad Placement&lt;/h3&gt;
&lt;p&gt;The sensor placement was performed according to the SparkFun recommendation.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The closer to the heart the pads are, the better the measurement. The cables are color-coded to help identify proper placement as shown in the table based on Einthoven&amp;#39;s triangle. The sensors can be placed on the forearms and leg as shown on the diagram on the left. Or they can be placed on the chest near the arms and above the right, lower abdomen (i.e. just above the right hip) as shown on the diagram on the right.&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;/p&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cable Color&lt;/td&gt;
&lt;td&gt;Signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Black&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;RA (Right Arm)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span style="color:blue;"&gt;Blue&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;LA (Left Arm)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span style="color:red;"&gt;Red&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;RL (Right Leg)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="center-block text-center"&gt;&lt;a href="https://cdn.sparkfun.com/assets/learn_tutorials/2/5/0/body.png" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/pastedimage1792134137603v1.png"  /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;The following code was used for a simple data read:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void setup() {
  // initialize the serial communication:
  Serial.begin(9600);
  pinMode(10, INPUT); // Setup for leads off detection LO +
  pinMode(11, INPUT); // Setup for leads off detection LO -

}

void loop() {
  
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
    Serial.println(&amp;#39;!&amp;#39;);
  }
  else{
    // send the value of analog input 0:
      Serial.println(analogRead(A0));
  }
  //Wait for a bit to keep serial data from saturating
  delay(1);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I got the following result from the Arduino Serial Plotter. Maybe it needs some adjustment in the code for a clean graph.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:439px;max-width:814px;"  height="439" src="https://community.element14.com/resized-image/__size/1628x878/__key/communityserver-discussions-components-files/458/ecg.jpg" width="814" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>EdgeCare: phase 5 - integration of MAX30208 and MAX30105 sensors; final stage</title><link>https://community.element14.com/thread/57351?ContentTypeID=0</link><pubDate>Thu, 15 Oct 2026 19:03:25 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ab6d1718-1b1f-4b32-a699-16c28d4308dd</guid><dc:creator>mihaita802003</dc:creator><slash:comments>5</slash:comments><comments>https://community.element14.com/thread/57351?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57351/edgecare-phase-5---integration-of-max30208-and-max30105-sensors-final-stage/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57261/edgecare-phase-1---setup-ide-mcu-and-ble" data-e14adj="t"&gt;EdgeCare: phase 1 - setup IDE, MCU and BLE - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57283/edgecare-phase-2---setup-i2c-read-max30100-and-create-vi-in-labview" data-e14adj="t"&gt;EdgeCare: phase 2 - setup I2C, read MAX30100 and create VI in LabView - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57334/edgecare-phase-3---bracelet-with-two-dry-electrodes-placed-on-the-skin-for-the-dielectric-profile-and-more" data-e14adj="t"&gt;EdgeCare: phase 3 - bracelet with two dry electrodes placed on the skin for the dielectric profile and more - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57341/edgecare-phase-4---save-data-and-smart-home-connection" data-e14adj="t"&gt;EdgeCare: phase 4 - save data and smart home connection - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;EdgeCare&amp;nbsp;will be a&amp;nbsp;Multi-Sensor Metabolic &amp;amp; Autonomic Datalogging Wearable with LabVIEW R&amp;amp;D Analytics.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In this post I will present the integration of temperature sensor and HR &amp;amp; SpO2 sensor&amp;nbsp; received from element14.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The MAX30208 temperature sensor proved somewhat problematic to use because it shared the same I2C bus with another chip&amp;mdash;an I2C-to-OneWire bridge&amp;mdash;which required specific configuration; otherwise, after a certain amount of time, the two chips would conflict, causing the I2C stack on the ESP32C6 to enter a locked state. Once I separated the two sensors on the Analog Devices development board, I was able to communicate reliably with this temperature sensor. Details on what I did can be found here:&amp;nbsp;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57286/question-is-the-max30208evsys-board-working-for-you/238617" data-e14adj="t"&gt;Question: Is the MAX30208EVSYS Board working for you? - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I replaced also the MAX30100 with the received MAX30105. This sensor features an improved optical component, allowing it to be used on other parts of the body&amp;mdash;not just the fingertip; it can even be placed on the back of the hand, in an area with hair, while still providing consistent readings.&lt;/p&gt;
&lt;p&gt;Additionally, I installed a small OLED display that shows three key measurements: temperature, heart rate (HR), and blood oxygen level (SpO2).&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:189px;max-width:252px;"  height="189" src="https://community.element14.com/resized-image/__size/504x378/__key/communityserver-discussions-components-files/458/20261015_5F00_190511.jpg" width="252" /&gt;&amp;nbsp; &amp;nbsp;&lt;img loading="lazy" style="max-height:188px;max-width:252px;" alt="ESP32C6 act as BLE Slave" src="https://community.element14.com/resized-image/__size/504x376/__key/communityserver-discussions-components-files/458/20261015_5F00_185532.jpg" /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/20261015_5F00_190337_5F00_1.mp4"&gt;community.element14.com/.../20261015_5F00_190337_5F00_1.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OBS: I also kept the DS18B28 sensor (used initially) as a backup for the MAX30208; in the software, I included a function that checks whether the MAX30208 readings are consistent&amp;mdash;if not, the value from the DS18B20 is used instead:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;    // read DS18B20; used as backup for MAX30208
    float realTemp = readDS18B20Temp(); 

    // read MAX30208
    float max30208Temp = readMAX30208Temp();   
    if (max30208Temp &amp;gt; -100) {
      realTemp = max30208Temp; // Use MAX30208 value if is valid
    }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The code for this project is written using PlatformIO along with the Arduino framework:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:238px;max-width:387px;"  height="238" src="https://community.element14.com/resized-image/__size/774x476/__key/communityserver-discussions-components-files/458/PlatformIO-main-screen.png" width="387" /&gt;&lt;/p&gt;
&lt;p&gt;Presented below are the data transmission by the ESP32C6 Master and the corresponding reception by the EST32C6&amp;nbsp;Client via BLE:&lt;/p&gt;
&lt;p&gt;- In PlatformIP, the data are sent to the BLE and serial port (COM3):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/PlatformIO-serial-data.mp4"&gt;community.element14.com/.../PlatformIO-serial-data.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;- In a serial tool, the client ESP32C6 is connected also via serial (COM4):&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/Client-receiving-data-over-ble.mp4"&gt;community.element14.com/.../Client-receiving-data-over-ble.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the overview of the final project:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Project-block-schematic_5F00_01.png" /&gt;&lt;/p&gt;
&lt;p&gt;Demo:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/20261015_5F00_191759_5F00_1.mp4"&gt;community.element14.com/.../20261015_5F00_191759_5F00_1.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The code used in this project contain two archive: one for ESP32C6 master and other for ESP32C6 slave:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/ESP32C6_5F00_BLE_5F00_server.zip"&gt;community.element14.com/.../ESP32C6_5F00_BLE_5F00_server.zip&lt;/a&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/ESP32C6_5F00_BLE_2D00_client.zip"&gt;community.element14.com/.../ESP32C6_5F00_BLE_2D00_client.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OBS: during the development phases, I created few small projects, to help me with the implementation: I2C scanner and max30208 termometer&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/I2c-scanner.zip"&gt;community.element14.com/.../I2c-scanner.zip&lt;/a&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/termometru.zip"&gt;community.element14.com/.../termometru.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For Smart Home i used an older project of mine, posted here:&amp;nbsp;&lt;a title="My Smart Home" href="https://www.hackster.io/popa-mihai/smart-home-with-mixtile-edge-2-kit-bee1b3" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://www.hackster.io/popa-mihai/smart-home-with-mixtile-edge-2-kit-bee1b3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is created using an mixtile Edge 2 Kit PC and NodeRed;&lt;/p&gt;
&lt;p&gt;Code used for Smart Home with NodeRed:&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/EdgeCare-flow.zip"&gt;community.element14.com/.../EdgeCare-flow.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Next steps:&lt;/p&gt;
&lt;p&gt;- create an PCB that contain the MCU, temp sensor and HR % SpO2 sensor;&lt;/p&gt;
&lt;p&gt;- add an LiPo battery to the circuit;&lt;/p&gt;
&lt;p&gt;- create a bracelet that will inclide the dry skin sensors;&lt;/p&gt;
&lt;p&gt;- record many data to improve the sensors algorithm accuracy;&lt;/p&gt;
&lt;p&gt;-&amp;nbsp;replace the simple circuit (but effective) with a specialied one based on&amp;nbsp;AD5933 (Analog Devices) to measure the&amp;nbsp;dielectric/bioimpedance;&lt;/p&gt;
&lt;p&gt;- use the termic transfer foile to connect the temperature sensor;&lt;/p&gt;
&lt;p&gt;- use the EMI foile to isolate the front-end circuit;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>EdgeCare: phase 4 - save data and smart home connection</title><link>https://community.element14.com/thread/57341?ContentTypeID=0</link><pubDate>Sat, 10 Oct 2026 19:46:42 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:a1eafe95-5e1e-42d1-ac22-8bf5bafe5ef0</guid><dc:creator>mihaita802003</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/57341?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57341/edgecare-phase-4---save-data-and-smart-home-connection/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57261/edgecare-phase-1---setup-ide-mcu-and-ble" data-e14adj="t"&gt;EdgeCare: phase 1 - setup IDE, MCU and BLE - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57283/edgecare-phase-2---setup-i2c-read-max30100-and-create-vi-in-labview" data-e14adj="t"&gt;EdgeCare: phase 2 - setup I2C, read MAX30100 and create VI in LabView - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57334/edgecare-phase-3---bracelet-with-two-dry-electrodes-placed-on-the-skin-for-the-dielectric-profile-and-more" data-e14adj="t"&gt;EdgeCare: phase 3 - bracelet with two dry electrodes placed on the skin for the dielectric profile and more - element14 Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;EdgeCare&amp;nbsp;will be a&amp;nbsp;Multi-Sensor Metabolic &amp;amp; Autonomic Datalogging Wearable with LabVIEW R&amp;amp;D Analytics.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;Important&lt;/strong&gt;: this phase 4 normally should be used to create a PCB for the project, optimise the code and add a small power supply toithe bracelet. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Because the issue with EORI code (I wait for the components for one month), the full schematic including the power supply, PCB and enclouser will be done after the contest; the same with the final shape and type for the dry sensors.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this post I will present two things:&lt;/p&gt;
&lt;p&gt;- save data from LabView on the PC in the excel format;&lt;/p&gt;
&lt;p&gt;- connect the LabView to my smart home based on NodeRed&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;A. Save data from LabView to the PC in excel format&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Saving the data is a good thing because they can be analyzed for bebuging, improvment of the system behavior and long time observations.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;To achive this I chosen to save data in excel format directly from LabView.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;For that I added the &amp;quot;Write to measurement file&amp;quot; block; inside I set the file path were the file will be saved (this is generic and can be modified);&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Because i have 16 signals + timestamp, I used &amp;quot;merge signals&amp;quot; block to gather all the signals in one entrance, to be sabed in the excel file.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I added also an button to start/stop the saving data; this button/option is used especially in the development phase:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:168px;max-width:561px;"  height="168" src="https://community.element14.com/resized-image/__size/1122x336/__key/communityserver-discussions-components-files/458/Save-data.png" width="561" /&gt;&lt;/p&gt;
&lt;p&gt;OBS:&amp;nbsp;it is not easy to set the name of the signals saved in the top of each column in LabView; that why I modified the original file with the signal names and then, for analisys, the first from the log file will be replaced with the modified one:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" style="max-height:360px;max-width:640px;" alt="First line modified with the signals name" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Tabel-with-signals-names.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" style="max-height:360px;max-width:640px;" alt="Saved data in the current log file" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/458/Saved-data.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;B. Connect the LabView to my smart home based on NodeRed&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After configuring all the parameters, I thought it would be useful to integrate this system&amp;nbsp;with an&amp;nbsp;smart home environment, to have all these information available in one place.&amp;nbsp;&lt;br /&gt;This &amp;quot;Smart Home&amp;quot; project runs on a Mixtile Edge 2 PC kit&amp;mdash;using Debian Linux and a Node-RED environment.&lt;br /&gt;Communication with this PC&amp;mdash;and by extension, the smart home/Node-RED system&amp;mdash;takes place via the HTTP protocol, as it is much easier to configure in LabVIEW than MQTT.&lt;br /&gt;I added a button in LabVIEW to toggle data transmission to Node-RED; this is useful for debugging and development, but especially for handling situations where Node-RED is shut down (otherwise, LabVIEW would generate a series of communication errors).&lt;/p&gt;
&lt;p&gt;Link with my Smart house project:&amp;nbsp;&lt;a href="https://www.hackster.io/popa-mihai/smart-home-with-mixtile-edge-2-kit-bee1b3" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;My Smart house project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is the communication implementation:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:180px;max-width:559px;"  height="180" src="https://community.element14.com/resized-image/__size/1118x360/__key/communityserver-discussions-components-files/458/Communication.png" width="559" /&gt;&lt;/p&gt;
&lt;p&gt;Now, this is the final LabView panel and implementation:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:290px;max-width:431px;"  src="https://community.element14.com/resized-image/__size/862x580/__key/communityserver-discussions-components-files/458/Final-panel.png" /&gt;&amp;nbsp;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:430px;"  src="https://community.element14.com/resized-image/__size/860x720/__key/communityserver-discussions-components-files/458/Final-implementation.png" /&gt;&lt;/p&gt;
&lt;p&gt;NodeRed implementation and panel:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:430px;"  src="https://community.element14.com/resized-image/__size/860x720/__key/communityserver-discussions-components-files/458/NodeRed-implementation.jpg" /&gt;&amp;nbsp; &amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:430px;"  src="https://community.element14.com/resized-image/__size/860x720/__key/communityserver-discussions-components-files/458/NodeRed-panel.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The code used in NodeRed will be available in the final project post.&lt;/p&gt;
&lt;p&gt;Demo:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/458/All-modules.mp4"&gt;community.element14.com/.../All-modules.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Next: replace the max30100 and DS18B20 sensors with the ones received from element14 and finalize the bracelet...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>EdgeCare - kit from element14</title><link>https://community.element14.com/thread/57340?ContentTypeID=0</link><pubDate>Fri, 09 Oct 2026 10:37:30 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:17d5e96a-1b97-405a-b5dc-1c4d9a10eacc</guid><dc:creator>mihaita802003</dc:creator><slash:comments>9</slash:comments><comments>https://community.element14.com/thread/57340?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-home-healthcare-challenge/f/forum/57340/edgecare---kit-from-element14/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;In this post I want to present the kit that I received from element14/Farnell Premium.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OBS&lt;/strong&gt;: on September 14 I received a note from Pegasus/fedEx to complete the custom papers and I discovered that my EORI code was &amp;quot;deactivated&amp;quot; because the availability period was only for ome year (on 2023 when was created!).&lt;/p&gt;
&lt;p&gt;Long story short: on October 7, my EORI code was updated and two days later, the package arrived to me.&lt;/p&gt;
&lt;p&gt;Big thank element14, Liz and Jo for support and&amp;nbsp;interest in solving this situation (discussions with FedEx and me)&lt;/p&gt;
&lt;p&gt;Now, the kit:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:200px;max-width:150px;"  height="200" src="https://community.element14.com/resized-image/__size/300x400/__key/communityserver-discussions-components-files/458/20261009_5F00_093746.jpg" width="150" /&gt;&amp;nbsp;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:150px;"  src="https://community.element14.com/resized-image/__size/300x720/__key/communityserver-discussions-components-files/458/20261009_5F00_100509.jpg" /&gt;&amp;nbsp;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:266px;max-width:150px;"  src="https://community.element14.com/resized-image/__size/300x532/__key/communityserver-discussions-components-files/458/20261009_5F00_100425.jpg" /&gt;&amp;nbsp;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:150px;"  src="https://community.element14.com/resized-image/__size/300x720/__key/communityserver-discussions-components-files/458/20261009_5F00_100447.jpg" /&gt;&amp;nbsp;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:150px;"  src="https://community.element14.com/resized-image/__size/300x720/__key/communityserver-discussions-components-files/458/20261009_5F00_100522.jpg" /&gt;&amp;nbsp; &lt;img loading="lazy" alt="image" style="max-height:112px;max-width:200px;"  src="https://community.element14.com/resized-image/__size/400x224/__key/communityserver-discussions-components-files/458/20261009_5F00_100805.jpg" /&gt;&amp;nbsp;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:150px;"  src="https://community.element14.com/resized-image/__size/300x720/__key/communityserver-discussions-components-files/458/20261009_5F00_101039.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The package contain:&lt;/p&gt;
&lt;p&gt;- Analog Devices - MAX30208EVSYS Evaluation kit;&lt;/p&gt;
&lt;p&gt;- Analog devices - MAXREFDES117 Optical heart rate and Pulse-Oximetry Monitor;&lt;/p&gt;
&lt;p&gt;- Basketball cup custom;&lt;/p&gt;
&lt;p&gt;- stickert and pin, all with element14;&lt;/p&gt;
&lt;p&gt;- Multicomp MCBB830K Solderless Breadboard;&lt;/p&gt;
&lt;p&gt;- Multicomp Pro Thermal tape;&lt;/p&gt;
&lt;p&gt;- 3M EM25TP-0050 EMI absorber.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The components arrived in two parcels, well packed.&lt;br /&gt;I found some surprises in the package, such as: a cap written with element14, stickers, a pin and especially the board for experiments without soldering, which has a very good quality.&lt;/p&gt;
&lt;p&gt;Thank you very much for these and for the opportunity to work with these components!&lt;br /&gt;Now follows their integration in my existing project.&lt;/p&gt;
&lt;p&gt;Thank you once again for everything!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>