<?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-security-and-surveillance/f/forum</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><lastBuildDate>Sun, 24 May 2026 17:49:48 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum" /><item><title>NetSentinel – Update 5: Full System Integration, Alert Display &amp; Lessons Le</title><link>https://community.element14.com/thread/56991?ContentTypeID=0</link><pubDate>Sun, 24 May 2026 17:49:48 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:5adac766-0451-42c8-9171-04d517ca08ef</guid><dc:creator>GustavoMorales</dc:creator><slash:comments>3</slash:comments><comments>https://community.element14.com/thread/56991?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56991/netsentinel-update-5-full-system-integration-alert-display-lessons-le/rss?ContentTypeId=0</wfw:commentRss><description>&lt;div&gt;
&lt;div&gt;
&lt;p&gt;This final post brings NetSentinel together as a complete system. The individual subsystems &amp;mdash; the network layer, the detection pipeline, the turret mechanism, and the alert display &amp;mdash; were built and tested independently across the previous blogs. Here they converge into a single coordinated response system. This blog covers the MAX Node 1 alert display firmware, the full integrated event flow, and an honest reflection on what worked, what did not, and what NetSentinel demonstrates about building distributed embedded security systems on real network infrastructure.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;strong&gt;MAX Node 1 &amp;mdash; The Operator Alert Panel&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;MAX Node 1 lives on the operator&amp;#39;s desk. Its job is simple and critical: make threats visible without requiring the operator to look at a screen. The CharlieWing 15x7 LED matrix provides that visibility &amp;mdash; a physical, always-on display that reacts to two completely independent threat vectors: physical intrusion from the field and network events from the infrastructure syslog feed.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;The firmware runs an HTTP server on port 8080. When the Raspberry Pi sends an alert POST to /alert, the MAX parses the message, classifies it, and drives the CharlieWing with the appropriate pattern.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;strong&gt;MAX Node 1 firmware &amp;mdash; CharlieWing alert display:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre class="ui-code" data-mode="text"&gt;/*
 * NetSentinel — MAX Node 1 Desktop Alert Panel
 * MAX32630FTHR + Particle Ethernet FeatherWing
 * + CharlieWing 15x7 LED Matrix
 *
 * Receives HTTP POST alerts from Raspberry Pi
 * Displays alert patterns on CharlieWing
 */

#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;Adafruit_IS31FL3731.h&amp;gt;

// ─── Configuration ────────────────────────────────────────
#define HTTP_PORT       8080
#define ALERT_MOTION    1
#define ALERT_NETWORK   2
#define ALERT_PHOTO     3

// ─── CharlieWing ──────────────────────────────────────────
Adafruit_CharlieWing matrix = Adafruit_CharlieWing();

// ─── Alert patterns ───────────────────────────────────────

// Motion detected — full matrix pulse
void pattern_motion() {
    for (int cycle = 0; cycle &amp;lt; 3; cycle++) {
        for (int brightness = 0; brightness &amp;lt; 255; brightness += 15) {
            for (int x = 0; x &amp;lt; 15; x++)
                for (int y = 0; y &amp;lt; 7; y++)
                    matrix.drawPixel(x, y, brightness);
            delay(10);
        }
        for (int brightness = 255; brightness &amp;gt; 0; brightness -= 15) {
            for (int x = 0; x &amp;lt; 15; x++)
                for (int y = 0; y &amp;lt; 7; y++)
                    matrix.drawPixel(x, y, brightness);
            delay(10);
        }
    }
    matrix.clear();
}

// Network event — scrolling row pattern
void pattern_network() {
    for (int pass = 0; pass &amp;lt; 4; pass++) {
        for (int row = 0; row &amp;lt; 7; row++) {
            matrix.clear();
            for (int x = 0; x &amp;lt; 15; x++)
                matrix.drawPixel(x, row, 180);
            delay(80);
        }
    }
    matrix.clear();
}

// Photo captured — center cross pattern
void pattern_photo() {
    matrix.clear();
    for (int x = 0; x &amp;lt; 15; x++) matrix.drawPixel(x, 3, 200);
    for (int y = 0; y &amp;lt; 7; y++)  matrix.drawPixel(7, y, 200);
    delay(1500);
    matrix.clear();
}

void display_alert(int alert_type) {
    switch (alert_type) {
        case ALERT_MOTION:  pattern_motion();  break;
        case ALERT_NETWORK: pattern_network(); break;
        case ALERT_PHOTO:   pattern_photo();   break;
    }
}

// ─── HTTP message parser ──────────────────────────────────
int classify_message(String message) {
    message.toLowerCase();
    if (message.indexOf(&amp;quot;motion&amp;quot;)  &amp;gt;= 0) return ALERT_MOTION;
    if (message.indexOf(&amp;quot;photo&amp;quot;)   &amp;gt;= 0) return ALERT_PHOTO;
    if (message.indexOf(&amp;quot;capture&amp;quot;) &amp;gt;= 0) return ALERT_PHOTO;
    return ALERT_NETWORK;  // default: treat as network event
}

void setup() {
    Serial.begin(115200);
    delay(1000);

    Wire.begin();
    if (!matrix.begin()) {
        Serial.println(&amp;quot;[ERROR] CharlieWing not found&amp;quot;);
        while (1);
    }
    matrix.clear();

    Serial.println(&amp;quot;=== NetSentinel Alert Panel ===&amp;quot;);
    Serial.println(&amp;quot;[READY] Waiting for alerts from RPi...&amp;quot;);

    // Startup pattern — brief sweep to confirm display is live
    pattern_network();
}

void loop() {
    // HTTP server logic handles incoming POST /alert
    // Message received → classify → display pattern
    if (Serial.available()) {
        String msg = Serial.readStringUntil(&amp;#39;\n&amp;#39;);
        msg.trim();
        if (msg.length() &amp;gt; 0) {
            Serial.print(&amp;quot;[ALERT] &amp;quot;);
            Serial.println(msg);
            int type = classify_message(msg);
            display_alert(type);
        }
    }
    delay(10);
}&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;&lt;strong&gt;Complete Integrated Event Flow&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;With all nodes online the full NetSentinel event flow works as follows.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;A person enters the datacenter. The HC-SR501 PIR output goes HIGH. The MAX32630FTHR on the turret reads the GPIO and simultaneously triggers the ESP32-CAM and sends MOTION_DETECTED to the Raspberry Pi. The ESP32-CAM captures a JPEG and POSTs it to the Pi&amp;#39;s /capture endpoint over WiFi. The Pi receives the motion event, pushes a MOTION DETECTED alert to MAX Node 1, sends the sweep trigger to MAX Node 2, and saves the timestamped photo. MAX Node 1 lights up the full matrix pulse pattern on the operator&amp;#39;s desk. MAX Node 2 executes the 180-degree pan sweep with the NEMA 17.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;Independently and in parallel, the FortiGate 90D, FortiGate 40F, and MikroTik RB3011 are continuously sending syslog to the Raspberry Pi on UDP port 514. When a relevant network event arrives &amp;mdash; a link state change, an authentication failure, an IPS alert &amp;mdash; the Pi parses and forwards it to MAX Node 1. The operator sees the scrolling row pattern, distinct from the motion pulse, and knows the event is network-originated.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p&gt;Two threat vectors. One operator panel. One physical response in the field.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The 3D Printed Turret &amp;mdash; Final Assembly&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The physical turret combines all field components into a single deployable unit. The NEMA 17 sits at the base coupled to the T8 lead screw through the red shaft coupler. The MAX32630FTHR stack &amp;mdash; board, Ethernet FeatherWing, DC+Stepper FeatherWing &amp;mdash; sits in the Fusion 360 printed enclosure adjacent to the motor with cables routed to the FeatherWing terminals. The ESP32-CAM in its modified printed case mounts at the top of the lead screw, oriented with the lens facing the sweep arc.&lt;/p&gt;
&lt;p&gt;The rotation is limited by firmware to 180 degrees in each direction to prevent cable wrap on the two power wires running up alongside the screw. In the final demonstration the sweep was performed manually to showcase the concept given a driver failure during integration testing &amp;mdash; the firmware, detection pipeline, and alert system all functioned correctly throughout.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&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-components-multipleuploadfilemanager/db08024c_2D00_4cfb_2D00_4f99_2D00_9edc_2D00_da1c78c1e724-446629-complete/pastedimage1779546550422v7.png" /&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-components-multipleuploadfilemanager/db08024c_2D00_4cfb_2D00_4f99_2D00_9edc_2D00_da1c78c1e724-446629-complete/pastedimage1779546573461v9.png" /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Raspberry Server&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-components-multipleuploadfilemanager/db08024c_2D00_4cfb_2D00_4f99_2D00_9edc_2D00_da1c78c1e724-446629-complete/pastedimage1779546701921v10.png" /&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre class="ui-code" data-mode="text"&gt;(venv) pi@Element14:~/netsentinel $ sudo venv/bin/python app.py
[sudo] password for pi:
[09:02:11] Syslog UDP escuchando en puerto 514
[09:02:11] Flask HTTP en puerto 5000
 * Serving Flask app &amp;#39;app&amp;#39;
 * Debug mode: off
[09:02:53] Alerta manual: ALERTA: login fallido en MikroTik
[09:02:54] Push OK → ALERTA: login fallido en MikroTik&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-components-multipleuploadfilemanager/db08024c_2D00_4cfb_2D00_4f99_2D00_9edc_2D00_da1c78c1e724-446629-complete/Demo.MOV"&gt;community.element14.com/.../Demo.MOV&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Several things became clear during this build that are worth documenting honestly.&lt;/p&gt;
&lt;p&gt;The stepper motor driver is the most fragile component in the system. The TB6612 on the Adafruit FeatherWing P2927D delivers 1.2A continuous per bridge. The NEMA 17HS19-2004S1 wants 2A per phase. Running the motor at full current during integration testing exceeded the driver&amp;#39;s thermal limits and damaged one of the two H-bridge channels. The lesson: always verify driver current rating against motor requirements before powering up, and add adequate delays between steps to reduce average current draw.&lt;/p&gt;
&lt;p&gt;Library compatibility with non-standard cores requires manual intervention. The Adafruit BusIO library defines BUSIO_USE_FAST_PINIO based on architecture detection macros. The MAX32630FTHR&amp;#39;s ARDUINO_MAXIM identifier was not in BusIO&amp;#39;s exclusion list, causing compilation failures. The fix required patching Adafruit_SPIDevice.h to add ARDUINO_MAXIM to the exclusion condition. This is the kind of issue that consumes hours if you do not know where to look.&lt;/p&gt;
&lt;p&gt;The Arduino IDE upload tool does not handle paths with spaces. The MAXDAP daplink.bat script fails when the sketch path contains spaces &amp;mdash; in this case C:\Users\Gustavo Morales. The workaround is drag-and-drop flashing directly to the DAPLINK USB drive, which works reliably.&lt;/p&gt;
&lt;p&gt;DMZ network architecture adds real complexity but real value. Running the Raspberry Pi in a properly segmented DMZ with firewall policies and OSPF routing is not the easy path for a weekend project. But it produces a system that behaves like real infrastructure, generates real syslog traffic, and demonstrates real security principles. That complexity is the point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What NetSentinel Demonstrates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NetSentinel is not a finished product. It is a proof of concept that demonstrates something specific: that a distributed embedded security system can be built on real network infrastructure, with proper network segmentation, using commodity embedded hardware, and produce coordinated physical responses to both network and physical threat events.&lt;/p&gt;
&lt;p&gt;The MAX32630FTHR proved capable as both an alert display controller and a motor control node. The Raspberry Pi as a DMZ-resident syslog aggregator and alert distributor works exactly as designed. The ESP32-CAM as a WiFi-connected evidence capture device integrated cleanly. The FortiGate and MikroTik infrastructure provided real syslog data throughout development.&lt;/p&gt;
&lt;p&gt;The mechanical pan mechanism worked in concept. The T8 lead screw driven by the NEMA 17 successfully rotates the camera platform. Driver thermal limits under continuous operation are a solvable problem with the right driver &amp;mdash; a DRV8825 or TMC2208 rated for 2A continuous would handle the 17HS19-2004S1 without issues.&lt;/p&gt;
&lt;p&gt;Building NetSentinel reconnected a network engineer with the embedded electronics side of the stack &amp;mdash; and demonstrated that the two disciplines, network infrastructure and embedded systems, are more complementary than they are separate.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thank you to element14 and the Smart Security and Surveillance Challenge for providing the hardware kit that made this project possible. The MAX32630FTHR is an underappreciated platform &amp;mdash; powerful, flexible, and worth far more exploration than it typically receives.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&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>You have too many oustanding abuse reports. Please respond to existing reports in your e-mail before posting.</title><link>https://community.element14.com/thread/56982?ContentTypeID=0</link><pubDate>Sun, 24 May 2026 14:21:02 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:dc0bc34f-e199-4610-b0e8-591aad968692</guid><dc:creator>Alistair</dc:creator><slash:comments>8</slash:comments><comments>https://community.element14.com/thread/56982?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56982/you-have-too-many-oustanding-abuse-reports-please-respond-to-existing-reports-in-your-e-mail-before-posting/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Well this is a fin howdedoo. The site has blocked my account when I was posing my final write up. It kept saying there was an error when I tried to save the draft, and then I was blocked for spam. I have filled in the form to get it unblocked, but that looks like a manual process, so I have created this second account to post the post before the deadline.&lt;/p&gt;
&lt;p&gt;I have removed the list links to my posts and useful links as that is probably what was causing it to be blocked. If we can sort it out then I will add them.&lt;/p&gt;
&lt;p&gt;Is anyone from Element14 in here able to help sort this mess out?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Integrating with Alexa using Virtual Smart Home (Don't Forger to Set)</title><link>https://community.element14.com/thread/56980?ContentTypeID=0</link><pubDate>Sat, 23 May 2026 15:15:56 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:be59f965-1626-4109-8509-816d3dd3d4d4</guid><dc:creator>Alistair</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/56980?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56980/integrating-with-alexa-using-virtual-smart-home-don-t-forger-to-set/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Just when you thought I was finished, here I am again. I was not planning to create a &amp;ldquo;how to&amp;rdquo; for this and only include it in the setup notes, but it has ballooned a little and is useful beyond the project so I thought I would post it here instead.&lt;/p&gt;
&lt;p&gt;As part of my build I need to activate a 3rd party alarm system. For me personally I could use an unofficial API, but that can break overnight and is only of use to someone with the same system as me. Not to mention that when I upgrade to a better system I will need to rewrite that part of the project. With that in mind I decided to take the unusual step of using Amazon&amp;rsquo;s Alexa. At first it may seem odd, but let me explain.&lt;/p&gt;
&lt;p&gt;There are many connected alarm systems, some with official APIs that allow integration with other systems (like what I am producing here), many more with unofficial APIs that are for internal use but someone has backwards engineered them, and some with no API at all. All the APIs are different and a separate integration would need to be created for each. However many systems have a form of Alexa integration that allows them to be armed using voice. This also allows Alexa routines (a routine being basic &amp;ldquo;if this happens then do that&amp;rdquo; feature within the Alexa ecosystem) to do the same when a button is pressed. All we need to do is to simulate a button being pressed and then we can arm the alarm automatically using their official integration from our code.&lt;/p&gt;
&lt;p&gt;While we could hack a hardware smart button such as an Echo button or Alexa compatible door bell, it is neater to create a virtual button and trigger it across the network. A few services already exist to do this and my preferred option is the URL Routine Trigger skill from Virtual Mart Home.&lt;/p&gt;
&lt;p&gt;You will need an Amazon account and the Alexa app installed to set up and configure things, but you do not need any Alexa hardware and you don&amp;rsquo;t need to pay any subscription.&lt;/p&gt;
&lt;p&gt;So once we have an Amazon account with the Alexa app installed, and you have linked your alarm system to it (normally through an option in your alarm&amp;rsquo;s app), we can create that virtual button and modify an Alexa routine to activate the alarm.&lt;/p&gt;
&lt;p&gt;To start go to &lt;a href="https://www.virtualsmarthome.xyz/url_routine_trigger/" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;www.virtualsmarthome.xyz/.../&lt;/a&gt;, click the &amp;ldquo;Login with Amazon&amp;rdquo; button, and follow the instructions. You will then see a screen like this&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img 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/452/virtualsmarthome.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now (1) enter a name for the virtual button (this can be anything) and (2) click Save. Once created click the down arrow (3) to show the URL information we need, and (4) copy the URL we need to trigger the button and keep it safe. It does not matter which of the URLs you copy as we will not be reading the returned data. Finally consider donating to this service (5) as it exists because of the generosity of the author. If you find yourself using it then do consider making a donation to support it.&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/Alexa-Routine.png" /&gt;&lt;/p&gt;
&lt;p&gt;After all that, open the Alexa App, click the &amp;ldquo;hamburger&amp;rdquo; button at the bottom, click Routines, and you should find a sample routine that has been created mirroring the name of the virtual button name you entered before. You can then add actions to do by clicking the &amp;ldquo;+&amp;rdquo; next to the very descriptive &amp;ldquo;Add another action&amp;rdquo; text. Arming an alarm is normally under Smart Home and Security Panels, but that depends on your exact alarm setup.&lt;/p&gt;
&lt;p&gt;Finally the URL that was noted down needs adding to the configuration at the top of the source code.&lt;/p&gt;
&lt;p&gt;That is it. I hope to have the final writeup posed later today.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Sentinel Box - Part V - Concept vs Perfect Build</title><link>https://community.element14.com/thread/56979?ContentTypeID=0</link><pubDate>Sat, 23 May 2026 09:55:53 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ad3077d4-e0e7-4806-bac0-f6e90581549b</guid><dc:creator>saramic</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/56979?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56979/sentinel-box---part-v---concept-vs-perfect-build/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;The competition ends tomorrow and I have fallen in a heap a week ago. I need to re-group on what I can achieve with my abilities, and be content with that. It will not be the perfect build I was hoping for, it may only partly touch on the concept I am aiming for, but such is life.&lt;/p&gt;
&lt;h2 id="recap"&gt;Recap&lt;/h2&gt;
&lt;p&gt;The idea is to build a smart lock box for digital devices to help control digital addiction, more on the idea can be found in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part I&lt;/code&gt;&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and coding with LPSDK and accessing a fingerprint scanner in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part II&lt;/code&gt;&lt;/strong&gt;, and mechanical stepper motors and vault lock mechanisms in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part III&lt;/code&gt;&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and Bluetooth and BTStack in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part IV&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56869/sentinel-box---part-i---the-plan" data-e14adj="t"&gt;Sentinel Box - Part I - the plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56894/sentinel-box---part-ii---back-to-c" data-e14adj="t"&gt;Sentinel Box - Part II - back to C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56937/sentinel-box---part-iii---stepper-motor-and-vault-lock-mechanism" data-e14adj="t"&gt;Sentinel Box - Part III - Stepper Motor and Vault lock mechanism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56942/sentinel-box---part-iv---bluetooth-and-btstack" data-e14adj="t"&gt;Sentinel Box - Part IV - Bluetooth and BTStack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="perfect-build"&gt;Perfect Build&lt;/h2&gt;
&lt;p&gt;Looking back honestly, I have learnt an enormous amount across this challenge. I attempted a fully hermetic&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;build, maybe next time. I did, with the help of the amazing Element 14 community, get to successfully drive a stepper motor, fingerprint scanner and connected&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Bluetooth&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;all for the first time. My final piece was a vault mechanism that look great in initial previews and I was genuinely excited about completing.&lt;/p&gt;
&lt;p&gt;The perspex work is where the gap between concept and reality opened up. Precision mechanical assembly&amp;nbsp;requires&amp;nbsp;tolerance, and I underestimated it badly. Only today I had been watching Clickspring&amp;rsquo;s extraordinary series on building an&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://www.youtube.com/watch?v=dRXI9KLImC4&amp;amp;list=PLZioPDnFPNsHnyxfygxA0to4RXv4_jDU2" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Antikythera mechanism (YouTube)&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and there is something humbling about watching someone fit-and-file a part to within a tenth of a millimetre with hand tools. My lock mechanism needed that same care. It did not get it. I cut fast, missed a few steps and thought it better try when I had the right tools and patience to actually get it right and build a mechanism that was &amp;ldquo;square&amp;rdquo;, worked and worthy of display.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img 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/452/20260523_5F00_vault_5F00_and_5F00_door_5F00_mechanism_5F00_in_5F00_build.jpg"  /&gt;&lt;/p&gt;
&lt;p&gt;The final week did not help. A hectic schedule, a weekend away from home and tools. Even though I was excited about the mechanical build, the perspex was not as forgiving as re-burning a new build onto the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX32630FTHR&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What I&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;em&gt;did&lt;/em&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;get started on is expanding the Bluetooth communications layer with the browser. As the theoretical setup would need stepper motor setting, reading a number of finger prints and setting up a consensus framework for who can co-operatively open the lock box, doing this via a web site seemed the way to go. The foundation is super sound:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;React 19&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;for a&amp;nbsp;modern frontend&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lit 3&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;hybrid with the React to allow for a custom&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;web component&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;code class="language-plaintext highlighter-rouge"&gt;&amp;lt;sentinel-ble-manager&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shadcn + Radix UI + Tailwind CSS&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;for styling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vite 8&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as the build&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The part I am most pleased with is that the browser and the firmware speak exactly the same binary protocol. The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX32630FTHR&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;stores its config in a 100-byte block in INFO flash, and the web console encodes and decodes the identical layout &amp;mdash; offsets and all &amp;mdash; using&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;DataView&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Uint8Array&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;view.setUint16(0x00, CONFIG_MAGIC, true)   // magic  0x5B5A (&amp;quot;SB&amp;quot; LE)
view.setUint16(0x02, cfg.vaultSteps, true) // vault_steps
buf[0x04] = enrolledCount                  // fp_count
buf[0x05] = cfg.unlockPolicy               // unlock_policy
buf[0x06] = cfg.relockMinutes              // relock_minutes
// fp_name[10]: 8 bytes each starting at 0x08
// fp_role[10]: 1 byte each starting at 0x58
view.setUint16(CRC_OFFSET, crc, true)      // CRC-16/CCITT over bytes 0x00–0x61
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;To make sure nothing gets corrupted in transit the browser runs the same&amp;nbsp;&lt;/span&gt;&lt;strong&gt;CRC-16/CCITT&lt;/strong&gt;&lt;span&gt;&amp;nbsp;the firmware uses, so a tampered or truncated blob is caught at both ends:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;export function crc16(data: Uint8Array): number {
  let crc = 0xffff
  for (const byte of data) {
    crc ^= byte &amp;lt;&amp;lt; 8
    for (let i = 0; i &amp;lt; 8; i++) {
      crc = crc &amp;amp; 0x8000 ? ((crc &amp;lt;&amp;lt; 1) ^ 0x1021) &amp;amp; 0xffff : (crc &amp;lt;&amp;lt; 1) &amp;amp; 0xffff
    }
  }
  return crc
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is not the kind of JavaScript you write every day, but it is satisfying when the numbers match on both sides of the BLE link.&lt;/p&gt;
&lt;p&gt;&lt;span&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/452/20260523_5F00_Red_5F00_Green_5F00_Blue_5F00_via_5F00_bluetooth.gif" width="720"  /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So the build is not what I imagined. The vault door is not ready, the full orchestration of fingerprint plus Bluetooth plus stepper motor is het to run end-to-end. But the pieces exist. The concept holds. I know now exactly which joints need filing to tolerance and which parts of the stack are solid. That is not failure, that is a prototype.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="next"&gt;Next&lt;/h2&gt;
&lt;p&gt;Well it&amp;rsquo;s crunch time, next step the full write up at&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/b/projects/posts/sentinel-box---consensus-based-lock-box" data-e14adj="t"&gt;Sentinel box: consensus based lock box&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="source"&gt;Source&lt;/h2&gt;
&lt;p&gt;&lt;a id="" href="https://github.com/saramic/sentinel-box" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://github.com/saramic/sentinel-box&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>It all works!</title><link>https://community.element14.com/thread/56974?ContentTypeID=0</link><pubDate>Thu, 21 May 2026 21:37:29 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:2904b7a2-dadb-4b47-8584-a959deeb8465</guid><dc:creator>Alistair</dc:creator><slash:comments>4</slash:comments><comments>https://community.element14.com/thread/56974?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56974/it-all-works/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Good news. Yesterday I managed to get everything working and a case tidied. Today I did some more serious testing. In short the hard work is done and I juts need to get&amp;nbsp;the final writeup done. Yay!&lt;/p&gt;
&lt;p&gt;&lt;img 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/452/IMG_5F00_20260521_5F00_143650813.jpg" /&gt;Thank you to all who have helped or participated. It has ben great working with you.&amp;nbsp;I hope you are as happy with your build as I am. As&amp;nbsp;mine turned out mostly software based around stock hardware I suspect it is not going to be seen as a winner, but it has been enjoyable to create.&amp;nbsp;I have a device that I will actually be using in real life, and perhaps some of my work will carry forward in other people&amp;#39;s projects and give more life to a useful little dev board. I will add that I have really enjoyed the challenge of&amp;nbsp;solving all these problems. Some of the issues were so abstract I am surprised I figured it out, but that made it more rewarding&amp;nbsp;when I found solution.&lt;/p&gt;
&lt;p&gt;If anyone has any questions that I might be able to help with the feel free to reach out.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>NetSentinel – Update 3: Network Architecture, Firewall Configuration &amp; Raspberry Pi Core</title><link>https://community.element14.com/thread/56969?ContentTypeID=0</link><pubDate>Wed, 20 May 2026 21:29:54 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:eaabae9b-69e8-47f8-82a9-66c151eedd26</guid><dc:creator>GustavoMorales</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/56969?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56969/netsentinel-update-3-network-architecture-firewall-configuration-raspberry-pi-core/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;The network layer is what separates NetSentinel from a standalone gadget. The Raspberry Pi at the core of the system does not sit on a flat home network &amp;mdash; it lives in a properly segmented DMZ, receives syslog from real enterprise firewall and routing equipment, and distributes processed alerts to the field and desktop nodes. This blog covers the full network architecture, the OSPF routing configuration, the firewall policies, and the Flask application running on the Raspberry Pi.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Topology Overview&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The network was built on infrastructure originally designed for an MSc Cybersecurity lab at Universidad Galileo. Three devices form the routing and security backbone.&lt;/p&gt;
&lt;p&gt;The FortiGate 90D is the exterior firewall. It connects to the simulated internet upstream and provides the first security boundary. Its internal interface connects to the MikroTik RB3011 on a /30 transit link.&lt;/p&gt;
&lt;p&gt;The MikroTik RB3011 is the central routing node. It has three relevant interfaces: ether1 connecting upstream to the FG-90D, ether4 hosting the DMZ segment where the Raspberry Pi lives, and ether2 connecting downstream to the FG-40F.&lt;/p&gt;
&lt;p&gt;The FortiGate 40F is the interior firewall protecting the LAN where both MAX nodes reside.&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/452/pastedimage1779290622384v5.png" /&gt;&lt;/p&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/452/pastedimage1779290663776v6.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OSPF Configuration &amp;mdash; Area 0&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dynamic routing runs OSPF Area 0 across all three devices. No static routes were used &amp;mdash; every segment is reachable through OSPF redistribution.&lt;/p&gt;
&lt;p&gt;FortiGate 90D:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;config router ospf
  set router-id 10.20.30.1
  set default-information-originate enable
  config area
    edit 0.0.0.0
    next
  end
  config network
    edit 1
      set prefix 192.168.10.0 255.255.255.252
    next
  end
  config redistribute &amp;quot;connected&amp;quot;
    set status enable
  end
end&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;MikroTik RB3011:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/routing ospf instance
add name=default router-id=10.20.30.0

/routing ospf network
add network=192.168.10.0/30 area=backbone
add network=192.168.20.0/30 area=backbone
add network=192.168.2.0/24  area=backbone&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;FortiGate 40F:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;config router ospf
  set router-id 10.20.30.3
  config area
    edit 0.0.0.0
    next
  end
  config network
    edit 1
      set prefix 192.168.20.0 255.255.255.252
    next
    edit 2
      set prefix 192.168.4.0 255.255.255.0
    next
  end
  config redistribute &amp;quot;connected&amp;quot;
    set status enable
  end
end&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Firewall Policies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The policies follow least-privilege: only explicitly required traffic is permitted. The DMZ design principle holds &amp;mdash; the Raspberry Pi can receive connections from all segments but cannot initiate connections toward the LAN.&lt;/p&gt;
&lt;p&gt;FortiGate 90D &amp;mdash; Internet to DMZ (syslog and management):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;config firewall policy
  edit 1
    set name &amp;quot;internet-to-dmz&amp;quot;
    set srcintf &amp;quot;wan1&amp;quot;
    set dstintf &amp;quot;internal10&amp;quot;
    set srcaddr &amp;quot;all&amp;quot;
    set dstaddr &amp;quot;RPi-DMZ&amp;quot;
    set action accept
    set service &amp;quot;HTTPS&amp;quot; &amp;quot;SSH&amp;quot;
    set schedule &amp;quot;always&amp;quot;
    set logtraffic all
  next
  edit 2
    set name &amp;quot;dmz-to-internet&amp;quot;
    set srcintf &amp;quot;internal10&amp;quot;
    set dstintf &amp;quot;wan1&amp;quot;
    set srcaddr &amp;quot;DMZ-Net&amp;quot;
    set dstaddr &amp;quot;all&amp;quot;
    set action accept
    set nat enable
    set schedule &amp;quot;always&amp;quot;
    set logtraffic all
  next
end&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;FortiGate 40F &amp;mdash; LAN to DMZ (MAX nodes reaching RPi):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;config firewall policy
  edit 1
    set name &amp;quot;lan-to-dmz&amp;quot;
    set srcintf &amp;quot;lan&amp;quot;
    set dstintf &amp;quot;wan1&amp;quot;
    set srcaddr &amp;quot;LAN-Net&amp;quot;
    set dstaddr &amp;quot;RPi-DMZ&amp;quot;
    set action accept
    set service &amp;quot;HTTP&amp;quot; &amp;quot;UDP-514&amp;quot;
    set schedule &amp;quot;always&amp;quot;
    set logtraffic all
  next
  edit 2
    set name &amp;quot;dmz-to-lan-block&amp;quot;
    set srcintf &amp;quot;wan1&amp;quot;
    set dstintf &amp;quot;lan&amp;quot;
    set srcaddr &amp;quot;DMZ-Net&amp;quot;
    set dstaddr &amp;quot;LAN-Net&amp;quot;
    set action deny
    set logtraffic all
  next
end&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Syslog forwarding &amp;mdash; FortiGate 90D and 40F:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;config log syslogd setting
  set status enable
  set server &amp;quot;192.168.2.200&amp;quot;
  set port 514
  set facility local7
  set format default
end

config log syslogd filter
  set severity information
  set forward-traffic enable
  set local-traffic enable
  set sniffer-traffic disable
  set anomaly enable
end&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;MikroTik RB3011 syslog&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/system logging action
set remote address=192.168.2.200 remote-port=514 \
    name=netsentinel src-address=0.0.0.0 target=remote

/system logging
add action=netsentinel topics=info
add action=netsentinel topics=warning
add action=netsentinel topics=error&lt;/pre&gt;:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Raspberry Pi &amp;mdash; Flask Application&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Flask app on the Raspberry Pi runs two services simultaneously: a UDP syslog listener on port 514 and an HTTP Flask server on port 5000. When a syslog message arrives from the FortiGates or MikroTik, it is parsed, cleaned, and forwarded as an alert to MAX Node 1 over HTTP. When a motion event arrives from the field, the same pipeline triggers the alert display and sends the sweep command to MAX Node 2.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;from flask import Flask, request, jsonify
from datetime import datetime
import requests
import socketserver
import threading
import logging

# ─── Configuration ────────────────────────────────────────
MAX_ALERT_IP   = &amp;quot;192.168.4.XX&amp;quot;   # MAX Node 1 — desktop alert panel
MAX_TURRET_IP  = &amp;quot;192.168.4.YY&amp;quot;   # MAX Node 2 — field turret
MAX_PORT       = 8080
SYSLOG_PORT    = 514

app = Flask(__name__)
logging.getLogger(&amp;#39;werkzeug&amp;#39;).setLevel(logging.ERROR)

# ─── Push alert to MAX Node 1 (desktop panel) ─────────────
def push_to_max(message):
    try:
        r = requests.post(
            f&amp;quot;http://{MAX_ALERT_IP}:{MAX_PORT}/alert&amp;quot;,
            json={&amp;quot;message&amp;quot;: message},
            timeout=3
        )
        print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Push OK → {message}&amp;quot;)
    except Exception as e:
        print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Push error: {e}&amp;quot;)

# ─── Send sweep trigger to MAX Node 2 (turret) ────────────
def trigger_sweep():
    try:
        requests.post(
            f&amp;quot;http://{MAX_TURRET_IP}:{MAX_PORT}/sweep&amp;quot;,
            json={&amp;quot;command&amp;quot;: &amp;quot;SCAN_TRIGGER&amp;quot;},
            timeout=3
        )
        print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Sweep triggered&amp;quot;)
    except Exception as e:
        print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Sweep error: {e}&amp;quot;)

# ─── UDP Syslog listener ───────────────────────────────────
class SyslogHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        try:
            message = data.decode(&amp;#39;utf-8&amp;#39;, errors=&amp;#39;ignore&amp;#39;)
        except:
            return
        print(f&amp;quot;[SYSLOG] {message}&amp;quot;)
        # Strip syslog priority header &amp;lt;PRI&amp;gt;
        clean = message
        if clean.startswith(&amp;#39;&amp;lt;&amp;#39;):
            end = clean.find(&amp;#39;&amp;gt;&amp;#39;)
            if end != -1:
                clean = clean[end+1:].strip()
        parts = clean.split()
        if len(parts) &amp;gt; 4:
            clean = &amp;#39; &amp;#39;.join(parts[3:])
        # Forward cleaned message to alert panel
        push_to_max(clean[:60])

# ─── Flask endpoints ───────────────────────────────────────
@app.route(&amp;#39;/alert&amp;#39;, methods=[&amp;#39;POST&amp;#39;])
def receive_alert():
    data = request.get_json()
    message = data.get(&amp;#39;message&amp;#39;, &amp;#39;&amp;#39;)
    print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Alert received: {message}&amp;quot;)
    push_to_max(message)
    trigger_sweep()
    return jsonify({&amp;quot;status&amp;quot;: &amp;quot;ok&amp;quot;}), 200

@app.route(&amp;#39;/motion&amp;#39;, methods=[&amp;#39;POST&amp;#39;])
def receive_motion():
    print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Motion event from field&amp;quot;)
    push_to_max(&amp;quot;MOTION DETECTED&amp;quot;)
    trigger_sweep()
    return jsonify({&amp;quot;status&amp;quot;: &amp;quot;ok&amp;quot;}), 200

@app.route(&amp;#39;/status&amp;#39;, methods=[&amp;#39;GET&amp;#39;])
def status():
    return jsonify({&amp;quot;status&amp;quot;: &amp;quot;NetSentinel online&amp;quot;}), 200

# ─── Startup ───────────────────────────────────────────────
if __name__ == &amp;#39;__main__&amp;#39;:
    syslog_server = socketserver.UDPServer(
        (&amp;#39;0.0.0.0&amp;#39;, SYSLOG_PORT), SyslogHandler
    )
    syslog_thread = threading.Thread(
        target=syslog_server.serve_forever
    )
    syslog_thread.daemon = True
    syslog_thread.start()
    print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Syslog UDP listening on port {SYSLOG_PORT}&amp;quot;)
    print(f&amp;quot;[{datetime.now().strftime(&amp;#39;%H:%M:%S&amp;#39;)}] Flask HTTP on port 5000&amp;quot;)
    app.run(host=&amp;#39;0.0.0.0&amp;#39;, port=5000, debug=False)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Running the application:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;cd ~/netsentinel
source venv/bin/activate
sudo python3 app.py&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Sudo is required for binding to port 514 which is a privileged port below 1024.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Event Flow Summary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When a FortiGate detects a threat or a link state changes, it sends a syslog UDP packet to 192.168.2.200 port 514. The SyslogHandler parses the message, strips the priority header, and calls push_to_max() which sends an HTTP POST to MAX Node 1. The CharlieWing lights up the alert pattern on the operator&amp;#39;s desk.&lt;/p&gt;
&lt;p&gt;When the PIR fires in the field, the ESP32-CAM sends an HTTP POST to the /motion endpoint. The RPi simultaneously calls push_to_max() to alert the operator and trigger_sweep() to start the NEMA 17 pan sequence on MAX Node 2.&lt;/p&gt;
&lt;p&gt;Two completely independent threat vectors &amp;mdash; network events and physical intrusion &amp;mdash; converging at a single processing node and producing coordinated responses at two physical endpoints.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;What Comes Next&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next blog covers the detection pipeline in detail &amp;mdash; the PIR sensor, the ESP32-CAM, and how photographic evidence is captured and logged the moment motion is detected.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>You can Now Post your Final Round-Up Project Blog</title><link>https://community.element14.com/thread/56970?ContentTypeID=0</link><pubDate>Wed, 20 May 2026 16:16:35 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:4f714742-4ffc-4a1e-875d-17ead259ea9d</guid><dc:creator>cstanton</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/56970?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56970/you-can-now-post-your-final-round-up-project-blog/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Hey everyone,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/b/projects"&gt;Projects&lt;/a&gt;&amp;nbsp;is available for you to write up your final project overview/summary.&lt;/p&gt;
&lt;p&gt;Remember Design Challenges encourage you to provide updates here in the forums while you build, and then for your final &amp;#39;presentation&amp;#39; your full write up, videos, images, etc are for the final blog post.&lt;/p&gt;
&lt;p&gt;The&amp;nbsp;specific requirements being:&lt;/p&gt;
&lt;p&gt;&amp;quot;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/dc/dc/81/smart_security_and_s" data-e14adj="t"&gt;at least 5 forum thread updates and 1 project blog before the closing date&lt;/a&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;Looking forward to seeing the round up posts!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>NetSentinel – Update 2: 3D Printed Turret Enclosure &amp; Physical Design</title><link>https://community.element14.com/thread/56967?ContentTypeID=0</link><pubDate>Tue, 19 May 2026 21:53:39 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:996e23b6-9f38-4342-92c1-e6710bbbe696</guid><dc:creator>GustavoMorales</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/56967?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56967/netsentinel-update-2-3d-printed-turret-enclosure-physical-design/rss?ContentTypeId=0</wfw:commentRss><description>&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/452/NetSentinel.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;A distributed embedded security system needs a physical presence that matches its purpose. For NetSentinel&amp;#39;s field node &amp;mdash; the turret that houses the MAX32630FTHR, the ESP32-CAM, and the NEMA 17 stepper motor &amp;mdash; a custom enclosure was designed in Fusion 360 and printed on a Voxelab Aquila X2. This blog covers the design process, the mechanical concept, and the physical assembly.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Two Nodes, Two Physical Forms&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The two MAX nodes have completely different physical forms reflecting their different roles.&lt;/p&gt;
&lt;p&gt;MAX Node 1 lives on the operator&amp;#39;s desk. It is built on the Particle Ethernet FeatherWing ProtoBoard with the MAX32630FTHR in slot 2 and the CharlieWing 15x7 LED matrix in slot 3. Its enclosure is compact and oriented so the LED matrix is always visible to the operator. This node does not move &amp;mdash; its job is to be seen.&lt;/p&gt;
&lt;p&gt;MAX Node 2 is the field turret. It needed a mechanical design that could rotate a camera through a surveillance arc, house a full Feather stack, and do it all with components already on hand. The solution came from an unexpected place: a lead screw from a 3D printer Z axis.&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/452/pastedimage1779206005219v3.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;The Lead Screw Mechanism&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The pan mechanism is built around a T8 lead screw &amp;mdash; the same Tr8x8 trapezoidal ACME thread used in the Z axis of FDM printers. The NEMA 17 stepper motor (17HS19-2004S1, 200 steps/rev, 2A/phase) drives the lead screw directly through the motor&amp;#39;s shaft coupler. Rather than using the lead screw for linear motion as it would in a printer, here it acts as a rotating vertical axis &amp;mdash; the NEMA spins the screw and the ESP32-CAM mounted at the top of the screw rotates with it, sweeping the surveillance arc.&lt;/p&gt;
&lt;p&gt;The base connection is minimal by design: the lead screw couples directly to the NEMA 17 shaft through the red coupler that came with the screw, with no additional printed parts at the base. This kept the mechanical design simple and the motor easily replaceable.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;ESP32-CAM Mount &amp;mdash; Fusion 360 Modification&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The ESP32-CAM mount at the top of the lead screw was designed in Fusion 360. Rather than modeling from scratch, an existing ESP32-CAM case was downloaded as a base and modified directly. The key addition was a square block on the lateral face of the case with a hole sized for the T8 screw &amp;mdash; 8.5mm diameter with a T8 ACME thread profile. This block positions the camera at the correct height on the screw and keeps it oriented with the lens facing outward through the sweep arc.&lt;/p&gt;
&lt;p&gt;The T8 thread in the printed block acts as the mounting point &amp;mdash; the case screws onto the lead screw at the desired height and stays fixed there while the whole assembly rotates with the NEMA.&lt;/p&gt;
&lt;p&gt;Cable management for the ESP32-CAM was straightforward: since the ESP32-CAM communicates over WiFi, only two wires run up the screw &amp;mdash; power and ground. These were left with enough slack to allow the full 180-degree sweep without binding, and the firmware limits rotation to prevent a full 360-degree turn that would tangle the cables.&lt;br /&gt;&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/452/pastedimage1779205827876v2.png" /&gt;&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Print Settings &amp;mdash; Voxelab Aquila X2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All printed parts were produced on the Voxelab Aquila X2 in PLA. Layer height was 0.2mm for the main enclosure bodies and 0.15mm for the ESP32-CAM mount where the thread accuracy matters most. Infill was 20% gyroid. Print temperature was 200&amp;deg;C with the bed at 60&amp;deg;C. No supports were needed on any of the pieces.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Assembly Sequence&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Assembly starts at the NEMA 17. The motor mounts to the base surface and the T8 lead screw couples to the shaft through the red coupler. The MAX32630FTHR stack &amp;mdash; board, Ethernet FeatherWing, and DC+Stepper FeatherWing &amp;mdash; sits in its enclosure adjacent to the motor with cables routed to the FeatherWing terminals. The ESP32-CAM case threads onto the top of the lead screw at the desired height. Power cables run up alongside the screw with a small spiral of slack to accommodate the sweep rotation.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;What Comes Next&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With the physical build complete, the next blog goes into the network layer &amp;mdash; the dual-firewall DMZ topology, OSPF routing across FortiGate 90D, FortiGate 40F, and MikroTik RB3011, syslog forwarding to the Raspberry Pi, and the firewall policies that define what each segment can reach.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>NetSentinel – Update 1: Project Overview &amp; System Design</title><link>https://community.element14.com/thread/56966?ContentTypeID=0</link><pubDate>Tue, 19 May 2026 21:18:03 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:7244ceff-6d32-4ab3-90ed-cca577560a28</guid><dc:creator>GustavoMorales</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/56966?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56966/netsentinel-update-1-project-overview-system-design/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;br /&gt;Security monitoring has two dimensions that are rarely combined in a single embedded system: physical intrusion detection and network event awareness. NetSentinel was built for the element14 Smart Security and Surveillance Challenge to address both simultaneously &amp;mdash; a distributed embedded SOC (Security Operations Center) node that detects movement in a datacenter environment, captures photographic evidence, performs an automated pan sweep, and delivers real-time visual alerts to an operator at their desk, all while also displaying network-level alerts from syslog sources across the infrastructure.&lt;/p&gt;
&lt;p&gt;This is not a single-device security camera. It is a multi-node distributed system running on enterprise-grade network infrastructure.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;The Two Nodes &amp;mdash; Two Roles&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NetSentinel is built around two MAX32630FTHR Feather boards, each with a completely different role and physical location.&lt;/p&gt;
&lt;p&gt;MAX Node 1 lives on the operator&amp;#39;s desk. It drives a CharlieWing LED matrix that serves as a physical alert panel. When something happens &amp;mdash; either a motion detection event in the field or a network change event captured via syslog from FortiGates, MikroTik routers, or switches &amp;mdash; the operator sees an immediate visual alert on the display. No screen required, no application to check. The alert comes to the operator physically.&lt;/p&gt;
&lt;p&gt;MAX Node 2 lives in the field, mounted on a turret enclosure printed on a Voxelab Aquila X2. When the Raspberry Pi sends it a trigger over UDP, it drives a NEMA 17 stepper motor through an Adafruit DC+Stepper FeatherWing (P2927D) to perform a 180-degree surveillance sweep of the area where motion was detected. An ESP32-CAM module captures photographic evidence in parallel the moment the PIR fires, before the sweep even begins.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;The Brain &amp;mdash; Raspberry Pi in the DMZ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Raspberry Pi is the central processing node. It sits in the DMZ of the network topology and has two inputs and two outputs.&lt;/p&gt;
&lt;p&gt;On the input side it receives syslog from network infrastructure &amp;mdash; FortiGate firewalls, MikroTik routers, and switches &amp;mdash; and it receives motion detection events from the ESP32-CAM and PIR sensor in the field. On the output side it forwards processed alerts to MAX Node 1 for visual display, and it sends UDP trigger packets to MAX Node 2 to initiate the pan sweep.&lt;/p&gt;
&lt;p&gt;The full event flow looks like this:&lt;/p&gt;
&lt;div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100"&gt;
&lt;div class="sticky opacity-0 group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 top-2 py-2 h-12 w-0 float-right"&gt;
&lt;div class="absolute right-0 h-8 px-2 items-center inline-flex z-10"&gt;
&lt;div class="relative"&gt;
&lt;div class="transition-all opacity-100 scale-100"&gt;&lt;/div&gt;
&lt;div class="absolute inset-0 flex items-center justify-center"&gt;
&lt;div class="transition-all opacity-0 scale-50"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-x-auto"&gt;
&lt;pre class="code-block__code !my-0 !rounded-lg !text-sm !leading-relaxed p-3.5"&gt;&lt;code&gt;&lt;span&gt;FIELD (Datacenter / Turret):
&lt;/span&gt;&lt;span&gt;[PIR sensor] ──► motion detected
&lt;/span&gt;&lt;span&gt;[ESP32-CAM] ──► photo captured ──► RPi
&lt;/span&gt;&lt;span&gt;[MAX Node 2] ◄── UDP trigger ◄── RPi ──► NEMA 17 sweep
&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;BRAIN (DMZ):
&lt;/span&gt;&lt;span&gt;[Raspberry Pi 192.168.2.200]
&lt;/span&gt;&lt;span&gt;    ◄── syslog from FortiGate 90D, FortiGate 40F,
&lt;/span&gt;&lt;span&gt;        MikroTik RB3011, switches
&lt;/span&gt;&lt;span&gt;    ◄── motion events from ESP32-CAM / PIR
&lt;/span&gt;&lt;span&gt;    ──► alert packets to MAX Node 1
&lt;/span&gt;&lt;span&gt;    ──► sweep trigger to MAX Node 2
&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;OPERATOR DESK:
&lt;/span&gt;&lt;span&gt;[MAX Node 1 + CharlieWing]
&lt;/span&gt;&lt;span&gt;    ◄── physical intrusion alerts
&lt;/span&gt;&lt;span&gt;    ◄── network change alerts (syslog)
&lt;/span&gt;&lt;span&gt;    ──► visual LED display to operator&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Network Architecture&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NetSentinel was deployed on a dual-firewall DMZ architecture originally designed for an MSc Cybersecurity lab at Universidad Galileo. This gave the project a realistic enterprise network context rather than a flat home lab.&lt;/p&gt;
&lt;p&gt;The topology uses a FortiGate 90D as the exterior firewall, a MikroTik RB3011 as the central routing node, and a FortiGate 40F as the interior firewall protecting the LAN where the MAX nodes reside.&lt;/p&gt;
&lt;div class="relative group/copy bg-bg-000/50 border-0.5 border-border-400 rounded-lg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-100"&gt;
&lt;div class="sticky opacity-0 group-hover/copy:opacity-100 group-focus-within/copy:opacity-100 top-2 py-2 h-12 w-0 float-right"&gt;
&lt;div class="absolute right-0 h-8 px-2 items-center inline-flex z-10"&gt;
&lt;div class="relative"&gt;
&lt;div class="transition-all opacity-100 scale-100"&gt;&lt;/div&gt;
&lt;div class="absolute inset-0 flex items-center justify-center"&gt;
&lt;div class="transition-all opacity-0 scale-50"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-x-auto"&gt;
&lt;pre class="code-block__code !my-0 !rounded-lg !text-sm !leading-relaxed p-3.5"&gt;&lt;code&gt;&lt;span&gt;Internet
&lt;/span&gt;&lt;span&gt;    |
&lt;/span&gt;&lt;span&gt;[FortiGate 90D] &amp;mdash; 192.168.10.1/30
&lt;/span&gt;&lt;span&gt;    |
&lt;/span&gt;&lt;span&gt;[MikroTik RB3011]
&lt;/span&gt;&lt;span&gt;    |&amp;mdash; ether4: 192.168.2.1/24  &amp;larr; DMZ
&lt;/span&gt;&lt;span&gt;    |       |
&lt;/span&gt;&lt;span&gt;    |   [Raspberry Pi &amp;mdash; NetSentinel Core]
&lt;/span&gt;&lt;span&gt;    |   192.168.2.200
&lt;/span&gt;&lt;span&gt;    |
&lt;/span&gt;&lt;span&gt;    |&amp;mdash; ether2: 192.168.20.1/30
&lt;/span&gt;&lt;span&gt;    |
&lt;/span&gt;&lt;span&gt;[FortiGate 40F]
&lt;/span&gt;&lt;span&gt;    |&amp;mdash; LAN: 192.168.4.0/24
&lt;/span&gt;&lt;span&gt;            |
&lt;/span&gt;&lt;span&gt;        [MAX Node 1 &amp;mdash; Operator Alert Panel]
&lt;/span&gt;&lt;span&gt;        [MAX Node 2 &amp;mdash; Field Turret Controller]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&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/452/pastedimage1779202919273v2.png" /&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;OSPF Area 0 runs across all three routing devices, providing full dynamic reachability without static routes. The Raspberry Pi in the DMZ can receive syslog and events from all segments but cannot initiate connections toward the LAN &amp;mdash; a clean security boundary that reflects real DMZ design principles.&lt;/p&gt;
&lt;p&gt;The FortiGates and MikroTik forward syslog to the Raspberry Pi at 192.168.2.200. The Pi processes those logs and determines which events warrant a visual alert on the operator panel.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;Hardware Summary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The complete bill of materials for NetSentinel includes the Raspberry Pi 4 as the central node, two MAX32630FTHR boards for the alert panel and turret controller, a Particle Ethernet FeatherWing for wired connectivity on each MAX board, an Adafruit CharlieWing LED matrix for the operator display, an Adafruit DC+Stepper FeatherWing P2927D for stepper motor control, a NEMA 17 stepper motor (17HS19-2004S1, 200 steps/rev, 2A/phase) for the pan mechanism, an ESP32-CAM for photographic evidence capture, a PIR sensor as the primary motion trigger, and a Voxelab Aquila X2 3D printer for the custom turret enclosure.&lt;/p&gt;
&lt;hr class="border-border-200 border-t-0.5 my-3 mx-1.5" /&gt;
&lt;p&gt;&lt;strong&gt;What Comes Next&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The following blogs will cover each subsystem in detail: the 3D printed turret enclosure, the network configuration and firewall policies, the PIR and ESP32-CAM detection pipeline, the stepper motor pan mechanism, and the full system integration.&lt;/p&gt;
&lt;p&gt;NetSentinel demonstrates that embedded security systems do not have to be isolated gadgets &amp;mdash; with the right network architecture they become nodes in a real security infrastructure.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Anyone else having PAN1326C2 initialisation problems after a power cycle?</title><link>https://community.element14.com/thread/56957?ContentTypeID=0</link><pubDate>Tue, 19 May 2026 11:06:23 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:f36dc6ee-b0a4-43fb-b025-893700aa392d</guid><dc:creator>Alistair</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/56957?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56957/anyone-else-having-pan1326c2-initialisation-problems-after-a-power-cycle/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I noticed this issue before, and I thought I had worked around it, but my hack is not 100% reliable.&lt;/p&gt;
&lt;p&gt;The problem is the&amp;nbsp;PAN1326C2 does not always appear initialise&amp;nbsp;correctly&amp;nbsp;so does not respond. My solution to this was to detect when this happened by having a timeout&amp;nbsp;on the initial response from the module, and pulling the reset line low if nothing came. The entire platform would reboot and almost all of the time it would spring in to life. Win.&lt;/p&gt;
&lt;p&gt;The issue is that if I power cycle the entire system it almost never comes to life. If I press the reset button it is more likely to start, but not much more likely. The only way I have found to bring things to life is to press the reset button (or pull the reset line low) twice in quick succession. This is 100% reliable, but because I am resetting the MCU I can not implement this in code.&lt;/p&gt;
&lt;p&gt;I even did a quick hack with a capacitor to act as a simple bit of nonvolatile memory and did reset twice in code, but even this did not work. Either the pulses are not long enough or by the time it gets to my code it is too late.&lt;/p&gt;
&lt;p&gt;My original assumption for&amp;nbsp;the&amp;nbsp;need to reset at all was it is related 32768Hz oscillator output on P1.7 breaking the Bluetooth reset on&amp;nbsp;&lt;span&gt;P1.6. My gut reaction is this is still the issue, but&amp;nbsp;there will be a chain of events and states leading to this.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Has anyone else experienced this? If so have you managed to work around it?&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I guess I could set up some kind of test setup to work out what timings work and what do not. A more&amp;nbsp;simple approach may be to hack on another microcontroller to handle the reset, or even reprogram the&amp;nbsp;MAX32625PICO to do it. My actual solution may be to simply show a warning light and require the use to double press the reset button.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Updating the PAN1326B Bluetooth module firmware and scanning for BLE devices (Don't Forget to Set)</title><link>https://community.element14.com/thread/56951?ContentTypeID=0</link><pubDate>Mon, 18 May 2026 11:37:11 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:557ffa80-5c57-4634-8237-2350afb04b88</guid><dc:creator>Alistair</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/56951?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56951/updating-the-pan1326b-bluetooth-module-firmware-and-scanning-for-ble-devices-don-t-forget-to-set/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;After a brief holiday I am back and documenting what I was working on literally hours before needing to go. Problem solving can be addictive.:-)&lt;/p&gt;
&lt;p&gt;Just before I went I thought I would test the scanning for BLE devices, like the BLE keyring I am using in the project, and it did not work. I was getting nothing. The summary is that I needed to upload a firmware update to the CC256xB in the PAN1326B module at boot to access the BLE functions.&lt;/p&gt;
&lt;p&gt;At first I decided to experiment with the BTStack solution that has the patch pre-rendered in the open source code, and after a little experimentation I was able to send these blocks, but timing was critical and I needed to implement a form of flow control to make this reliable.&lt;/p&gt;
&lt;p&gt;For reference I am wanting to avoid BTStack as it adds so much complexity to my project when I only need a fraction of its functionality. There is nothing wrong with BTStack, and following other threads here I may be the only person not using it for my project, it is just not the best fit for this project..&lt;/p&gt;
&lt;p&gt;In the end I used the library from &lt;a href="https://www.ti.com/tool/CC256XB-BT-SP" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://www.ti.com/tool/CC256XB-BT-SP&lt;/a&gt; and created code to read each HCI block and send to the module, and then wait for a response before sending the next.&lt;/p&gt;
&lt;p&gt;To my surprise this worked without any great complication, but it was still not scanning for BLE devices. Then thank to&amp;nbsp;&lt;a href="https://community.element14.com/members/bigg"&gt;BigG&lt;/a&gt;&amp;nbsp;for finding&amp;nbsp;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56886/ble-scanning-and-cc256x-firmware-uploading" data-e14adj="t"&gt;the magic HCI commands&lt;/a&gt;. I was getting data. I believe I missed that I needed to activate the old school Bluetooth functionality before activating the Low Energy functionality, but I have not yet tested that.&lt;/p&gt;
&lt;p&gt;Here is some test code. I should have it tidied by the time the full project is ready.&lt;/p&gt;
&lt;p&gt;First I downloaded cc256xb_bt_sp_v1.8.zip from the TI link above. I then took BasePatch (including the part in the #ifdef __SUPPORT_LOW_ENERGY__ block) and LowEnergyPatch from CC256XB.h. Do not take the AvprPatch though. I then load that into a const uint8_t.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;const uint8_t patchBinary[] = { 0x01,0x37,0xfe,0x02,0x07,0x10…&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Next I add my commands to the bottom to start the scan. I could, and in a different scenario would, send these separately, but for this project this gives me little advantage.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Set Event Mask
0x01, 0x01, 0x0C, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
// Set LE Event Mask
0x01, 0x01, 0x20, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
// Set Enable LE
0x01, 0x6D, 0x0C, 0x02, 0x01, 0x01,
// Set Scan Parameters
0x01, 0x0B, 0x20, 0x07, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00,
// Set Scan Enable (aka Start)
0x01, 0x0C, 0x20, 0x02, 0x01, 0x00&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The code simply iterates thought the data and waits for a response at the end of each HCI command.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;uint16_t cursor = 0;

while (cursor &amp;lt; totalSize) {

    BT_SERIAL.write(pgm_read_byte(&amp;amp;patchBinary[cursor++])); // Command (should always be 0x01)
    BT_SERIAL.write(pgm_read_byte(&amp;amp;patchBinary[cursor++])); // Opcode Low
    BT_SERIAL.write(pgm_read_byte(&amp;amp;patchBinary[cursor++])); // Opcode High
    
    uint8_t blockSize = pgm_read_byte(&amp;amp;patchBinary[cursor++]); // Read the size of the block
    BT_SERIAL.write(blockSize);
    
    for (int i=0; i&amp;lt;blockSize; i++) {
        BT_SERIAL.write(pgm_read_byte(&amp;amp;patchBinary[cursor++]));
    }
    
    // Wait for a response
    receiveHCIResponse(BT_SERIAL);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The code that does the reading of the response still needs some tidying and functionality adding, but here it is as it stands.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;int streamReadBlocking(Stream &amp;amp;inSerial, int inTimeout = HCI_TIMEOUT) {
    unsigned long waitEnd = millis() + inTimeout;
    while ( ( !inSerial.available() ) &amp;amp;&amp;amp; ( waitEnd&amp;gt;millis() ) ) {
        delay(1);
    }
    return BT_SERIAL.read();
}

void receiveHCIResponse(Stream &amp;amp;inSerial) {
    uint8_t packetType = streamReadBlocking(inSerial);
    uint8_t eventCode = streamReadBlocking(inSerial);
    uint8_t paramLength = streamReadBlocking(inSerial);
    
    // Skip what we don&amp;#39;t need
    streamSkipBlocking(inSerial, paramLength, HCI_TIMEOUT);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;There was still one issue, that being I was getting incomplete messages back from the module. I was getting packets of data reporting to have many many messages in it, but in fact only had one to two. My code was timing out and nothing was making any sense.&lt;/p&gt;
&lt;p&gt;In the end I instigated the scan (aka ran the Set Scan Enable command) with the remove duplicates flag set to 1 (&amp;quot;0x01, 0x0C, 0x20, 0x02, 0x01, 0x01&amp;quot;). This just worked and I now get several properly formed messages a minute. All the local BLE devices are showing up, and are repeated between 1 and 2 minutes, so adequate for my needs.&lt;/p&gt;
&lt;p&gt;I will note that buffer overruns should be considered with this approach. I am not so worried at the moment as binary data being read from flash is fixed at compile time and not stored in RAM, and I do not trust the data received from the module to use it for checking a buffer size, but it really does need considering.&lt;/p&gt;
&lt;p&gt;So that is working and I am at the point in starting the final &amp;ldquo;integration hell&amp;rdquo; stage of the project. Wish me luck.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Getting btstack to work via Arduino</title><link>https://community.element14.com/thread/56949?ContentTypeID=0</link><pubDate>Sun, 17 May 2026 22:06:13 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:7982c187-284b-4227-9ccd-3991fe500f58</guid><dc:creator>BigG</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/56949?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56949/getting-btstack-to-work-via-arduino/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;This was purely an agentic AI exercise as I was curious to learn how fast I could get my AI agent to modify an Arduino version of bluekitchen&amp;#39;s btstack I had found online. I had no way of testing this btstack version with other MCU&amp;#39;s so thought to give it a go anyway.&lt;/p&gt;
&lt;p&gt;Well, it took a couple of hours to crack it, with the majority time spent testing 2 examples. The impressive part is that it started by (re?)creating a &amp;quot;HAL&amp;quot; of sorts for the MAX32630FTHR in seconds once I had pointed it to be previous manual attempt of uploading the service pack and configuring the RX and TX pins correctly. It worked first time without error.&lt;/p&gt;
&lt;p&gt;Header:&amp;nbsp;hal_max32630fthr.h&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#ifndef HAL_MAX32630FTHR_H
#define HAL_MAX32630FTHR_H

#include &amp;lt;stdint.h&amp;gt;

#if defined __cplusplus
extern &amp;quot;C&amp;quot; {
#endif

void max32630fthr_bluetooth_setup(void);
void max32630fthr_bluetooth_set_baud(uint32_t baud);

#if defined __cplusplus
}
#endif

#endif&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Source:&amp;nbsp;hal_max32630fthr.cpp&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;hal_max32630fthr.h&amp;quot;

#if defined(ARDUINO_MAX32630FTHR) || defined(TARGET_MAX32630FTHR) || defined(MAX32630FTHR) || defined(MAX32630)

#include &amp;lt;Arduino.h&amp;gt;
#include &amp;quot;pwrseq_regs.h&amp;quot;
#include &amp;quot;rtc_regs.h&amp;quot;
#include &amp;quot;ioman_regs.h&amp;quot;
#include &amp;quot;gpio_regs.h&amp;quot;

// Pin Definitions for MAX32630FTHR
#define BLE_SHUTDOWN_PIN  P1_6   // nSHUTD (Active Low)
#define M4_RTS_OUT_TO_BLE P0_2   // M4 RTS Output
#define BLE_RTS_IN_TO_M4  P0_3   // BLE Module RTS Input (M4 CTS)
#define M4_TX_PIN         P0_0   // UART0 TX (Mapping B)
#define M4_RX_PIN         P0_1   // UART0 RX (Mapping B)

extern &amp;quot;C&amp;quot; void max32630fthr_bluetooth_setup(void) {
    // --- 1. SET VOLTAGES ---
    useVDDIO(BLE_SHUTDOWN_PIN); 
    useVDDIO(M4_TX_PIN); 
    useVDDIO(M4_RX_PIN);
    useVDDIO(M4_RTS_OUT_TO_BLE); 
    useVDDIO(BLE_RTS_IN_TO_M4);

    // --- 2. INITIALIZE HARDWARE ---
    // Configure 32.768 kHz Clock (P1.7)
    MXC_RTCCFG-&amp;gt;clk_ctrl |= MXC_F_RTC_CLK_CTRL_NANO_EN;
    MXC_RTCCFG-&amp;gt;osc_ctrl |= MXC_F_RTC_OSC_CTRL_OSC_WARMUP_ENABLE;
    MXC_RTCTMR-&amp;gt;prescale  = MXC_V_RTC_PRESCALE_DIV_2_0; 
    MXC_PWRSEQ-&amp;gt;reg4     |= MXC_F_PWRSEQ_REG4_PWR_PSEQ_32K_EN;

    // Prepare Pins: Set M4 RTS LOW BEFORE the module wakes up to signal &amp;quot;Ready&amp;quot;
    pinMode(M4_RTS_OUT_TO_BLE, OUTPUT);
    digitalWrite(M4_RTS_OUT_TO_BLE, LOW); 
    
    pinMode(BLE_RTS_IN_TO_M4, INPUT); 
    pinMode(M4_RX_PIN, INPUT);        

    // Pulse Reset (nSHUTD)
    pinMode(BLE_SHUTDOWN_PIN, OUTPUT);
    digitalWrite(BLE_SHUTDOWN_PIN, LOW);
    delay(100);
    digitalWrite(BLE_SHUTDOWN_PIN, HIGH);
    
    // Give the TI Controller time to wake up and stabilize
    delay(500); 
}

extern &amp;quot;C&amp;quot; void max32630fthr_bluetooth_set_baud(uint32_t baud) {
    Serial0.begin(baud);
    // Force IOMAN to Mapping B (Crossover). 
    // Serial0.begin() can revert to Mapping A under the hood. We force it back!
    MXC_IOMAN-&amp;gt;uart0_req = 0x11;
    while (MXC_IOMAN-&amp;gt;uart0_ack != 0x11) continue;
}

#endif // MAX32630FTHR&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Then it was a case of adding in the service pack info for the CC256x.&lt;/p&gt;
&lt;p&gt;Finally, it was tweaking a couple of files to align them with the MAX32630FTHR. The main file that was tweaked was &lt;code&gt;bsp_arduino_em9301.cpp&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**
 * Arduino + Energia Wrapper for BTstack
 */

#if !defined(ARDUINO)
#error &amp;quot;Not compiling for Arduino/Energia&amp;quot;
#endif

#include &amp;lt;Arduino.h&amp;gt;
#ifdef ENERGIA
#include &amp;lt;Energia.h&amp;gt;
#endif
#include &amp;lt;SPI.h&amp;gt;

#include &amp;quot;btstack/hal_uart_dma.h&amp;quot;

#if defined(__arm__)

// --- TRUE UART IMPLEMENTATION FOR ARM / MAX32630FTHR ---

#include &amp;quot;utility/hal_max32630fthr.h&amp;quot;

// Define the hardware serial port connected to your CC256x
#if defined(ARDUINO_MAX32630FTHR) || defined(TARGET_MAX32630FTHR) || defined(MAX32630FTHR) || defined(MAX32630)
#define BT_SERIAL Serial0
#else
#define BT_SERIAL Serial1
#endif

static uint16_t  bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = NULL;

static uint16_t  bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = NULL;

static void dummy_handler(void){};
static void (*rx_done_handler)(void) = dummy_handler;
static void (*tx_done_handler)(void) = dummy_handler;

// Large secondary ring buffer to absorb Arduino loop() / Serial.print() latency
#define RX_RING_BUFFER_SIZE 1024
static uint8_t rx_ring_buffer[RX_RING_BUFFER_SIZE];
static volatile uint16_t rx_ring_head = 0;
static volatile uint16_t rx_ring_tail = 0;

extern &amp;quot;C&amp;quot; __attribute__((weak)) void max32630fthr_bluetooth_setup(void) {}
extern &amp;quot;C&amp;quot; __attribute__((weak)) void max32630fthr_bluetooth_set_baud(uint32_t baud) {
    BT_SERIAL.begin(baud);
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_init(void){
    max32630fthr_bluetooth_setup();
    max32630fthr_bluetooth_set_baud(115200);
}

extern &amp;quot;C&amp;quot; int hal_uart_dma_set_baud(uint32_t baud){
    max32630fthr_bluetooth_set_baud(baud);
    return 0;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){
    tx_buffer_ptr = (uint8_t *) buffer;
    bytes_to_write = length;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t length){
    rx_buffer_ptr = buffer;
    bytes_to_read = length;
}

static inline void drain_hardware_buffer(void) {
    // Drain Hardware UART buffer into our massive Ring Buffer to prevent overflows
    while (BT_SERIAL.available() &amp;gt; 0) {
        uint16_t next_head = (rx_ring_head + 1) % RX_RING_BUFFER_SIZE;
        if (next_head != rx_ring_tail) {
            rx_ring_buffer[rx_ring_head] = BT_SERIAL.read();
            rx_ring_head = next_head;
        } else {
            break; // Ring buffer full!
        }
    }
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_process(void){
    // 1. Process Transmit (Blocking write for reliability during init script upload)
    if (bytes_to_write &amp;gt; 0) {
        BT_SERIAL.write(tx_buffer_ptr, bytes_to_write);
        bytes_to_write = 0;
        (*tx_done_handler)();
    }

    // 2. Drain Hardware UART buffer
    drain_hardware_buffer();

    // 3. Process Receive (Feed BTstack from Ring Buffer)
    while (bytes_to_read &amp;gt; 0 &amp;amp;&amp;amp; rx_ring_head != rx_ring_tail) {
        *rx_buffer_ptr++ = rx_ring_buffer[rx_ring_tail];
        rx_ring_tail = (rx_ring_tail + 1) % RX_RING_BUFFER_SIZE;
        bytes_to_read--;
        if (bytes_to_read == 0) {
            (*rx_done_handler)();
        }
    }
}

// Override Arduino&amp;#39;s weak yield() to aggressively drain the UART buffer
// while the user sketch is blocked on delay() or Serial.print()!
extern &amp;quot;C&amp;quot; void yield(void) {
    drain_hardware_buffer();
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_set_sleep(uint8_t sleep){}
extern &amp;quot;C&amp;quot; void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){}
extern &amp;quot;C&amp;quot; void hal_uart_dma_set_block_received( void (*block_handler)(void)){ rx_done_handler = block_handler ? block_handler : dummy_handler; }
extern &amp;quot;C&amp;quot; void hal_uart_dma_set_block_sent( void (*block_handler)(void)){ tx_done_handler = block_handler ? block_handler : dummy_handler; }
extern &amp;quot;C&amp;quot; uint32_t hal_time_ms(void){ return millis(); }

#else

// --- ORIGINAL EM9301 SPI IMPLEMENTATION (AVR) ---

#define HAVE_SHUTDOWN

#ifdef ENERGIA

// CMM 9301 Configuration for TI Launchpad
#define PIN_SPI_SCK      7
#define PIN_CS       8
#define PIN_SHUTDOWN 11
#define PIN_IRQ_DATA 13
#define PIN_SPI_MISO     14
#define PIN_SPI_MOSI     15
#else // ARDUINO

// CMM 9301 Configuration for Arduino
#define PIN_IRQ_DATA 2
#define PIN_CS 4
#define PIN_SHUTDOWN 5

// -- SPI defines for Arduino Mega
#ifndef PIN_SPI_MISO
#define PIN_SPI_MISO 50
#endif
#ifndef PIN_SPI_MOSI
#define PIN_SPI_MOSI 51
#endif
#ifndef PIN_SPI_SCK
#define PIN_SPI_SCK  52
#endif

#endif

// rx state
static uint16_t  bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0;

// tx state
static uint16_t  bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0;

// handlers
static void dummy_handler(void){};
static void (*rx_done_handler)(void) = dummy_handler;
static void (*tx_done_handler)(void) = dummy_handler;

static void bt_setup(void){
    pinMode(PIN_CS, OUTPUT);
    pinMode(PIN_SPI_MOSI, OUTPUT);
    pinMode(PIN_SPI_SCK, OUTPUT);
    pinMode(PIN_SHUTDOWN, OUTPUT);
    pinMode(PIN_IRQ_DATA, INPUT);

    digitalWrite(PIN_CS, HIGH);
    digitalWrite(PIN_SPI_MOSI, LOW);
    digitalWrite(PIN_SHUTDOWN, HIGH);

    // SPI settings are reset in SPI.begin() - calls hang on Arduino Zero, too.
    // SPI.setBitOrder(MSBFIRST);
    // SPI.setDataMode(SPI_MODE0);
    // SPI.end();
}

#ifdef HAVE_SHUTDOWN
static void bt_power_cycle(void){

    // power cycle. set CPU outputs to input to not power EM9301 via IOs
    // pinMode(PIN_SPI_MOSI, INPUT);
    // pinMode(PIN_CS, INPUT);
    pinMode(PIN_CS, OUTPUT);
    pinMode(PIN_SPI_MOSI, OUTPUT);
    pinMode(PIN_SPI_SCK, OUTPUT);
    pinMode(PIN_SHUTDOWN, OUTPUT);
    digitalWrite(PIN_CS, LOW);
    digitalWrite(PIN_SPI_MOSI, LOW);
    digitalWrite(PIN_SPI_SCK, LOW);
    digitalWrite(PIN_SHUTDOWN, HIGH);
    delay(500);

    pinMode(PIN_SPI_MOSI, OUTPUT);
    pinMode(PIN_CS, OUTPUT);
    digitalWrite(PIN_SPI_MOSI, LOW);
    digitalWrite(PIN_CS, HIGH);
    digitalWrite(PIN_SHUTDOWN, LOW);
    delay(1000);
}
#endif

#ifndef HAVE_SHUTDOWN
static void bt_send_illegal(void){
    digitalWrite(PIN_SPI_MOSI, HIGH);
    digitalWrite(PIN_CS, LOW);
    printf(&amp;quot;Illegal start\n&amp;quot;);
    SPI.begin(); 
    int i;
    for (i=0;i&amp;lt;255;i++){
        SPI.transfer(0xff);
        printf(&amp;quot;.&amp;quot;);
    }    
    SPI.end(); 
    printf(&amp;quot;\nIllegal stop\n&amp;quot;);
    digitalWrite(PIN_CS, HIGH);
}

static void bt_flush_input(void){
    digitalWrite(PIN_SPI_MOSI, LOW);
    digitalWrite(PIN_CS, LOW);
    SPI.begin(); 
    while (digitalRead(PIN_IRQ_DATA) == HIGH){
        SPI.transfer(0x00);
    }
    SPI.end(); 
    digitalWrite(PIN_CS, HIGH);
}

static void bt_send_reset(void){
      digitalWrite(PIN_SPI_MOSI, HIGH);
      digitalWrite(PIN_CS, LOW);
      SPI.begin(); 
      SPI.transfer(0x01);
      SPI.transfer(0x03);
      SPI.transfer(0x0c);
      SPI.transfer(0x00);
      SPI.end(); 
      digitalWrite(PIN_CS, HIGH);
}
#endif


static void bt_try_send(void){
    
    if (!bytes_to_write) return;

    // activate module
    pinMode(PIN_SPI_MOSI, OUTPUT);
    digitalWrite(PIN_SPI_MOSI, HIGH);
    digitalWrite(PIN_CS, LOW);

    // module ready
    int tx_done = 0;
    if (digitalRead(PIN_SPI_MISO) == HIGH){
        // printf(&amp;quot;Sending: &amp;quot;);

        SPI.begin(); 
        while (bytes_to_write){
            // printf(&amp;quot;%02x &amp;quot;, *tx_buffer_ptr);
            SPI.transfer(*tx_buffer_ptr);
            tx_buffer_ptr++;
            bytes_to_write--;
        }
        SPI.end();
        // printf(&amp;quot;.\n&amp;quot;);
        tx_done = 1;
    } 

    // deactivate module
    digitalWrite(PIN_CS, HIGH);
    digitalWrite(PIN_SPI_MOSI, LOW);
    pinMode(PIN_SPI_MOSI, OUTPUT);

    // notify upper layer
    if (tx_done) {
        (*tx_done_handler)();
    }
}

static int bt_try_read(void){

    // check if data available and buffer is ready
    if (digitalRead(PIN_IRQ_DATA) == LOW) return 0;
    if (bytes_to_read == 0) return 0;

    int num_bytes_read = 0;

    // printf(&amp;quot;Reading (%u): &amp;quot;, bytes_to_read);

    // activate module
    digitalWrite(PIN_SPI_MOSI, LOW);
    digitalWrite(PIN_CS, LOW);
    SPI.begin(); 
    do {
        uint8_t byte_read = SPI.transfer(0x00);
        // printf(&amp;quot;%02x &amp;quot;, byte_read); 
        *rx_buffer_ptr = byte_read;
        rx_buffer_ptr++;
        bytes_to_read--;
        num_bytes_read++;
    } while (bytes_to_read &amp;gt; 0);
    SPI.end(); 
    digitalWrite(PIN_CS, HIGH);

    // printf(&amp;quot;\n&amp;quot;); 

    // notify upper layer
    (*rx_done_handler)();

    return num_bytes_read;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_init(void){
    bt_setup();

#ifdef HAVE_SHUTDOWN
    bt_power_cycle(); 
#else
    // bring EM9301 into defined state
    bt_send_illegal();
    bt_send_reset();
    bt_flush_input();
#endif
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_set_block_received( void (*block_handler)(void)){
    rx_done_handler = block_handler;
}
extern &amp;quot;C&amp;quot; void hal_uart_dma_set_block_sent( void (*block_handler)(void)){
    tx_done_handler = block_handler;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){
    // only used for eHCILL
}

extern &amp;quot;C&amp;quot; int  hal_uart_dma_set_baud(uint32_t baud){
	return 0;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){
    // printf(&amp;quot;send_block, bytes %u\n&amp;quot;, length);
    tx_buffer_ptr = (uint8_t *) buffer;
    bytes_to_write = length;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t length){
    rx_buffer_ptr = buffer;
    bytes_to_read = length;
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_set_sleep(uint8_t sleep){
    // not needed for SPI (doesn&amp;#39;t need internal clock to work)
}

extern &amp;quot;C&amp;quot; void hal_uart_dma_process(void){
    int num_bytes_read = bt_try_read();
    if (num_bytes_read == 0){
        bt_try_send();
    }
}

extern &amp;quot;C&amp;quot; uint32_t hal_time_ms(void){
    return millis();
}

#endif
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Once the btstack library compiled it was onto creating two examples. Here I modified one example (LEPeripheral.ino) and created a new example (LEScanner.ino). The other examples in the btstack library were not tested and would need to be modified to get them to work with the MAX32630FTHR board.&lt;/p&gt;
&lt;p&gt;The modified version of `LEPeripheral.ino` basically creates a LED service which allows you to modify the onboard RGB LED&amp;#39;s colour, brightness and a blinking pattern. It does this through the use of two characteristics. I tried to add in a button service but the CC256b BLE device did not have enough memory. This was because I was using 128-bit UUID&amp;#39;s. It&amp;#39;s a well known problem with old (v4.x) BLE devices.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// LE Peripheral Example - Adapted for MAX32630FTHR
#include &amp;lt;BTstack.h&amp;gt;

// Bring in the native C BTstack headers
extern &amp;quot;C&amp;quot; {
    #include &amp;quot;btstack_memory.h&amp;quot;
    #include &amp;lt;btstack/run_loop.h&amp;gt;
    #include &amp;lt;bt_control.h&amp;gt;
    #include &amp;quot;btstack/hal_uart_dma.h&amp;quot;
    #include &amp;quot;att_server.h&amp;quot;
    
    // Expose the TI CC256x controller
    extern bt_control_t * bt_control_cc256x_instance(void);
}

// GATT Characteristic Handles
uint16_t handle_rgb_color;
uint16_t handle_rgb_state;

// State Variables
uint8_t color_r = 0;
uint8_t color_g = 0;
uint8_t color_b = 255; // Default to Blue
uint8_t intensity = 100;

uint8_t state_mode = 0; // 0=Off, 1=Solid, 2=Blink
uint16_t state_period = 1000;
uint8_t state_duty = 50;

// Blink tracking
uint32_t last_blink_time = 0;
bool blink_state = false;

// Update physical RGB LED (Active LOW on MAX32630FTHR)
void updateLEDs(bool is_on) {
    if (!is_on || state_mode == 0) {
        // Active LOW: 255 turns the LED completely off
        analogWrite(RED_LED, 255);
        analogWrite(GREEN_LED, 255);
        analogWrite(BLUE_LED, 255);
    } else {
        // Calculate intensity-scaled values
        uint8_t r = 255 - ((uint16_t)color_r * intensity / 100);
        uint8_t g = 255 - ((uint16_t)color_g * intensity / 100);
        uint8_t b = 255 - ((uint16_t)color_b * intensity / 100);
        
        analogWrite(RED_LED, r);
        analogWrite(GREEN_LED, g);
        analogWrite(BLUE_LED, b);
    }
}

void setup(void){
    Serial.begin(115200);
    while(!Serial) continue;

    Serial.println(&amp;quot;\r\nStarting LEPeripheral setup for MAX32630FTHR...&amp;quot;);

    pinMode(RED_LED, OUTPUT);
    pinMode(GREEN_LED, OUTPUT);
    pinMode(BLUE_LED, OUTPUT);
    
    updateLEDs(false); // Start OFF

    // set callbacks
    BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback);
    BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback);
    BTstack.setGATTCharacteristicRead(gattReadCallback);
    BTstack.setGATTCharacteristicWrite(gattWriteCallback);

    // --- SETUP GATT DATABASE ---
    
    // 1. rgbService
    BTstack.addGATTService(new UUID(&amp;quot;00000001-1111-2222-3333-444444444444&amp;quot;));
    
    handle_rgb_color = BTstack.addGATTCharacteristicDynamic(
        new UUID(&amp;quot;00000002-1111-2222-3333-444444444444&amp;quot;), 
        ATT_PROPERTY_READ | ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, 0);
        
    handle_rgb_state = BTstack.addGATTCharacteristicDynamic(
        new UUID(&amp;quot;00000003-1111-2222-3333-444444444444&amp;quot;), 
        ATT_PROPERTY_READ | ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, 0);

    // Pass the official CC256X controller flag so it loads the TI Service patch!
    BTstack.setup(BT_CONTROLLER_CC256X);
    BTstack.startAdvertising();
}

void loop(void){
    BTstack.loop();

    // 1. Non-blocking Blink Logic
    if (state_mode == 2) {
        uint32_t now = millis();
        uint32_t on_time = (uint32_t)state_period * state_duty / 100;
        uint32_t off_time = state_period - on_time;
        
        if (blink_state &amp;amp;&amp;amp; (now - last_blink_time &amp;gt;= on_time)) {
            blink_state = false;
            last_blink_time = now;
            updateLEDs(false);
        } else if (!blink_state &amp;amp;&amp;amp; (now - last_blink_time &amp;gt;= off_time)) {
            blink_state = true;
            last_blink_time = now;
            updateLEDs(true);
        }
    }

}

void deviceConnectedCallback(BLEStatus status, BLEDevice *device) {
    if (status == BLE_STATUS_OK) {
        Serial.println(&amp;quot;Device connected!&amp;quot;);
    }
}

void deviceDisconnectedCallback(BLEDevice * device){
    Serial.println(&amp;quot;Disconnected. Scanning resumes automatically.&amp;quot;);
}

uint16_t gattReadCallback(uint16_t value_handle, uint8_t * buffer, uint16_t buffer_size){
    if (value_handle == handle_rgb_color) {
        if (buffer &amp;amp;&amp;amp; buffer_size &amp;gt;= 4) {
            buffer[0] = color_r;
            buffer[1] = color_g;
            buffer[2] = color_b;
            buffer[3] = intensity;
        }
        return 4;
    } else if (value_handle == handle_rgb_state) {
        if (buffer &amp;amp;&amp;amp; buffer_size &amp;gt;= 4) {
            buffer[0] = state_mode;
            buffer[1] = (state_period &amp;gt;&amp;gt; 8) &amp;amp; 0xFF;
            buffer[2] = state_period &amp;amp; 0xFF;
            buffer[3] = state_duty;
        }
        return 4;
    }
    return 0;
}

int gattWriteCallback(uint16_t value_handle, uint8_t *buffer, uint16_t size){
    if (value_handle == handle_rgb_color &amp;amp;&amp;amp; size &amp;gt;= 4) {
        color_r = buffer[0];
        color_g = buffer[1];
        color_b = buffer[2];
        intensity = buffer[3];
        
        Serial.print(&amp;quot;RGB updated: &amp;quot;); Serial.print(color_r); Serial.print(&amp;quot;,&amp;quot;); 
        Serial.print(color_g); Serial.print(&amp;quot;,&amp;quot;); Serial.print(color_b);
        Serial.print(&amp;quot; @ &amp;quot;); Serial.print(intensity); Serial.println(&amp;quot;%&amp;quot;);
        
        if (state_mode == 1 || (state_mode == 2 &amp;amp;&amp;amp; blink_state)) {
            updateLEDs(true);
        }
    } else if (value_handle == handle_rgb_state &amp;amp;&amp;amp; size &amp;gt;= 4) {
        state_mode = buffer[0];
        state_period = (buffer[1] &amp;lt;&amp;lt; 8) | buffer[2];
        state_duty = buffer[3];
        
        Serial.print(&amp;quot;State updated: Mode=&amp;quot;); Serial.print(state_mode); 
        Serial.print(&amp;quot;, Period=&amp;quot;); Serial.print(state_period); 
        Serial.print(&amp;quot;ms, Duty=&amp;quot;); Serial.print(state_duty); Serial.println(&amp;quot;%&amp;quot;);
        
        last_blink_time = millis();
        blink_state = true;
        
        if (state_mode == 0) {
            updateLEDs(false);
        } else {
            updateLEDs(true);
        }
    }
    return 0;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The other example was a scanning app. This sketch scanned for a particular 128-bit UUID. This app revealed a few low level issues which were readily resolved.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/* 
 * Stripped down LE Central Scanner
 * Scans for a specific 16-bit Service UUID and retrieves the MAC address.
 * Does NOT initiate a connection.
 */

// Target Luggage Tag Service UUID (16-bit)
// Note. It will also search for iBeacons using same UUID.
// Use the full 128-bit Bluetooth Base UUID to safely bypass the 16-bit parsing bug

#include &amp;lt;BTstack.h&amp;gt;
// Bring in the native C BTstack headers
extern &amp;quot;C&amp;quot; {
    #include &amp;quot;btstack_memory.h&amp;quot;
    #include &amp;lt;btstack/run_loop.h&amp;gt;
    #include &amp;lt;bt_control.h&amp;gt;
    #include &amp;quot;btstack/hal_uart_dma.h&amp;quot;
    
    // Expose the TI CC256x controller and the H4 UART transport
    extern bt_control_t * bt_control_cc256x_instance(void);
    extern hci_transport_t * hci_transport_h4_dma_instance(void);
}

UUID targetLuggageTagUUID(&amp;quot;0000FEED-0000-1000-8000-00805F9B34FB&amp;quot;);

// Hardware definitions
const int LED_PIN = LED_BUILTIN; // Triggers the MAX32630FTHR&amp;#39;s onboard LED
uint32_t lastTagSeenTime = 0;

// Globals to pass data from the fast callback to the main loop
bool targetFound = false;
int targetRssi = 0;
char targetMac[18] = {0};

 void setup(void){
    Serial.begin(115200);
    
    pinMode(LED_PIN, OUTPUT);
    
    // Wait for the native USB serial port to connect before booting BTstack
    while(!Serial) continue;

    Serial.println(&amp;quot;\r\nStarting LECentral Scanner&amp;quot;);
    
    // Only register the advertisement callback (used for scanning)
    BTstack.setBLEAdvertisementCallback(advertisementCallback);
    
    // 1. Disable packet logging now that everything is working!
    // (Printing massive raw hex dumps to USB causes the hardware UART buffer to overflow and drop packets)
    // BTstack.enablePacketLogger();
    // BTstack.enableDebugLogger();

    // 2. Use the official setup (now that we patched BTstack.cpp to use the CC256x!)
    BTstack.setup(BT_CONTROLLER_CC256X);
    
    BTstack.bleStartScanning();
}

void loop(void){
    // Must be called continuously to process Bluetooth events
    BTstack.loop();

    // Turn off LED if we haven&amp;#39;t seen the target tag in the last 3 seconds
    if (millis() - lastTagSeenTime &amp;gt; 3000) {
        digitalWrite(LED_PIN, HIGH); // Note: Built-in LEDs are often active-LOW on Maxim boards!
    }

    // Process the discovery safely outside the callback
    if (targetFound) {
        targetFound = false; // clear the flag
        lastTagSeenTime = millis();
        digitalWrite(LED_PIN, LOW); // Turn ON the LED!
        
        // Rough distance calculation (assuming Tx Power at 1 meter is ~ -65 dBm)
        // Distance = 10 ^ ((TxPower - RSSI) / (10 * N)) -&amp;gt; N = Path loss exponent (usually ~2.5)
        float distance = pow(10.0, (-65.0 - targetRssi) / (10.0 * 2.5))*0.6;
        
        static uint32_t lastPrintTime = 0;
        if (millis() - lastPrintTime &amp;gt; 100) {
            lastPrintTime = millis();
            Serial.print(&amp;quot;\r\n *** Target Tag Found! MAC: &amp;quot;);
            Serial.print(targetMac);
            Serial.print(&amp;quot; | RSSI: &amp;quot;);
            Serial.print(targetRssi);
            Serial.print(&amp;quot; dBm | Est. Distance: &amp;quot;);
            Serial.print(distance);
            Serial.println(&amp;quot; meters&amp;quot;);
        }
    }
}

void advertisementCallback(BLEAdvertisement *bleAdvertisement) {
    bool isTarget = false;

    // 1. Check if the advertisement contains our target as a standard GATT Service UUID
    if (bleAdvertisement-&amp;gt;containsService(&amp;amp;targetLuggageTagUUID)) {
        isTarget = true;
    }
    
    // 2. Check if the beacon is an iBeacon, which hides the UUID inside Manufacturer Specific Data
    if (bleAdvertisement-&amp;gt;isIBeacon()) {
        if (targetLuggageTagUUID.matches((UUID*)bleAdvertisement-&amp;gt;getIBeaconUUID())) {
            isTarget = true;
        }
    }

    if (isTarget) {
        // Quickly copy the data to our globals and get out of the callback!
        targetRssi = bleAdvertisement-&amp;gt;getRssi();
        // getAddressString() uses a single static buffer internally in BTstack, 
        // so we copy it to our own safe array using strncpy.
        strncpy(targetMac, bleAdvertisement-&amp;gt;getBdAddr()-&amp;gt;getAddressString(), sizeof(targetMac));
        targetFound = true; 
    }
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here is a video demonstration of this sketch:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/452/btstack_5F00_lescanner.mp4"&gt;community.element14.com/.../btstack_5F00_lescanner.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The whole library can be found here should anyone find it useful - I just compressed it as a zip file rather than uploading it onto Github:&amp;nbsp;&lt;a href="https://drive.google.com/file/d/18-V3d7NckCjgbqI09-9MtiYFfE9YE3BZ/view?usp=sharing" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://drive.google.com/file/d/18-V3d7NckCjgbqI09-9MtiYFfE9YE3BZ/view?usp=sharing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I hope you find this useful. Any question please feel free to ask.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Sentinel Box - Part IV - Bluetooth and BTStack</title><link>https://community.element14.com/thread/56942?ContentTypeID=0</link><pubDate>Fri, 15 May 2026 01:40:06 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:69855a0f-3979-43ac-82a6-57b614d748ac</guid><dc:creator>saramic</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/56942?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56942/sentinel-box---part-iv---bluetooth-and-btstack/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;As the competition end&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f3c1.svg" title="Checkered flag"&gt;&amp;#x1f3c1;&lt;/span&gt;&amp;nbsp;is nearing, I am hoping to connect to some Bluetooth to help speed up some of the configuration options of my Lock&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f510.svg" title="Closed lock with key"&gt;&amp;#x1f510;&lt;/span&gt;&amp;nbsp;Box&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f4e6.svg" title="Package"&gt;&amp;#x1f4e6;&lt;/span&gt;&amp;nbsp;&amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Sentinel Box&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="recap"&gt;Recap&lt;/h2&gt;
&lt;p&gt;The idea is to build a smart lock box for digital devices to help control digital addiction, more on the idea can be found in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part I&lt;/code&gt;&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and coding with LPSDK and accessing a fingerprint scanner in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part II&lt;/code&gt;&lt;/strong&gt;, and mechanical stepper motors and vault lock mechanisms in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part III&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56869/sentinel-box---part-i---the-plan" data-e14adj="t"&gt;Sentinel Box - Part I - the plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56894/sentinel-box---part-ii---back-to-c" data-e14adj="t"&gt;Sentinel Box - Part II - back to C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56937/sentinel-box---part-iii---stepper-motor-and-vault-lock-mechanism" data-e14adj="t"&gt;Sentinel Box - Part III - Stepper Motor and Vault lock mechanism&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="getting-over-my-fears"&gt;Getting over my fears&lt;/h2&gt;
&lt;p&gt;I have a somewhat scarred history in some parts of microprocessor hobbyist programming. I recall back in the early 2000s making some relatively expensive development board unresponsive, I think it may have been running some version of&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;J2ME&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Java&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&amp;macr;_(ツ)_/&amp;macr;&lt;/strong&gt;, I shoved it under the house and gave up for some 5 years. I thought with the advent of&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://en.wikipedia.org/wiki/PIC_microcontrollers" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;&lt;strong&gt;PIC microcontrollers&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/a&gt;, and when I got around to looking at them around 2005, I would give it a try, but after a few different approaches I failed and gave up again. By the time Arduino came around I was a little hesitant and didn&amp;rsquo;t really think much of it. Finally, at a coding hackathon in Melbourne Australia, I was lucky enough to get a Particle board &amp;mdash; one you had to program through a web browser and by default it was internet connected by WiFi when the implications of an internet connected device sparked something in me. Noting that most Arduinos do not support wireless communications, I quickly switched to ESP32 as my go-to and was relatively happy ever since. This was until a few years ago when I wanted to connect via Bluetooth &amp;mdash; and I failed, the project went into a box.&lt;/p&gt;
&lt;p&gt;So with this background I got myself into this competition, where all of a sudden I would need a DAP link programmer to connect to a device, and the only wireless comms that it came with was Bluetooth. Numerous times when my device was unresponsive, I thought I had fried it somehow and it was time to put it in a box under the house. Numerous times I would touch and check voltages just in case something was heating up, or I had mixed up a wire or a voltage. This was exacerbated by my reliance on AI guiding me in a bunch of ideas like hermetic builds in a new&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Rust&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f980.svg" title="Crab"&gt;&amp;#x1f980;&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;tool chain only to work out I had not thought about setting up the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;PMIC&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(power management) and pins were at random voltages. I got this far, touch wood, I can finish this off.&lt;/p&gt;
&lt;p&gt;When it came to Bluetooth&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and not really understanding the communications protocol and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;GATT&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Generic Attribute Profile) vs&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;ATT&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Bluetooth Attribute Protocol) and what is&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Bluetooth&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;vs&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;BLE&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Bluetooth Low Energy) and all the write ups on bluetooth that came before me in this competition:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56925/guardian-sentinel-part-3-ethernet-ble" data-e14adj="t"&gt;Guardian Sentinel &amp;lt;Part 3&amp;gt; &amp;mdash; Ethernet &amp;amp; BLE &lt;/a&gt;&amp;nbsp;&lt;a href="https://community.element14.com/members/meera_5f00_hussien"&gt;meera_hussien&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56886/ble-scanning-and-cc256x-firmware-uploading" data-e14adj="t"&gt;BLE scanning and CC256X firmware uploading &lt;/a&gt;&amp;nbsp;&lt;a href="https://community.element14.com/members/alistairuk"&gt;Alistair&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56883/identity-protocol---part-9---ble-gatt-challenge-response-with-btstack" data-e14adj="t"&gt;Identity Protocol - Part 9 - BLE GATT Challenge/Response with BTstack&amp;nbsp;&lt;/a&gt;&lt;a href="https://community.element14.com/members/arvindsa"&gt;arvindsa&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56850/accessing-the-pan1326b-bluetooth-module-with-the-arduino-ide-don-t-forget-to-set" data-e14adj="t"&gt;Accessing the PAN1326B Bluetooth module with the Arduino IDE (Don&amp;rsquo;t Forget to Set)&amp;nbsp;&lt;/a&gt;&lt;a href="https://community.element14.com/members/alistairuk"&gt;Alistair&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56831/accessing-the-pan1326b-bluetooth-module-on-the-max32630fthr" data-e14adj="t"&gt;Accessing the PAN1326B Bluetooth module on the MAX32630fTHR&amp;nbsp;&lt;/a&gt;&lt;a href="https://community.element14.com/members/alistairuk"&gt;Alistair&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56853/identity-protocol---part-4---ble-using-pan1326b-and-btstack" data-e14adj="t"&gt;Identity Protocol - Part 4 - BLE using PAN1326B and BTstack&amp;nbsp;&lt;/a&gt;&lt;a href="https://community.element14.com/members/arvindsa"&gt;arvindsa&lt;/a&gt;&amp;nbsp;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/arvindsa/identity-protocol-e14-challenge/tree/main/firmware/tests/ble-beacon" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;github:arvindsa ble_beacon test using LPSDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With things like:&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;CC256X firmware uploading &amp;hellip; returned&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;0x01&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Unknown&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;HCI&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Command), and that shown new firmware needs uploading. Has anyone done this?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;GATT Service Definition &amp;hellip; BTstack generates an ATT database at plaintext .gatt file. Refer:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;tool/compile_gatt.py&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;hellip; If you are new to GATT - I recommend to watch this video &amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;The first thing I do is to pull the reset pin low (aka active) white we set up some other things. There is an obscure hardware bug in the module design that at times prevents the reset from functioning as it should later&lt;/p&gt;
&lt;div class="language-c highlighter-rouge"&gt;
&lt;div class="highlight"&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define BT_RST P1_6
&lt;/span&gt;&lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BT_RST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;I figured since&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;BTStack&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;was kind enough to share the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;LPSDK&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;I thought they would also include the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;TI&lt;/strong&gt;&amp;rsquo;s Init Script for the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;CC2564B&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;AI&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;no longer having access to reading artilces on Element 14 - seems like that block came in recently?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was scared&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f62c.svg" title="Grimacing"&gt;&amp;#x1f62c;&lt;/span&gt;&amp;nbsp;&amp;mdash; was I going to fry my device? Was this ever going to work? Was my reliance on AI&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;going to just burn tokens and not get me anywhere?&lt;/p&gt;
&lt;p&gt;here goes nothing &amp;hellip;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 id="random-paths-with-ai"&gt;Random paths with AI&lt;/h2&gt;
&lt;p&gt;The Element 14 apparent block of AI&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;hit me day one. Given all the great resources of other people&amp;rsquo;s findings, I thought I would point AI at these articles and have it give me a strategy to go forward. Not paying too much attention, I just kept agreeing to the prompt to come up with a plan; only after hours of going around in circles I worked out it was actually having trouble accessing the articles and nothing to do with coming up with a plan of how to get things going. I was triggered when I saw it trying to install and set up&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Jina AI Reader&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;&lt;strong&gt;Jina AI&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;is a specialized tool designed to scrape website data and convert it into clean,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;LLM&lt;/strong&gt;-friendly text or Markdown format. It is particularly useful for&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;RAG&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Retrieval-Augmented Generation) systems, AI agents, and content extraction by removing HTML clutter.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A bunch of tokens burnt and the long way round to getting Bluetooth working, as we will see shortly.&lt;/p&gt;
&lt;h3 id="hci-host-control-interface"&gt;HCI (Host Control Interface)&lt;/h3&gt;
&lt;p&gt;The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX32630FTHR&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;has a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;PAN1326B&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Bluetooth module soldered directly on it &amp;mdash; no external module or extra wiring needed. Inside the PAN1326B is a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;TI CC2564B&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;dual-mode BT/BLE chip. It talks to the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX32630&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;via&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;UART0&lt;/code&gt;, via&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;P0.0&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;P0.1&lt;/code&gt;, simple enough, at least I couldn&amp;rsquo;t get the wiring wrong.&lt;/p&gt;
&lt;p&gt;As I had somehow gone down the direct&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;HCI&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Host Control Interface) method, I seemed to have to start to do a lot of low-level stuff like setting up the 32kHz reference clock on&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;P1.7&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;needed by the BLE module. So this required starting the crystal oscillator and enabling it&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;MXC_RTCCFG-&amp;gt;clk_ctrl |= MXC_F_RTC_CLK_CTRL_NANO_EN;
MXC_RTCCFG-&amp;gt;osc_ctrl |= MXC_F_RTC_OSC_CTRL_OSC_WARMUP_ENABLE;
MXC_PWRSEQ-&amp;gt;reg4     |= MXC_F_PWRSEQ_REG4_PWR_PSEQ_32K_EN;
TMR_Delay(MXC_TMR0, MSEC(50));&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Skipping the first two lines gives you a valid&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;GPIO&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;voltage on&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;P1.7&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; just no clock signal. The module boots but never initialises its&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;HCI&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;UART&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;properly.&lt;/p&gt;
&lt;p&gt;Next there was a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;CTS&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;trap. The module relies on hardware flow control &amp;mdash; specifically&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;RTS&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Ready to Send) and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;CTS&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Clear to Send) &amp;mdash; to manage data transmission.&lt;/p&gt;
&lt;p&gt;With hardware flow control enabled (&lt;code class="language-plaintext highlighter-rouge"&gt;.cts = 1&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;uart_cfg_t&lt;/code&gt;), the UART peripheral refuses to transmit while the CTS input (P0.2) is HIGH. During boot, the PAN1326B holds its RTS output HIGH &amp;mdash; which feeds directly into P0.2. Result: every HCI command sits in the transmit buffer and never goes out. The fix is to&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;disable hardware CTS checking&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and let the MCU transmit freely:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;const uart_cfg_t ble_cfg = {
    .parity = UART_PARITY_DISABLE, .size = UART_DATA_SIZE_8_BITS,
    .extra_stop = 0, .cts = 0, .rts = 0, .baud = 115200,
};&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Finally, to run BLE (Bluetooth Low Energy), the CC256XB requires a service pack???&lt;/p&gt;
&lt;p&gt;The CC2564B chip ships without any LE (Bluetooth Low Energy) subsystem firmware. After a plain HCI Reset, standard BLE commands like&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;HCI_LE_Set_Advertising_Parameters&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(opcode&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;0x2006&lt;/code&gt;) come back as &amp;ldquo;Unknown HCI Command&amp;rdquo;. Before BLE works, a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;service pack&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;of ~150 TI vendor-specific HCI commands must be uploaded.&lt;/p&gt;
&lt;p&gt;TI distributes this as&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;CC256XB-BT-SP&lt;/code&gt;. The Bluetopia variant (&lt;code class="language-plaintext highlighter-rouge"&gt;CC256XB.h&lt;/code&gt;) packages all the commands as two C arrays &amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;BasePatch[]&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;LowEnergyPatch[]&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; each a flat stream of raw HCI packets. Uploading is straightforward iteration:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;while (p + 4 &amp;lt;= end) {
    unsigned int cmd_len = 4 + p[3];
    hci_send(p, cmd_len);
    hci_drain_event(200);
    p += cmd_len;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The last command in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;LowEnergyPatch&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;is&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;0xFD5B&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(LE enable). It takes noticeably longer than the others and its Command Complete event can still be sitting in the UART buffer when you send the follow-up HCI Reset. The symptom:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;hci_reset()&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;receives&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;04 0E 04 01 5B FD 00&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; a valid response, but for the wrong command. The fix is to loop in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;hci_reset()&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and skip any Command Complete that isn&amp;rsquo;t for the Reset opcode&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;0x0C03&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The file is TI proprietary (TSPA licence)&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;TI TSPA License TECHNOLOGY AND SOFTWARE PUBLICLY AVAILABLE&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;so it lives in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;reference/CC256XB_BT_SP/&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;which is gitignored.&lt;/p&gt;
&lt;p&gt;The license to get it reminds me of distributing encryption back in the 90s&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;I certify that the following is true: (a) I understand that this Software/Tool/Document is subject to export controls under the U.S. Commerce Department&amp;rsquo;s Export Administration Regulations (&amp;ldquo;EAR&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;(b) I am NOT located in Cuba, Iran, North Korea, Sudan or Syria. I understand these are prohibited destination countries under the EAR or U.S. sanctions regulations.&lt;/p&gt;
&lt;p&gt;(c) I am NOT listed on the Commerce Department&amp;rsquo;s Denied Persons List, the Commerce Department&amp;rsquo;s Entity List, the Commerce Department&amp;rsquo;s General Order No. 3 (in Supp. 1 t o EAR Part 736), or the Treasury Department&amp;rsquo;s Lists of Specially Designated Nationals.&lt;/p&gt;
&lt;p&gt;(d) I WILL NOT EXPORT, re-EXPORT or TRANSFER this Software/Tool/Document to any prohibited destination, entity, or individual without the necessary export license(s) or authorization(s) from the U.S. Government.&lt;/p&gt;
&lt;p&gt;(e) I will NOT USE or TRANSFER this Software/Tool/Document for use in any sensitive NUCLEAR, CHEMICAL or BIOLOGICAL WEAPONS, or MISSILE TECHNOLOGY end-uses unless authorized by the U.S. Government by regulation or specific license. &amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;something was working, so now to connect&lt;/p&gt;
&lt;h3 id="chrome-web-bluetooth-scanner"&gt;Chrome Web Bluetooth scanner&lt;/h3&gt;
&lt;p&gt;Chrome (and Edge) support the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Web Bluetooth API&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; a page served from&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;localhost&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;can scan for and connect to nearby BLE peripherals without any native app. The device picker shows all advertising BLE devices:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="javascript"&gt;const device = await navigator.bluetooth.requestDevice({
  acceptAllDevices: true,
  optionalServices: [&amp;quot;generic_access&amp;quot;],
});
const server = await device.gatt.connect();
const services = await server.getPrimaryServices();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The MAX32630FTHR was advertising and I had connectivity&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f389.svg" title="Tada"&gt;&amp;#x1f389;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;but what now? &amp;hellip;&lt;/p&gt;
&lt;h2 id="btstack-is-the-way"&gt;BTStack is the way&lt;/h2&gt;
&lt;p&gt;Seems I had gone a roundabout way to try to manually install packages and set oscillators as well as use HCI, but this was a lot of code and was not going to scale well to actually having 2-way comms between a configuration browser page and the BLE device. I re-read some of the above mentioned resources and it seemed BTStack was the way.&lt;/p&gt;
&lt;p&gt;AI still seemed to take me down some custom &amp;ldquo;polling&amp;rdquo; method it claimed&lt;/p&gt;
&lt;blockquote style="background-color:#f9f9f9;border-left:5px solid #ccc;font-style:italic;padding:0.5em 10px;"&gt;
&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;src/btstack_port.c&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;uses the same cooperative polling approach &amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;interrupt-driven DMA &amp;mdash; but with a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&amp;ldquo;simpler&amp;rdquo;&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;single-pass structure: RX drain &amp;rarr; TX drain &amp;rarr; run loop tick.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;but I finally corrected it to pretty much use the code from&lt;span&gt;&amp;nbsp;&lt;span style="font-family:monospace;"&gt;&amp;nbsp;&lt;a href="https://community.element14.com/members/arvindsa"&gt;arvindsa&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Switching from the raw HCI to BTstack &amp;mdash; a proper BLE stack &amp;mdash; meant the code was simpler, faster and more robust.&lt;/p&gt;
&lt;p&gt;Following adding BTstack as a git submodule&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;git submodule add https://github.com/bluekitchen/btstack.git third_party/btstack&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I could now compile a human-readable GATT database &amp;mdash;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;.gatt&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;.h&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;file into a C byte array. The service definition is trivial:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;PRIMARY_SERVICE, 0000F001-0000-1000-8000-00805F9B34FB
    CHARACTERISTIC, 0000F002-..., DYNAMIC | WRITE | WRITE_WITHOUT_RESPONSE,&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;And I could now access this from the browser and by writing data, see changes on the board.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img style="cursor:zoom-in;display:block;margin-left:auto;margin-right:auto;max-width:640px;" alt="LED Red/Green/Blue controll via Web Bluetooth control" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260514_5F00_BLE_5F00_demo_5F00_simple.gif" width="640" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;shows that changes on the Chrome page change the LED colour:&amp;nbsp;&lt;code class="language-plaintext highlighter-rouge"&gt;01&lt;/code&gt;&amp;nbsp;&amp;mdash; RED&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f534.svg" title="Red circle"&gt;&amp;#x1f534;&lt;/span&gt;,&amp;nbsp;&lt;code class="language-plaintext highlighter-rouge"&gt;02&lt;/code&gt;&amp;nbsp;&amp;mdash; GREEN ,&amp;nbsp;&lt;code class="language-plaintext highlighter-rouge"&gt;03&lt;/code&gt;&amp;nbsp;&amp;mdash; BLUE&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f535.svg" title="Large blue circle"&gt;&amp;#x1f535;&lt;/span&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/452/20260514_5F00_BLE_5F00_demo.mp4"&gt;community.element14.com/.../20260514_5F00_BLE_5F00_demo.mp4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="next"&gt;Next&lt;/h2&gt;
&lt;p&gt;Ok, I have some Bluetooth, a dash of stepper and a finger scan or two. I am away down the coast at the moment so I cannot attempt the build of the vault mechanism till I have access to my limited tools. I am feeling bullish and maybe I should also get access to writing some things to the SD card, but maybe it is time to start to bring these things together in a final design of a Bluetooth-controlled setup for capturing fingerprints, locking and unlocking once the required family members have scanned their fingers.&lt;/p&gt;
&lt;h2 id="source"&gt;Source&lt;/h2&gt;
&lt;p&gt;&lt;a id="" href="https://github.com/saramic/sentinel-box" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://github.com/saramic/sentinel-box&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Sentinel Box - Part III - Stepper Motor and Vault lock mechanism</title><link>https://community.element14.com/thread/56937?ContentTypeID=0</link><pubDate>Tue, 12 May 2026 02:55:08 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:1f7d6483-bf19-4eb3-9b99-5ebe041017e5</guid><dc:creator>saramic</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/56937?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56937/sentinel-box---part-iii---stepper-motor-and-vault-lock-mechanism/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Time is running out and I need a locking&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f510.svg" title="Closed lock with key"&gt;&amp;#x1f510;&lt;/span&gt;&amp;nbsp;mechanism&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/2699.svg" title="Gear"&gt;&amp;#x2699;&lt;/span&gt;️ for my smart lock box.&lt;/p&gt;
&lt;h2 id="recap"&gt;Recap&lt;/h2&gt;
&lt;p&gt;The idea is to build a smart lock box for digital devices to help control digital addiction, more on the idea can be found in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part I&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and a switch back to coding with LPSDK and accessing a fingerprint scanner in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part II&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56869/sentinel-box---part-i---the-plan" data-e14adj="t"&gt;Sentinel Box - Part I - the plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56894/sentinel-box---part-ii---back-to-c" data-e14adj="t"&gt;Sentinel Box - Part II - back to C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="acrylic-as-a-build-medium"&gt;Acrylic as a build medium&lt;/h2&gt;
&lt;p&gt;I have limited resources on the mechanical side, some hand tools and no 3D printer yet. I do have a mechanical engineering degree so maybe I do know what is possible but hand cutting intricate parts is hard and a limitation. My most recent build medium choice has been 3mm acrylic sheet, it is relatively easy to cut and with a heat gun I can also shape it. Finally it gives things a very &amp;ldquo;skeletonized&amp;rdquo; see-through tech aesthetic.&lt;/p&gt;
&lt;p&gt;As the core of my device is a &amp;ldquo;lock box&amp;rdquo; I looked around for some inspiration and found some vault door designs out there. I decided to come up with my own. First I drew a couple of ideas, then I extended it to what a full 5 pin vault door would look like with a simple HTML animation (I am sure there are some good engineering tools for this, keen to hear people&amp;rsquo;s thoughts) and finally to make sure I get my head around any tolerances and interferences I built a prototype of one arm.&lt;/p&gt;
&lt;p&gt;&lt;img style="cursor:zoom-in;display:block;margin-left:auto;margin-right:auto;max-width:640px;" alt="vault door design" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260511_5F00_lock_5F00_unlock_5F00_vault_5F00_door.gif" width="640" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Above are 5 &amp;ldquo;T-shaped&amp;rdquo; pins running through the motion of lock and unlock driven by a central round piece.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img loading="lazy" style="cursor:zoom-in;display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:640px;" alt="perspex model" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260512_5F00_perspex_5F00_model.gif" width="640" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A perspex model to iron out tolerances and my construction limitations.&lt;/p&gt;
&lt;h2 id="stepper-motor"&gt;Stepper motor&lt;/h2&gt;
&lt;p&gt;I presume there are a number of ways I could power my vault door, but as I have never actually used a stepper motor, nothing like now being the right time. I got some&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ULN2003&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;based&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;28BYJ-48&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;4-Phase Stepper Motor running at 5V. The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;ULN2003&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;input threshold is 2.4 V so the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;MAX32630FTHR&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GPIO outputs 3.3 V should be fine. As each input draws ~1 mA through the built-in 2.7 k&amp;Omega; base resistor &amp;mdash; no translator required.&lt;/p&gt;
&lt;p&gt;The other good thing is, the stepper is geared down, which means it will prevent being &amp;ldquo;forced open&amp;rdquo; ie the gears are 1 way and the vault door will stay shut unless the decision is made by the device to power the stepper. This is the case if I used a motor with a worm drive but not the case with most servos and they can be pushed into position.&lt;/p&gt;
&lt;p&gt;As I am deep in C-land with LPSDK, I don&amp;rsquo;t get the benefit of just including a library like&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Includes the Arduino Stepper Library
#include &amp;lt;Stepper.h&amp;gt;

// Defines the number of steps per rotation
const int stepsPerRevolution = 2038;

// Creates an instance of stepper class
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Fortunately the library is open source so looking at the code&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/arduino-libraries/Stepper/blob/master/src/Stepper.h" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://github.com/arduino-libraries/Stepper/blob/master/src/Stepper.h&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;shows me the details of controlling the various coils in the stepper motor. This is good as initially my guesses were wrong and I had it erratically turning in 1 direction and just buzzing on the spot when directed in reverse. Fortunately no smoke left the devices.&lt;/p&gt;
&lt;p&gt;Finally I got the motor working once I worked out the delay to take between steps, 3 ms, and the correct coils to power at the correct time.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/* -------------------------------------------------------------------------
 * 28BYJ-48 stepper via ULN2003 driver board.
 *
 * Gear ratio: 32 internal steps &amp;#215; 63.68 ≈ 2037.9 → use 2038 full / 4076 half.
 * Reverse (-steps): table index retreats instead of advances.
 * Coils stay energised after a move — holds gearbox meshed for clean reversal.
 * ------------------------------------------------------------------------- */

static const uint8_t wave_step[4][4] = {
    { 1, 0, 0, 0 },   /* IN1        */
    { 0, 1, 0, 0 },   /* IN2        */
    { 0, 0, 1, 0 },   /* IN3        */
    { 0, 0, 0, 1 },   /* IN4        */
};

static const uint8_t half_step[8][4] = {
    { 1, 0, 0, 0 },   /* IN1        */
    { 1, 1, 0, 0 },   /* IN1+IN2    */
    { 0, 1, 0, 0 },   /* IN2        */
    { 0, 1, 1, 0 },   /* IN2+IN3    */
    { 0, 0, 1, 0 },   /* IN3        */
    { 0, 0, 1, 1 },   /* IN3+IN4    */
    { 0, 0, 0, 1 },   /* IN4        */
    { 1, 0, 0, 1 },   /* IN4+IN1    */
};

static const uint8_t (*active_table)[4] = half_step;
static int      table_len     = 8;
static uint32_t step_delay_us  = 2944;   /* 5 RPM – 60,000,000 / 4076 / 5 */
static int      steps_per_rev  = 4076;   /* 32 &amp;#215; 63.68 &amp;#215; 2 */&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;also some fine tuning on the delay settings based on the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://github.com/arduino-libraries/Stepper/blob/master/src/Stepper.cpp" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Stepper.cpp&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;file&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Half-step:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;2,944 &amp;micro;s&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr; 5 RPM (60,000,000 / 4076 / 5)&lt;/li&gt;
&lt;li&gt;Wave drive:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;1,963 &amp;micro;s&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr; 15 RPM (60,000,000 / 2038 / 15)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and success&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" style="cursor:zoom-in;display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:640px;" alt="stepper test" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260512_5F00_stepper_5F00_test.gif" width="640" /&gt;&lt;/p&gt;
&lt;h2 id="next"&gt;Next&lt;/h2&gt;
&lt;p&gt;I am starting to bring a bunch of things together, the MAX32630FTHR connecting to a fingerprint reader, powering a stepper motor, being configured with a rotary encoder and displaying things on an LED matrix. Still I am not sure if that will be enough to enable a lock box that needs more than 1 person to verify for it to be unlocked. For that I am hoping to investigate BLE (Bluetooth Low Energy) and maybe a phone app to help configure it, that said the phone is likely to be locked into the lock box, so maybe only for configuring the lock box. Then there is connecting the stepper motor to the vault mechanism and only a few weeks left in the competition &amp;mdash; 24th May 2026.&lt;/p&gt;
&lt;h2 id="source"&gt;Source&lt;/h2&gt;
&lt;p&gt;&lt;a id="" href="https://github.com/saramic/sentinel-box" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://github.com/saramic/sentinel-box&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Guardian Sentinel &lt;Part 5&gt; - Sensor &amp; Motor</title><link>https://community.element14.com/thread/56935?ContentTypeID=0</link><pubDate>Mon, 11 May 2026 09:10:33 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:900629e8-6148-4ec1-8982-b437e3ca66c2</guid><dc:creator>meera_hussien</dc:creator><slash:comments>3</slash:comments><comments>https://community.element14.com/thread/56935?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56935/guardian-sentinel-part-5---sensor-motor/rss?ContentTypeId=0</wfw:commentRss><description>&lt;h1 id="mcetoc_1jo48kj5u0" style="text-align:center;"&gt;&lt;span style="font-size:200%;text-decoration:underline;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Guardian Sentinel - Sensor &amp;amp; Motor&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id="mcetoc_1jo48kj5u1" style="text-align:center;"&gt;&lt;span style="font-size:200%;text-decoration:underline;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&amp;lt;Part 5&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span style="font-size:200%;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;The sensor that i planned to use in this design is the SGP30 and SHT40 sensor.&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jo6oav8b0"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;What is SGP30 sensor?&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;The SGP30 is a digital multi-pixel gas sensor developed for simple integration into air purifiers, demand-controlled ventilation systems, and IoT-based applications. Sensirion&amp;rsquo;s CMOSens&amp;reg; technology combines a complete sensor system into a single chip, including a digital I&amp;sup2;C interface, a temperature-controlled micro hotplate, and two preprocessed indoor air quality output signals. As one of the first metal-oxide gas sensors with multiple sensing elements integrated on a single chip, the SGP30 can provide more comprehensive information about indoor air quality.&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Here is the simple infographic about the sensor&lt;br /&gt;&lt;br /&gt;&lt;img alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:812px;max-width:541px;"  height="812" src="https://community.element14.com/resized-image/__size/1082x1624/__key/communityserver-components-multipleuploadfilemanager/b39d126b_2D00_2bea_2D00_4cbf_2D00_9279_2D00_576df857e231-10114-complete/SGP30.png" width="541" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;The one which i am using is from Seeedstudio. A grove based sensor&lt;br /&gt;&lt;br /&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:460px;max-width:345px;"  height="460" src="https://community.element14.com/resized-image/__size/690x920/__key/communityserver-components-multipleuploadfilemanager/b39d126b_2D00_2bea_2D00_4cbf_2D00_9279_2D00_576df857e231-10114-complete/photo_5F00_2026_2D00_05_2D00_10_5F00_00_2D00_17_2D00_09.jpg" width="345" /&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:457px;max-width:343px;"  height="457" src="https://community.element14.com/resized-image/__size/686x914/__key/communityserver-components-multipleuploadfilemanager/b39d126b_2D00_2bea_2D00_4cbf_2D00_9279_2D00_576df857e231-10114-complete/photo_5F00_2026_2D00_05_2D00_10_5F00_00_2D00_17_2D00_07.jpg" width="343" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;The sensor is connected to the&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jo6oav8b1"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;What is SHT40 sensor?&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;The Grove SHT40 digital sensor is built around Sensirion&amp;rsquo;s proven humidity and temperature sensing technology. It delivers reliable temperature and humidity measurements across a wide measurement range. With the Grove connector system, the SHT40 sensor can be easily connected and used with a wide range of microcontrollers, making it suitable for quick plug-and-play prototyping.&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Here is the simple infographic about the sensor&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:786px;max-width:524px;"  height="786" src="https://community.element14.com/resized-image/__size/1048x1572/__key/communityserver-discussions-components-files/452/SHT40.png" width="524" /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:451px;max-width:338px;"  height="451" src="https://community.element14.com/resized-image/__size/676x902/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_10_5F00_00_2D00_17_2D00_04.jpg" width="338" /&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;"  height="452" src="https://community.element14.com/resized-image/__size/678x904/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_10_5F00_00_2D00_17_2D00_02.jpg" width="339" /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Both the sensor is interfaced to the&amp;nbsp;&lt;span&gt;FTHR-PMD-INTZ Feather-to-PMOD via i2C. Figure below shows how the pinout for the i2C connection.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&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:640px;" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-components-multipleuploadfilemanager/27a15253_2D00_ebd3_2D00_47ac_2D00_88a7_2D00_25ad84a63dad-10114-complete/pastedimage1778370277659v1.png"  /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&amp;nbsp;At the top we connect the SGP30 sensor and at the bottom we connect the SHT40 sensor as shown in the image below&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:380px;max-width:287px;"  height="380" src="https://community.element14.com/resized-image/__size/574x760/__key/communityserver-components-multipleuploadfilemanager/27a15253_2D00_ebd3_2D00_47ac_2D00_88a7_2D00_25ad84a63dad-10114-complete/image_5F00_2026_2D00_05_2D00_10_5F00_075746330.png" width="287" /&gt;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:378px;max-width:284px;"  height="378" src="https://community.element14.com/resized-image/__size/568x756/__key/communityserver-components-multipleuploadfilemanager/27a15253_2D00_ebd3_2D00_47ac_2D00_88a7_2D00_25ad84a63dad-10114-complete/photo_5F00_2026_2D00_05_2D00_10_5F00_07_2D00_55_2D00_00.jpg" width="284" /&gt;&amp;nbsp;&lt;img loading="lazy" alt="image" style="max-height:377px;max-width:282px;"  height="377" src="https://community.element14.com/resized-image/__size/564x754/__key/communityserver-components-multipleuploadfilemanager/27a15253_2D00_ebd3_2D00_47ac_2D00_88a7_2D00_25ad84a63dad-10114-complete/photo_5F00_2026_2D00_05_2D00_10_5F00_07_2D00_54_2D00_54.jpg" width="282" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;Once the sensor are connected, we re-run the i2c scanner code to ensure that the sensor are detected by the MAX32630FTHR and also to get respective i2C address.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;#include &amp;lt;Wire.h&amp;gt;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println(&amp;quot;MAX32630FTHR I2C Scanner&amp;quot;);
  Wire.begin();
}

void loop() {
  byte error, address;
  int devices = 0;

  Serial.println(&amp;quot;Scanning I2C bus...&amp;quot;);

  for (address = 1; address &amp;lt; 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print(&amp;quot;I2C device found at address 0x&amp;quot;);
      if (address &amp;lt; 16) Serial.print(&amp;quot;0&amp;quot;);
      Serial.println(address, HEX);
      devices++;
    }
  }

  if (devices == 0) {
    Serial.println(&amp;quot;No I2C devices found.&amp;quot;);
  } else {
    Serial.print(&amp;quot;Total devices found: &amp;quot;);
    Serial.println(devices);
  }

  Serial.println();
  delay(3000);
}&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;The serial output shows the sensor are detected and also the i2C address as well&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="max-height:257px;max-width:866px;" height="257" src="https://community.element14.com/resized-image/__size/1732x514/__key/communityserver-components-multipleuploadfilemanager/27a15253_2D00_ebd3_2D00_47ac_2D00_88a7_2D00_25ad84a63dad-10114-complete/pastedimage1778371930396v3.png" width="866"  /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;Once we have the i2C address, we can now write the code the read both the sensor values&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&amp;nbsp;&lt;pre class="ui-code" data-mode="csharp"&gt;#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;Adafruit_SGP30.h&amp;gt;
#include &amp;lt;Adafruit_SHT4x.h&amp;gt;
#include &amp;lt;Adafruit_Sensor.h&amp;gt;

// Sensor objects
Adafruit_SGP30 sgp30;
Adafruit_SHT4x sht40 = Adafruit_SHT4x();

// I2C addresses
#define SGP30_ADDR 0x58
#define SHT40_ADDR 0x44

unsigned long lastReadTime = 0;
const unsigned long readInterval = 2000; // Read every 2 seconds

// Function to calculate absolute humidity for SGP30 compensation
// Input: temperature in Celsius, relative humidity in %
// Output: absolute humidity in mg/m^3
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
  const float absoluteHumidity =
    216.7f *
    ((humidity / 100.0f) * 6.112f *
    exp((17.62f * temperature) / (243.12f + temperature)) /
    (273.15f + temperature));

  return (uint32_t)(absoluteHumidity * 1000.0f);
}

void setup() {
  Serial.begin(115200);
  delay(2000);

  Serial.println();
  Serial.println(&amp;quot;SGP30 + SHT40 Sensor Test&amp;quot;);
  Serial.println(&amp;quot;-------------------------&amp;quot;);

  Wire.begin();

  // Start SHT40
  if (!sht40.begin(&amp;amp;Wire)) {
    Serial.println(&amp;quot;SHT40 not detected at address 0x44.&amp;quot;);
    Serial.println(&amp;quot;Check wiring and I2C connection.&amp;quot;);
    while (1);
  }

  Serial.println(&amp;quot;SHT40 detected at address 0x44.&amp;quot;);

  // Optional SHT40 settings
  sht40.setPrecision(SHT4X_HIGH_PRECISION);
  sht40.setHeater(SHT4X_NO_HEATER);

  // Start SGP30
  if (!sgp30.begin(&amp;amp;Wire)) {
    Serial.println(&amp;quot;SGP30 not detected at address 0x58.&amp;quot;);
    Serial.println(&amp;quot;Check wiring and I2C connection.&amp;quot;);
    while (1);
  }

  Serial.println(&amp;quot;SGP30 detected at address 0x58.&amp;quot;);

  Serial.print(&amp;quot;SGP30 serial number: &amp;quot;);
  Serial.print(sgp30.serialnumber[0], HEX);
  Serial.print(sgp30.serialnumber[1], HEX);
  Serial.println(sgp30.serialnumber[2], HEX);

  Serial.println();
  Serial.println(&amp;quot;Allow the SGP30 to warm up for stable readings.&amp;quot;);
  Serial.println();
}

void loop() {
  if (millis() - lastReadTime &amp;gt;= readInterval) {
    lastReadTime = millis();

    sensors_event_t humidityEvent;
    sensors_event_t temperatureEvent;

    // Read SHT40 temperature and humidity
    sht40.getEvent(&amp;amp;humidityEvent, &amp;amp;temperatureEvent);

    float temperature = temperatureEvent.temperature;
    float humidity = humidityEvent.relative_humidity;

    // Calculate absolute humidity for SGP30 compensation
    uint32_t absoluteHumidity = getAbsoluteHumidity(temperature, humidity);

    // Send humidity compensation to SGP30
    sgp30.setHumidity(absoluteHumidity);

    // Read SGP30 air quality values
    if (!sgp30.IAQmeasure()) {
      Serial.println(&amp;quot;Failed to read SGP30.&amp;quot;);
      return;
    }

    Serial.println(&amp;quot;===== Sensor Readings =====&amp;quot;);

    Serial.print(&amp;quot;SHT40 Temperature : &amp;quot;);
    Serial.print(temperature);
    Serial.println(&amp;quot; &amp;#176;C&amp;quot;);

    Serial.print(&amp;quot;SHT40 Humidity    : &amp;quot;);
    Serial.print(humidity);
    Serial.println(&amp;quot; %RH&amp;quot;);

    Serial.print(&amp;quot;SGP30 TVOC        : &amp;quot;);
    Serial.print(sgp30.TVOC);
    Serial.println(&amp;quot; ppb&amp;quot;);

    Serial.print(&amp;quot;SGP30 eCO2        : &amp;quot;);
    Serial.print(sgp30.eCO2);
    Serial.println(&amp;quot; ppm&amp;quot;);

    Serial.print(&amp;quot;Abs Humidity      : &amp;quot;);
    Serial.print(absoluteHumidity);
    Serial.println(&amp;quot; mg/m3&amp;quot;);

    Serial.println(&amp;quot;===========================&amp;quot;);
    Serial.println();
  }
}&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;The output&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:343px;max-width:807px;" height="343" src="https://community.element14.com/resized-image/__size/1614x686/__key/communityserver-discussions-components-files/452/pastedimage1778471795906v2.png" width="807"  /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Next we shall see how to interface the stepper motor. Below is the stepper motor i use in this project and the wiring diagram. I am using the stepper motor as shown in image below&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;img loading="lazy" alt="image" style="max-height:553px;max-width:415px;"  height="553" src="https://community.element14.com/resized-image/__size/830x1106/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_11_5F00_16_2D00_56_2D00_32.jpg" width="415" /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;The connection between the stepper FeatherWing and the stepper motor is done as shown in the image below&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img loading="lazy" alt="image" style="max-height:536px;max-width:402px;"  height="536" src="https://community.element14.com/resized-image/__size/804x1072/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_11_5F00_16_2D00_56_2D00_24.jpg" width="402" /&gt;&lt;img loading="lazy" alt="image" style="max-height:536px;max-width:402px;"  height="536" src="https://community.element14.com/resized-image/__size/804x1072/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_11_5F00_16_2D00_56_2D00_27.jpg" width="402" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Coil 1 from stepper motor is connected to M3 and coil 2 is connected to M4. Since the FeatherWing has two port, please ensure you are connecting which port. Port 1 is connected with M1 and M2 and Port 2 is connected to M3 and M4. In my case i am using the Port 2. Once the wiring for the motor is complete, connect the external power to power up the stepper motor. And i run the code below to test if everything works fine.&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;Adafruit_MotorShield.h&amp;gt;

#define MOTOR_ADDR 0x60
#define STEPPER_PORT 2
#define STEPS_PER_REV 200

Adafruit_MotorShield AFMS = Adafruit_MotorShield(MOTOR_ADDR);
Adafruit_StepperMotor *myMotor = AFMS.getStepper(STEPS_PER_REV, STEPPER_PORT);

void setup() {
  Serial.begin(115200);
  delay(2000);

  Serial.println(&amp;quot;Stepper Smooth Test - M3/M4&amp;quot;);

  Wire.begin();

  if (!AFMS.begin()) {
    Serial.println(&amp;quot;Motor FeatherWing not found at 0x60.&amp;quot;);
    while (1);
  }

  Serial.println(&amp;quot;Motor FeatherWing found.&amp;quot;);
  Serial.println(&amp;quot;Using Port 2: M3/M4&amp;quot;);

  myMotor-&amp;gt;setSpeed(5);  // Try 5, 10, 20
}

void loop() {
  Serial.println(&amp;quot;Forward MICROSTEP...&amp;quot;);
  myMotor-&amp;gt;step(200, FORWARD, MICROSTEP);
  delay(1000);

  Serial.println(&amp;quot;Backward MICROSTEP...&amp;quot;);
  myMotor-&amp;gt;step(200, BACKWARD, MICROSTEP);
  delay(1000);
}&lt;/pre&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;And the video below is the working demo&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/452/video_5F00_2026_2D00_05_2D00_11_5F00_16_2D00_56_2D00_39.mp4"&gt;community.element14.com/.../video_5F00_2026_2D00_05_2D00_11_5F00_16_2D00_56_2D00_39.mp4&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Now all are working fine. Next is the integration.&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Part 2 Tracking Sentry: Components and Design Plan</title><link>https://community.element14.com/thread/56927?ContentTypeID=0</link><pubDate>Sat, 09 May 2026 04:21:03 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:b9e48a6a-8d94-4cef-9a50-b5d48ad1e1e1</guid><dc:creator>adam_k</dc:creator><slash:comments>3</slash:comments><comments>https://community.element14.com/thread/56927?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56927/part-2-tracking-sentry-components-and-design-plan/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:inherit;"&gt;Bit late to get started, I know, but unavoidable given exams and travel commitments. Thankfully I&amp;rsquo;ve found myself with some free time and all the components I ordered have arrived so should be smooth sailing from now on (sarcasm).&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:inherit;"&gt;This is my second post so I&amp;rsquo;ll start with a reminder of what my project is, walk through the components I&amp;rsquo;ve chosen for it, get into some specifics, then explain my action plan and potential challenges ahead.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;The Project&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:inherit;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:inherit;"&gt;My project is essentially a two-node autonomous security system. Node A includes a camera and stepper motor to pick up movement and follow a target. It also uses the board&amp;rsquo;s in-built IMU to detect when it is being tampered with. This data is then sent via Bluetooth to Node B &amp;ndash; the &amp;lsquo;command station&amp;rsquo;. This receives the alert (movement or tampering), and outputs the relevant signal on the LED board. It should also log the incident to the main computer using a simple Python server.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;The Components&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&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/452/pastedimage1778300324598v1.jpeg" /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;I was lucky enough to win the nomination and receive many components for free. My proposal was based around this and I try to incorporate as many elements of these as possible within my design. Others were ordered specifically for the project and I also take advantage of my existing inventory.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;strong&gt;The motor&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;This is essential for my camera to pan and track targets. Otherwise it is just a stationary camera which is not very useful nor creative. I decided a NEMA 17 motor would be most useful for my project and ordered one along with a steel mounting bracket for stability. At least that was the intention and have since come to find the bracket may act more as dead weight than anything useful. Well at least it looks nice. I also ordered a 5mm coupling for the motor shaft, allowing me to directly mount components on top of the motor. Probably avoided in industry but works fine for this.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;The stepper motor is driven with the included ADA2927 driver. Two are included but only one is needed. This is powered from a wall AC &amp;ndash; 12V 1 A adapter, split into two terminals with a DC barrel jack &amp;ndash; 2 pin connector. Slightly concerned by the 12W output but may be acceptable for a single NEMA 17 motor not needing much torque.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;strong&gt;The camara (and rest of Node A)&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;I am using the Arducam Mini 2MP Plus OV2640. Should be able to suitably take power from our setup and send data to the Node A MAX32630FTHR#. The camera should provide suitable on-board compression to allow the board to process frame differences to detect movement and drive the motor. The IMU should also work to detect tampering (IMU triggering disabled during motor movement to eliminate false detections). Given unfortunate time constraints there won&amp;rsquo;t be SD storage. State information and times are sent to Node B via Bluetooth. States being &amp;ldquo;connection&amp;rdquo;, &amp;ldquo;movement&amp;rdquo; and &amp;ldquo;tampering&amp;rdquo;. No connection could display static or something on the LED matrix. This just makes it look more engaging than just having a single LED light up to imply a state. Data should be sent to the computer to log state and timing information. The board on A will be powered directly with a 3.7V lithium battery.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;strong&gt;Node B&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;This is pretty straightforward. Just another board connected to an LED matrix display. Either the CharliePlex FeatherWing 7x15 or the W&amp;uuml;rth Elektronnik ICLED Featherwing. If feasible within time constraints the Ethernet adapter will also be included. Since this is intended as the &amp;lsquo;command station&amp;rsquo; we can just power it using USB from the computer.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;strong&gt;Other stuff&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;There are some other components included such as the FTHR-PMD-INTZ Adapter which is likely necessary. I also have a couple 9V batteries, breadboards, wires, jumper wires, wire strippers, and a Leatherman Wave (very useful) which will all be incorporated.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;The Plan&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;Time is very limited for me but there&amp;rsquo;s no point jumping in trying to get to the final design immediately. I plan to build this up in stages and test parts individually before putting it all together.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;I&amp;rsquo;ll first start by getting one of the boards to display patterns on the LED matrix. This shows I can get the board powered up properly and code running. Then I&amp;rsquo;ll try triggering this by a Bluetooth signal from the other board. Then I&amp;rsquo;ll set up Node A to control the motor to angle the camera. Perhaps the trickiest I&amp;rsquo;ll attempt to get the camera module feeding data to the board, have the board analyse the frames, and use the analysis to direct the camera towards movement. If by miracle this all works well then I should be able to integrate this all together in addition with the IMU detection.&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-weight:400;"&gt;I have a clear plan ahead now and am excited for the days to come. To be honest I am a little nervous about this not working out perfectly within the time constraints but I hope to have something running to demonstrate, even if it means some deviation from the original plan. I&amp;rsquo;ve worked on more complex stuff before though&amp;nbsp;not in the same time constraints. Regardless, it will be a learning experience and I will be documenting the whole process. The free socks are also appreciated!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Guardian Sentinel &lt;Part 4&gt; — The Slave</title><link>https://community.element14.com/thread/56926?ContentTypeID=0</link><pubDate>Sat, 09 May 2026 00:29:33 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:fc5e9ec3-a60b-4e37-8a68-33f83d7bfee5</guid><dc:creator>meera_hussien</dc:creator><slash:comments>3</slash:comments><comments>https://community.element14.com/thread/56926?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56926/guardian-sentinel-part-4-the-slave/rss?ContentTypeId=0</wfw:commentRss><description>&lt;h1 id="mcetoc_1jo48kj5u0" style="text-align:center;"&gt;&lt;span style="font-size:200%;"&gt;&lt;strong&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;Guardian Sentinel - The Slave&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 style="text-align:center;"&gt;&lt;span style="font-size:200%;"&gt;&lt;strong&gt;&amp;lt;Part 4&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:inherit;"&gt;For the slave, i decided to use the similar setup, hence i decide to use the FeatherWing Tripler Mini Kit.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img 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/452/20260509_2D00_004431.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The following image shows the header pins being soldered&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h1 id="mcetoc_1jo48kj5u2" class="products_name"&gt;&lt;/h1&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_011410.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_012550.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;Once finish soldering, I place the MAX32630FTHR in the middle.&lt;/p&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_013701.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;Followed by the FTHR-PMD-INTZ Feather-to-PMOD&lt;/p&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_013753.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;Which is place to the right of the MAX32630FTHR&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_013838.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;For further info on the&amp;nbsp;&lt;span&gt;FTHR-PMD-INTZ Feather-to-PMOD&lt;/span&gt; click &lt;a href="https://wiki.analog.com/resources/eval/user-guides/circuits-from-the-lab/fthr-pmd-intz" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;here&lt;/a&gt;.&amp;nbsp; Following that, i place the DC Motor + Stepper FeatherWing Addon.&lt;/p&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_013917.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Which is place to left of the MAX32630FTHR&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;"  height="363" src="https://community.element14.com/resized-image/__size/1290x726/__key/communityserver-discussions-components-files/452/20260509_2D00_015816.JPG" width="645" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&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:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260509_2D00_015853.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;To ensure all the three boards are connected, i did the i2C scanner and below are the result&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;#include &amp;lt;Wire.h&amp;gt;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println(&amp;quot;MAX32630FTHR I2C Scanner&amp;quot;);
  Wire.begin();
}

void loop() {
  byte error, address;
  int devices = 0;

  Serial.println(&amp;quot;Scanning I2C bus...&amp;quot;);

  for (address = 1; address &amp;lt; 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print(&amp;quot;I2C device found at address 0x&amp;quot;);
      if (address &amp;lt; 16) Serial.print(&amp;quot;0&amp;quot;);
      Serial.println(address, HEX);
      devices++;
    }
  }

  if (devices == 0) {
    Serial.println(&amp;quot;No I2C devices found.&amp;quot;);
  } else {
    Serial.print(&amp;quot;Total devices found: &amp;quot;);
    Serial.println(devices);
  }

  Serial.println();
  delay(3000);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and the result from the serial monitor is shown below&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:345px;max-width:764px;"  height="345" src="https://community.element14.com/resized-image/__size/1528x690/__key/communityserver-discussions-components-files/452/pastedimage1778286221638v1.png" width="764" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the next post we shall see on interfacing with sensor and motor.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Guardian Sentinel  &lt;Part 3&gt; — Ethernet &amp; BLE</title><link>https://community.element14.com/thread/56925?ContentTypeID=0</link><pubDate>Fri, 08 May 2026 09:37:37 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:62624e19-ec95-481b-87ee-c29a2d948aa3</guid><dc:creator>meera_hussien</dc:creator><slash:comments>10</slash:comments><comments>https://community.element14.com/thread/56925?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56925/guardian-sentinel-part-3-ethernet-ble/rss?ContentTypeId=0</wfw:commentRss><description>&lt;h1 id="mcetoc_1jno19ikt0" style="text-align:center;"&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;Guardian Sentinel &amp;mdash;&amp;nbsp;Ethernet &amp;amp; BLE&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id="mcetoc_1jno19ikt1" style="text-align:center;"&gt;&lt;span style="font-size:200%;"&gt;&amp;lt;Part 3&amp;gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;In the previous post we have seen about how to program the MAX32630FTHR and the OLED. In this post we shall see how to configure the ethernet and the BLE.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jno19ikt2"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;text-decoration:underline;"&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span style="font-size:150%;"&gt;Since we are using the ethernet FeatherWing, there is onboard RJ45 connector with controller. The image below shows the details of the device.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span style="font-size:150%;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;&lt;span style="font-size:150%;"&gt;&lt;img alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:440px;max-width:440px;" height="440" src="https://community.element14.com/resized-image/__size/880x880/__key/communityserver-discussions-components-files/452/pastedimage1777848566744v1.png" width="440"  /&gt;The board is based one the WIZnet5500 and take the form factor of the Adafruit FeatherWing Tripler. It can support&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;10BaseT/100BaseTX Ethernet&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;Support Auto Negotiation (Full and half duplex, for both 10BaseT and 100BaseTX)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;In order to test the ethernet connectivity i have use the following code. And the serial output shows the output. I have also configure the OLED to show the output as well.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;SPI.h&amp;gt;
#include &amp;lt;Ethernet.h&amp;gt;

#define STATUS_LED LED_BUILTIN

#define ETH_CS    44
#define ETH_RESET 46

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x30 };

void resetEthernet() {
  pinMode(ETH_RESET, OUTPUT);

  digitalWrite(ETH_RESET, HIGH);
  delay(100);

  digitalWrite(ETH_RESET, LOW);
  delay(300);

  digitalWrite(ETH_RESET, HIGH);
  delay(1000);
}

void setup() {
  pinMode(STATUS_LED, OUTPUT);

  Serial.begin(9600);
  delay(3000);

  Serial.println();
  Serial.println(&amp;quot;==============================&amp;quot;);
  Serial.println(&amp;quot;MAX32630FTHR + Particle Ethernet&amp;quot;);
  Serial.println(&amp;quot;==============================&amp;quot;);

  SPI.begin();

  resetEthernet();

  Ethernet.init(ETH_CS);

  Serial.println(&amp;quot;Starting DHCP...&amp;quot;);

  if (Ethernet.begin(mac) == 0) {
    Serial.println(&amp;quot;DHCP failed.&amp;quot;);
    while (true) {
      digitalWrite(STATUS_LED, HIGH);
      delay(300);
      digitalWrite(STATUS_LED, LOW);
      delay(300);
    }
  }

  Serial.println(&amp;quot;DHCP successful!&amp;quot;);
  Serial.print(&amp;quot;Local IP: &amp;quot;);
  Serial.println(Ethernet.localIP());

  Serial.print(&amp;quot;Subnet: &amp;quot;);
  Serial.println(Ethernet.subnetMask());

  Serial.print(&amp;quot;Gateway: &amp;quot;);
  Serial.println(Ethernet.gatewayIP());

  Serial.print(&amp;quot;DNS: &amp;quot;);
  Serial.println(Ethernet.dnsServerIP());
}

void loop() {
  Ethernet.maintain();

  Serial.print(&amp;quot;Running. IP: &amp;quot;);
  Serial.println(Ethernet.localIP());

  digitalWrite(STATUS_LED, !digitalRead(STATUS_LED));
  delay(3000);
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;span style="font-size:150%;"&gt;The library used is the Ethernet.h. And below is the serial output.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:312px;max-width:691px;" height="312" src="https://community.element14.com/resized-image/__size/1382x624/__key/communityserver-discussions-components-files/452/pastedimage1777849715464v2.png" width="691"  /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;And i have tried to show the&amp;nbsp;status update of the ethernet&amp;nbsp;on the OLED as well&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:600px;"  height="450" src="https://community.element14.com/resized-image/__size/1200x900/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_04_5F00_10_2D00_51_2D00_57.jpg" width="600" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;Next lets configure the BLE&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jno19ikt2"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;text-decoration:underline;"&gt;&lt;strong&gt;BLE&lt;/strong&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;text-decoration:underline;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;Initially i found that, most of the resources are using the Mbed OS to setup the BLE. After researching and also the sharing from other participant, below is the code that i am using to check the BLE.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;#include &amp;lt;pwrseq_regs.h&amp;gt;
#include &amp;lt;pwrman_regs.h&amp;gt;
#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;Adafruit_GFX.h&amp;gt;
#include &amp;lt;Adafruit_SSD1306.h&amp;gt;

// -------------------- Bluetooth Settings --------------------
#define BT_SERIAL Serial0
#define BT_RST    P1_6

// -------------------- OLED Settings --------------------
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define OLED_ADDR 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;amp;Wire, OLED_RESET);
bool oledOK = false;

// -------------------- HCI Commands --------------------
const byte HCI_RESET_CMD[] = {
  0x01, 0x03, 0x0C, 0x00
};

const byte HCI_READ_BD_ADDR[] = {
  0x01, 0x09, 0x10, 0x00
};

const byte HCI_LE_READ_LOCAL_SUPPORTED_FEATURES[] = {
  0x01, 0x03, 0x20, 0x00
};

// -------------------- Helper Functions --------------------
void showOLED(String line1, String line2, String line3 = &amp;quot;&amp;quot;, String line4 = &amp;quot;&amp;quot;) {
  if (!oledOK) return;

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);

  display.setCursor(0, 0);
  display.println(line1);

  display.setCursor(0, 8);
  display.println(line2);

  display.setCursor(0, 16);
  display.println(line3);

  display.setCursor(0, 24);
  display.println(line4);

  display.display();
}

void setupOLED() {
  Wire.begin();

  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(&amp;quot;OLED not detected.&amp;quot;);
    oledOK = false;
    return;
  }

  oledOK = true;
  showOLED(&amp;quot;MAX32630FTHR&amp;quot;, &amp;quot;OLED Started&amp;quot;, &amp;quot;BLE Detect Test&amp;quot;);
  delay(1500);
}

void printHexByte(byte b) {
  if (b &amp;lt; 0x10) Serial.print(&amp;quot;0&amp;quot;);
  Serial.print(b, HEX);
  Serial.print(&amp;quot; &amp;quot;);
}

void clearBTBuffer() {
  while (BT_SERIAL.available()) {
    BT_SERIAL.read();
  }
}

void configureBluetoothUART() {
  // Enable 32.768 kHz oscillator output on P1.7
  MXC_PWRSEQ-&amp;gt;reg4 |= MXC_F_PWRSEQ_REG4_PWR_PSEQ_32K_EN;

  // Start HCI UART
  BT_SERIAL.begin(115200);

  // Swap RX/TX lines and enable CTS/RTS
  MXC_IOMAN-&amp;gt;uart0_req |= MXC_F_IOMAN_UART0_REQ_CTS_IO_REQ |
                          MXC_F_IOMAN_UART0_REQ_RTS_IO_REQ |
                          MXC_F_IOMAN_UART0_REQ_IO_MAP;
}

void hardwareResetBT() {
  pinMode(BT_RST, OUTPUT);

  digitalWrite(BT_RST, LOW);
  delay(1000);

  digitalWrite(BT_RST, HIGH);
  delay(3000);

  clearBTBuffer();
}

bool readHCIResponse(byte *buffer, int &amp;amp;length, unsigned long timeoutMs) {
  length = 0;
  unsigned long startTime = millis();

  while (millis() - startTime &amp;lt; timeoutMs) {
    while (BT_SERIAL.available()) {
      byte data = BT_SERIAL.read();

      if (length &amp;lt; 64) {
        buffer[length++] = data;
      }
    }
  }

  return length &amp;gt; 0;
}

bool sendHCICommand(const byte *cmd, int cmdLen, const char *label, byte *response, int &amp;amp;responseLen) {
  Serial.println();
  Serial.print(&amp;quot;Sending: &amp;quot;);
  Serial.println(label);

  clearBTBuffer();

  BT_SERIAL.write(cmd, cmdLen);

  bool gotResponse = readHCIResponse(response, responseLen, 2500);

  Serial.print(&amp;quot;Response: &amp;quot;);

  if (!gotResponse) {
    Serial.println(&amp;quot;No response&amp;quot;);
    return false;
  }

  for (int i = 0; i &amp;lt; responseLen; i++) {
    printHexByte(response[i]);
  }

  Serial.println();

  return true;
}

bool checkStatusOK(byte *response, int responseLen) {
  // HCI Command Complete format:
  // 04 0E XX 01 OP_LSB OP_MSB STATUS ...
  if (responseLen &amp;gt;= 7 &amp;amp;&amp;amp; response[0] == 0x04 &amp;amp;&amp;amp; response[1] == 0x0E) {
    return response[6] == 0x00;
  }

  return false;
}

String extractBDADDR(byte *response, int responseLen) {
  // Read BD_ADDR response:
  // 04 0E 0A 01 09 10 00 XX XX XX XX XX XX
  // Address is returned LSB first
  if (responseLen &amp;gt;= 13 &amp;amp;&amp;amp; response[6] == 0x00) {
    String addr = &amp;quot;&amp;quot;;

    for (int i = 12; i &amp;gt;= 7; i--) {
      if (response[i] &amp;lt; 0x10) addr += &amp;quot;0&amp;quot;;
      addr += String(response[i], HEX);

      if (i &amp;gt; 7) addr += &amp;quot;:&amp;quot;;
    }

    addr.toUpperCase();
    return addr;
  }

  return &amp;quot;Unknown&amp;quot;;
}

void setup() {
  Serial.begin(115200);
  delay(3000);

  Serial.println();
  Serial.println(&amp;quot;MAX32630FTHR BLE Module Detection Test&amp;quot;);
  Serial.println(&amp;quot;--------------------------------------&amp;quot;);

  setupOLED();
  showOLED(&amp;quot;BLE Test&amp;quot;, &amp;quot;Starting...&amp;quot;);

  configureBluetoothUART();

  bool detected = false;
  String btAddress = &amp;quot;Unknown&amp;quot;;

  for (int attempt = 1; attempt &amp;lt;= 5; attempt++) {
    Serial.println();
    Serial.print(&amp;quot;BLE detection attempt &amp;quot;);
    Serial.println(attempt);

    showOLED(&amp;quot;BLE Detect&amp;quot;, &amp;quot;Attempt &amp;quot; + String(attempt), &amp;quot;Resetting module&amp;quot;);

    hardwareResetBT();

    byte response[64];
    int responseLen = 0;

    bool resetOK = sendHCICommand(
      HCI_RESET_CMD,
      sizeof(HCI_RESET_CMD),
      &amp;quot;HCI Reset&amp;quot;,
      response,
      responseLen
    );

    if (resetOK &amp;amp;&amp;amp; checkStatusOK(response, responseLen)) {
      Serial.println(&amp;quot;HCI Reset: OK&amp;quot;);
      showOLED(&amp;quot;BLE Module&amp;quot;, &amp;quot;HCI Reset OK&amp;quot;, &amp;quot;Reading address&amp;quot;);

      bool addrOK = sendHCICommand(
        HCI_READ_BD_ADDR,
        sizeof(HCI_READ_BD_ADDR),
        &amp;quot;Read BD_ADDR&amp;quot;,
        response,
        responseLen
      );

      if (addrOK &amp;amp;&amp;amp; checkStatusOK(response, responseLen)) {
        btAddress = extractBDADDR(response, responseLen);
        Serial.print(&amp;quot;Bluetooth Address: &amp;quot;);
        Serial.println(btAddress);

        bool leOK = sendHCICommand(
          HCI_LE_READ_LOCAL_SUPPORTED_FEATURES,
          sizeof(HCI_LE_READ_LOCAL_SUPPORTED_FEATURES),
          &amp;quot;LE Read Local Supported Features&amp;quot;,
          response,
          responseLen
        );

        if (leOK &amp;amp;&amp;amp; checkStatusOK(response, responseLen)) {
          Serial.println(&amp;quot;LE Feature Check: OK&amp;quot;);
          detected = true;
          break;
        }
      }
    }

    Serial.println(&amp;quot;BLE module not ready. Retrying...&amp;quot;);
    delay(1000);
  }

  Serial.println();

  if (detected) {
    Serial.println(&amp;quot;BLE MODULE DETECTED SUCCESSFULLY&amp;quot;);
    Serial.print(&amp;quot;BD_ADDR: &amp;quot;);
    Serial.println(btAddress);

    showOLED(
      &amp;quot;BLE: Detected&amp;quot;,
      &amp;quot;HCI: OK&amp;quot;,
      btAddress,
      &amp;quot;LE Feature: OK&amp;quot;
    );
  } else {
    Serial.println(&amp;quot;BLE MODULE NOT DETECTED&amp;quot;);

    showOLED(
      &amp;quot;BLE: Not Found&amp;quot;,
      &amp;quot;Check reset/UART&amp;quot;,
      &amp;quot;Try board reset&amp;quot;
    );
  }
}

void loop() {
  // Nothing needed. The result remains on OLED.
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;And we can monitor the status on oled. The image below shows the status of the BLE on the OLED.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;img loading="lazy" alt="image" style="max-height:490px;max-width:653px;"  height="490" src="https://community.element14.com/resized-image/__size/1306x980/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_05_2D00_08_5F00_17_2D00_33_2D00_28.jpg" width="653" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;Now the MASTER is ready. We can now prepare the SLAVE.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:150%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Identity Protocol - Part 10 - W5500 Ethernet</title><link>https://community.element14.com/thread/56912?ContentTypeID=0</link><pubDate>Tue, 05 May 2026 05:09:14 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:3bd1ae4d-aa87-4b7a-b534-26cb4d4e1680</guid><dc:creator>arvindsa</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/56912?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56912/identity-protocol---part-10---w5500-ethernet/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p style="text-align:left;"&gt;Argh, Writing a good post is definitely the hard part. :D i completed interfacing all the necessary modules almost a week ago, I am also working on other projects in parallel, but this weekend, i managed to sit down and write this post. The final piece of the jigsaw in my project is to get W5500 to interface with the MAX32630.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The idea is simple enough: stop making people swipe a card and type a PIN at every single door. Instead, the ID card (a MAX32630FTHR + ATECC508A in your pocket) unlocks once via PIN, then silently does challenge-response crypto over Bluetooth every time you walk up to a door. If the card gets yanked off you, the IMU detects the tug and it locks itself. No PIN, no entry. For more details check the Part 1 of the series&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56768/identity-protocol-part-1---plan" data-contentid="d5152729d060498f812f0244641b3810" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol Part 1 - Plan&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56830/identity-protocol---part-2---django-server" data-contentid="1ab561efc7f2445b8eb20783970ed89c" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol - Part 2 - Django Server&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56840/identity-protocol---part-3---unboxing-and-blinking-with-maxim-lpsdk" data-contentid="75fef2ca1ed74f3ca296a48a29402617" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol - Part 3 - Unboxing and Blinking with Maxim LPSDK&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56853/identity-protocol---part-4---ble-using-pan1326b-and-btstack" data-contentid="b449688fb5c8477991ced940f32ac3fa" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol - Part 4 - BLE using PAN1326B and BTstack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title="Identity Protocol - Part 5 - Interfacing a Keypad" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56856/identity-protocol---part-5---interfacing-a-keypad" data-e14adj="t"&gt;Identity Protocol - Part 5 - Interfacing a Keypad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56861/identity-protocol---part-6---snatch-detection-with-the-bmi160-imu" data-e14adj="t"&gt;Identity Protocol - Part 6 - Snatch Detection with the BMI160 IMU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56861/identity-protocol---part-6---snatch-detection-with-the-bmi160-imu" data-e14adj="t"&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56874/identity-protocol---part-7---colouring-on-the-icled-featherwing" data-e14adj="t"&gt;Identity Protocol - Part 7 - Colouring on the ICLED FeatherWing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56881/identity-protocol---part-8---cryptographically-sign-with-atecc508-and-verify-with-micro-ecc" data-e14adj="t"&gt;Identity Protocol - Part 8 - Cryptographically Sign with ATECC508 and Verify with Micro-ECC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56883/identity-protocol---part-9---ble-gatt-challenge-response-with-btstack" data-e14adj="t"&gt;Identity Protocol - Part 9 - BLE GATT Challenge/Response with BTstack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1jnr5ufo20"&gt;The SPI Protocol: Reads, Writes, and Verifying Connectivity&lt;/h2&gt;
&lt;p&gt;The SPI transaction requires three bytes of command header (address + block + direction) followed by one or more data bytes. The direction is in the control byte:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Read:  [ADDR_H][ADDR_L][BSB|READ |OM][DATA_IN_FROM_W5500...]
Write: [ADDR_H][ADDR_L][BSB|WRITE|OM][DATA_OUT_TO_W5500...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;RWB&lt;/code&gt; bit: 0 = read, 1 = write. &lt;code&gt;OM&lt;/code&gt; (Operation Mode) is almost always 0 for variable-length reads/writes. BSB is the block selection bits to say which memory i want to access.&lt;/p&gt;
&lt;p&gt;The first test is always the same: read VERSIONR (register 0x39 in the common block, BSB 0x00). The W5500 should respond as 0x04.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static int w5500_read(uint16_t addr, uint8_t *rx, int len)
{
    uint8_t tx[3] = {
        (uint8_t)(addr &amp;gt;&amp;gt; 8),                   /* ADDR_H */
        (uint8_t)(addr &amp;amp; 0xFF),                 /* ADDR_L */
        (W5500_BSB_COMMON &amp;lt;&amp;lt; 3) | W5500_READ    /* control: BSB 0x00, READ */
    };
    return spi_read_write(tx, 3, rx, len);
}

uint8_t version = 0;
w5500_read(W5500_REG_VERSIONR, &amp;amp;version, 1);
if (version != 0x04) {
    printf(&amp;quot;W5500 not responding. VERSIONR = 0x%02x\n&amp;quot;, version);
    return -1;
}
printf(&amp;quot;W5500 alive. VERSIONR = 0x%02x\n&amp;quot;, version);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;BSB = 0x00  Common registers // (VERSIONR, IP config etc.)
BSB = 1, 5, 9, 13... → Socket 0, 1, 2, 3... register space (status, control, RX/TX pointers)
BSB = 2, 6, 10, 14... → Socket 0, 1, 2, 3... transmit buffer
BSB = 3, 7, 11, 15... → Socket 0, 1, 2, 3... receive buffer


The formula for socket n:
Registers: BSB = (n * 4) + 1
TX buffer: BSB = (n * 4) + 2
RX buffer: BSB = (n * 4) + 3&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1jnr6ecs91"&gt;Never on the same boat, I mean Voltage&lt;/h3&gt;
&lt;p&gt;But my code was being heard on deaf ears, No response. I tried going though the documentation, it&amp;#39;s clear as day. It should work, But it did not. So, I hooked up my logic analyzer. No signals on the clock lines. Then spend an hour trying to see why the SPI peripherals is not being initiated. I even compiled the official examples, yet no avail. But then I &amp;quot;Accidentally&amp;quot; Clicked the Analog reading of the signal lines and then i saw something like an ECG. The SPI&amp;#39;s clock line. But the logic levels was around 1.7V. And then it hit me. The chip is communicating at 1.8V levels. But W5500 Does not respond back to such levels. So first instinct, I used TXB108 Level shifter, I checked the output lines, and it was working but W5500 Never responded. I was greeted with 0xFF&lt;/p&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/452/Logic-Pro-16_5F00_2.png" /&gt;&lt;/p&gt;
&lt;p&gt;Now, what i noticed is that when i reset, the MOSI was not very consistent. Ideally it was supposed to sent 0x00 0x39 0x00 0x00 (the image above has the ideal sequence) but many times i noticed, there would be extra 0xFF in between the right sequence. I felt the level shifter had to do something to with the ghost bits, In my past, the level shifter had created issues for me. Without a reliable level shifting, I was stuck, But then i remembered the MAX32630 was working fine with the I2C lines which was pulled up to 3.3V which means it is 3.3V tolerant,&amp;nbsp; so i dug into the documentation to find, i can change the Logic level of the Pins on an individual level. Whoa is what i said,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;By changing the&amp;nbsp;IOMAN has select bits to move a pins output buffer to another voltage level (&lt;code&gt;use_vddioh_0/1/2&lt;/code&gt;). By calling&amp;nbsp;&lt;code&gt;SYS_IOMAN_UseVDDIOH(&amp;amp;cfg)&lt;/code&gt;&amp;nbsp;after &lt;code&gt;SPIM_Init&lt;/code&gt;, I get a 3.3V SPI Signals&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;const spim_cfg_t spim_cfg = { .mode=0, .ssel_pol=SPIM_SSEL0_LOW, .baud=1000000 };
SPIM_Init(MXC_SPIM2, &amp;amp;spim_cfg, &amp;amp;sys_cfg);

const gpio_cfg_t spim2_vddioh = {
    PORT_5, (PIN_0 | PIN_1 | PIN_2 | PIN_3),
    GPIO_FUNC_GPIO, GPIO_PAD_NORMAL
};
SYS_IOMAN_UseVDDIOH(&amp;amp;spim2_vddioh);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Careful enough to change only the SPI lines i tried again and It is alive. W5500 was talking back 0x40.&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/452/Logic-Pro-16_5F00_4.png" /&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/452/20260418_5F00_230800-_2D00_-Copy.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jnr74cpp2"&gt;Back to SPI Protocol&lt;/h2&gt;
&lt;p&gt;To write a register,&amp;nbsp; i use&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static int w5500_write(uint16_t addr, const uint8_t *tx, int len)
{
    uint8_t cmd[3] = {
        (uint8_t)(addr &amp;gt;&amp;gt; 8),
        (uint8_t)(addr &amp;amp; 0xFF),
        (W5500_BSB_COMMON &amp;lt;&amp;lt; 3) | W5500_WRITE   /* BSB 0x00, WRITE */
    };
    return spi_write(cmd, 3, tx, len);
}

uint8_t mac[6] = {0x00, 0x08, 0xDC, 0xAB, 0xCD, 0xEF};
w5500_write(W5500_REG_SHAR, mac, 6);            /* set source hardware address */&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;To read a socket register, i use the the code below with the BSB calulated as per the code above&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;int sreg_read(int socket, uint16_t offset, uint8_t *rx, int len)
{
    uint16_t addr = offset;
    uint8_t bsb = W5500_BSB_SREG(socket);   /* computes (socket*4)+1 */
    uint8_t tx[3] = {
        (uint8_t)(addr &amp;gt;&amp;gt; 8),
        (uint8_t)(addr &amp;amp; 0xFF),
        (bsb &amp;lt;&amp;lt; 3) | W5500_READ
    };
    return spi_read_write(tx, 3, rx, len);
}

uint8_t sr;
sreg_read(0, Sn_SR, &amp;amp;sr, 1);   /* read socket 0 status register */
if (sr == SOCK_ESTABLISHED) {
    /* socket is connected */
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jnr7h5ge3"&gt;TCP: Open, Connect, Send, Receive, Close&lt;/h2&gt;
&lt;p&gt;The W5500 has a simple socket abstraction. Each operation sets a CR (Command Register) value and polls the SR (Status Register) for the result/&lt;/p&gt;
&lt;figure class="table-figure"&gt;
&lt;table border="1"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Write CR&lt;/th&gt;
&lt;th&gt;Poll SR until&lt;/th&gt;
&lt;th&gt;Timeout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Open&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CR_OPEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SOCK_INIT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;100 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connect&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CR_CONNECT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SOCK_ESTABLISHED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CR_SEND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Sn_IR.SEND_OK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recv&lt;/td&gt;
&lt;td&gt;(no cmd)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Sn_RX_RSR &amp;gt; 0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;per attempt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Close&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CR_DISCON&lt;/code&gt; then &lt;code&gt;CR_CLOSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SOCK_CLOSED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;
&lt;p&gt;The So i code&amp;nbsp;&lt;code&gt;tcp_recv&lt;/code&gt;, which reads in a loop until either the buffer fills or the remote closes the connection and yes, i used HTTP1 which i copied from the regular arduino library.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static int tcp_recv(int sn, uint8_t *buf, int max_len)
{
    int total = 0;
    for (int idle = 0; idle &amp;lt; 100 &amp;amp;&amp;amp; total &amp;lt; max_len; idle++) {
        uint16_t avail = sreg_r16(sn, Sn_RX_RSR);
        if (avail == 0) {
            uint8_t sr = sreg_r8(sn, Sn_SR);
            if (sr == SOCK_CLOSE_WAIT || sr == SOCK_CLOSED) break;
            TMR_Delay(MXC_TMR0, MSEC(50));
            continue;
        }
        int n = avail;
        if (total + n &amp;gt; max_len) n = max_len - total;
        uint16_t rd = sreg_r16(sn, Sn_RX_RD);
        srx_read(sn, rd, buf + total, n);
        sreg_w16(sn, Sn_RX_RD, rd + (uint16_t)n);
        sreg_w8(sn, Sn_CR, CR_RECV);
        total += n;
        idle = 0;
    }
    return total;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I did use static ip configuration for my LAN, and copied more and more working from the arduino library to interface the actual requests. Explaining that will be far too gruesome and more sleep inducing than Propofol So i will end it here. Now for the 3D printing and integration&lt;/p&gt;
&lt;h2 id="mcetoc_1jnr8dor24"&gt;Final Notes&lt;/h2&gt;
&lt;p&gt;When you are used to Arduino Libraries for quick prototyping, you forget to appreciate the work done by the developers to get these things working. Even porting an existing code to a diferent platform to make it work the SDK is a huge task. So respects to the Developers.&amp;nbsp; Now, truth be told, My code is bit flaky and does not work 20% of the time, I am not going to solve this considering the timeline. But i will take it as a good enough work for the final integration and solve it there if needed.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-c" lang="c"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Sentinel Box - Part II - back to C</title><link>https://community.element14.com/thread/56894?ContentTypeID=0</link><pubDate>Thu, 30 Apr 2026 12:42:46 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:085fd39e-8ab5-43de-a7db-bbc8127d7724</guid><dc:creator>saramic</dc:creator><slash:comments>4</slash:comments><comments>https://community.element14.com/thread/56894?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56894/sentinel-box---part-ii---back-to-c/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I had fun with my&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Rust&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f980.svg" title="Crab"&gt;&amp;#x1f980;&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;experiment but it was time to get back to&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;C &lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;LPSDK&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Low Power ARM Micro SDK) if I was going to get anything complete for this challenge.&lt;/p&gt;
&lt;h2 id="recap"&gt;Recap&lt;/h2&gt;
&lt;p&gt;The idea is to build a smart lock box for digital devices to help control digital addiction, more on the idea can be found in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;part I&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56869/sentinel-box---part-i---the-plan" data-e14adj="t"&gt;Sentinel Box - Part I - the plan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rust-for-hermetic-builds"&gt;Rust for Hermetic builds&lt;/h2&gt;
&lt;p&gt;As I was not super happy in having to depend on EOL (End-of-life) software stacks like Mbed or LPSDK, I thought, how hard can it be writing a HAL (Hardware Abstraction Layer) from scratch in Rust. I had some initial wins getting the LED flashing, so I continued. In&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;Part I&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;I even started implementing some commands against the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX14690 PMIC&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Power Management Integrated Circuit) - I was actually going above and beyond and looking at the schematic of the dev board to see how it hangs together. This should have&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;turned me OFF&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;the idea of rust, but it gave me some false hope and I continued.&lt;/p&gt;
&lt;p&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:640px;" alt="part of the MAX32630FTHR diagram highlighting the BMi160 accelerometer chip" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260430_5F00_01_5F00_max32630_5F00_BMi160_5F00_accelerometer.png" /&gt;&lt;br /&gt;The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;BMi160&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;accelerometer chip highlighted on the block diagram of the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX32630FTHR&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Next on the diagram there was an Accelerometer and Gyroscope using the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;BMi160&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;6-Axis Inertial Motion Sensor. With a bit of AI I soon enough had a driver to get X, Y, Z accelerations and using the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;MAX7219&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;I built a simple &amp;ldquo;attitude meter&amp;rdquo; which would show you which way to move the board to correct it being right way round. At this point I started to notice that some of the timing was out, my LED refresh rate was out by anywhere from 4x to 20x - that should have&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;turned me OFF&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;the idea of rust but with false hopes I continued.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/452/20260423_5F00_01_5F00_attitude_5F00_meter.mp4"&gt;community.element14.com/.../20260423_5F00_01_5F00_attitude_5F00_meter.mp4&lt;/a&gt;&lt;br /&gt;The video above shows the attitude meter&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f6e9.svg" title="Airplane small"&gt;&amp;#x1f6e9;&lt;/span&gt;️ that displays on the LED matrix the direction to turn the device to flatten the chip.&lt;/p&gt;
&lt;p&gt;These were all distractions from the core of the Smart Security Challenge, so it was time to use a finger print reader. This would need&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;UART&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Universal Asynchronous Receiver-Transmitter) surely that cannot be hard? Well this is where the speed changes of 4X &amp;ndash; 20X really started to bite. You see if you don&amp;rsquo;t know how fast your clock speed is going, you are not going to be able to transmit or receive at a given Baud. I tried a bunch of things. As I don&amp;rsquo;t have a logic analyzer nor oscilloscope on hand, I ended up hooking up an&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;ESP32&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to measure the duration of pulses. I didn&amp;rsquo;t know there was a function to measure pulse length&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://docs.arduino.cc/language-reference/en/functions/advanced-io/pulseIn/" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;pulseIn&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="language-c highlighter-rouge"&gt;
&lt;div class="highlight"&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;unsigned long width = pulseIn(RX2_PIN, LOW, 5000000UL); // 5 s timeout
if (width == 0) {
  Serial.println(&amp;quot;timeout — no signal on RX pin&amp;quot;);
  return;
}
// Filter noise: allow 1200–115200 baud = 8–833 &amp;#181;s.
if (width &amp;lt; 8 || width &amp;gt; 833) {
  Serial.printf(&amp;quot;noise/glitch: %lu &amp;#181;s (ignored)\n&amp;quot;, width);
  return;
}
unsigned long estimated_baud = 1000000UL / width;
  // Square-wave formula: CPU MHz = N / width_&amp;#181;s, where N is the delay_cycles count.
  // Firmware step 1 uses N=4800. Steps double: 4800, 9600, 19200, 38400, 76800.
  // Read the first group of pulses (smallest width) and use N=4800.
Serial.printf(
  &amp;quot;LOW pulse: %lu &amp;#181;s | sq-wave asm::delay(4800)~9600 cycles: CPU ~%lu MHz\n&amp;quot;,
  width,
  9600UL / width); // asm::delay(N) ≈ 2N cycles → CPU MHz = 9600 / width_&amp;#181;s&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The above code also made me realise that&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color:#999999;font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;\n&lt;/code&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;does not cut it and my serial monitor only displayed the output when I had&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color:#999999;font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;\r\n&lt;/code&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- need that Carriage return.&lt;/p&gt;
&lt;p&gt;And all my Rust results were conclusive on 1 part, I was never getting 96 MHz. After some digging around I found the C file in LPSDK that seems to do the setup of the frequency&lt;/p&gt;
&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;Maxim/Firmware/MAX3263X/Libraries/CMSIS/Device/Maxim/MAX3263X/Source/system_max3263x.c&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enable the 32 kHz RTC oscillator&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; this serves as the stable reference clock for calibration, then wait for it to warm up and settle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable the RO calibration complete interrupt&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; so the system can signal when calibration is done.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clear the calibration complete interrupt flag&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; removing any stale state from a previous run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write an initial trim&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;value into the frequency calibration initial condition register &amp;mdash; giving the hardware a starting point rather than hunting from scratch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Load that initial trim&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;into the active frequency trim register &amp;mdash; making it live.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable the frequency control loop&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; the hardware mechanism that will drive the RO trim toward the target frequency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start calibration in atomic mode&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; the hardware runs the measurement and adjustment cycle uninterrupted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wait for the ro_cal_done flag&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; polling until the hardware signals completion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stop the calibration engine.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disable the calibration complete interrupt.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read back the final trim value&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; the digital code the loop converged on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write the final trim to the RO flash trim shadow register&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; persisting the result across resets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restore the RTC to its previous state&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; since it may have been off before the routine borrowed it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disable the frequency control loop.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;no can do - I tried and tried again but could not get a consistent 96 MHz set which meant the UART was not going to work and the rust experiment was over for the time being&lt;/p&gt;
&lt;p style="font-size:100px;text-align:center;"&gt;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/274c.svg" title="X"&gt;&amp;#x274c;&lt;/span&gt;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f980.svg" title="Crab"&gt;&amp;#x1f980;&lt;/span&gt;&lt;/p&gt;
&lt;h1 id="back-to-lpsdk"&gt;Back to LPSDK&lt;/h1&gt;
&lt;p&gt;I couldn&amp;rsquo;t get myself to go to Mbed, a platform that is slated for EOL in July 2026, so it was back to C and the legacy LPSDK stack.&lt;/p&gt;
&lt;p&gt;Hitting up my ESP32 setup, proved I had the right frequency set on UART and in no time I was connected to the fingerprint reader. The problem was that now my system would need to be multi modal. I pulled in a rotary encoder and got some runs on the board. First just to read turns to the left and right as well as a button press and display it on the LED MAX7219 matrix display. Then I added in the finger print reader.&lt;br /&gt;&lt;br /&gt;&lt;img loading="lazy" style="display:block;margin-left:auto;margin-right:auto;max-height:360px;max-width:640px;" alt="Fingerprint reading success and failure" src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/452/20260430_5F00_02_5F00_fingerprint_5F00_demo_5F00_short.gif" width="620" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/452/20260430_5F00_03_5F00_fingerprint_5F00_demo.mp4"&gt;community.element14.com/.../20260430_5F00_03_5F00_fingerprint_5F00_demo.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Getting the fingerprint, LED Matrix and rotary encoder was the easy bit, but having a state diagram that can save a bunch of fingerprints and identify them was starting to get a bit complicated, as is the setup on my workbench.&lt;img loading="lazy" style="display:block;margin-left:auto;margin-right:auto;max-height:960px;max-width:640px;" alt="Encoder and fingerprint state machine flow chart" height="960" src="https://community.element14.com/resized-image/__size/1920x4128/__key/communityserver-discussions-components-files/452/2273.20260430_5F00_04_5F00_encoder_5F00_state_5F00_machine.png" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="next"&gt;Next&lt;/h2&gt;
&lt;p&gt;Now that I have a basic fingerprint reader and a build system that I am confident in, I think I need to get the required piece for a minimal complete build, some kind of actuator working: stepper motor, servo motor or just a motor with a worm drive. This will allow me to create a lock box with multi finger print triggering. If I get time, I may be able to expand on that. Time will tell.&lt;/p&gt;
&lt;h2 id="source"&gt;Source&lt;/h2&gt;
&lt;p&gt;&lt;a id="" href="https://github.com/saramic/sentinel-box" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://github.com/saramic/sentinel-box&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Guardian Sentinel &lt;Part 2&gt;  — Getting Started</title><link>https://community.element14.com/thread/56893?ContentTypeID=0</link><pubDate>Thu, 30 Apr 2026 08:39:01 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:e847499f-2d80-430b-9267-17c43e86a09d</guid><dc:creator>meera_hussien</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/56893?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56893/guardian-sentinel-part-2-getting-started/rss?ContentTypeId=0</wfw:commentRss><description>&lt;h1 id="mcetoc_1jnahmpi20" style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;strong&gt;Guardian Sentinel &amp;mdash;&amp;nbsp;Getting Started&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;h1 id="mcetoc_1jnahmpi21" style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&amp;lt;Part 2&amp;gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;The figure below shows the basic block diagram and idea of how the project will be implemented. The system will consist of two parts: a master and a slave. The master will use the MAX32630FTHR and will be connected to the LAN through an Ethernet FeatherWing. It will also include a&amp;nbsp;OLED&amp;nbsp;FeatherWing to display status or other useful information. The slave will use another MAX32630FTHR together with the DC Motor + Stepper FeatherWing and a gas sensor. This is the basic idea of the project architecture. Along the process of building of this project i will make the necessary changes in order to accomplish the objective of this project.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;img alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:678px;max-width:904px;"  height="678" src="https://community.element14.com/resized-image/__size/1808x1356/__key/communityserver-discussions-components-files/452/Green-and-White-Project-Phases-Flowchart-_2800_1_2900_.png" width="904" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;As i have mentioned previously, in this second post we would like to see in details and initial setup for all the devices used in this project. First lets take a look at the core of this project which is the MAX32630FTHR. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jnd0uq7k0"&gt;&lt;span style="font-size:inherit;"&gt;&lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;"&gt;MAX32630FTHR&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;From my initial research i found that the&amp;nbsp;&lt;span&gt;MAX32630FTHR can be programmed using MBED OS, but unfortunately it will become obsolete or end of life this coming July. Hence while looking for other alternative, i saw the post from&amp;nbsp;&lt;a href="https://community.element14.com/members/alistairuk"&gt;Alistair&lt;/a&gt;&amp;nbsp;, mentioning about using Arduino to program the&amp;nbsp;MAX32630FTHR. Here is my initial setup and the step to program the&amp;nbsp;MAX32630FTHR using Arduino&amp;nbsp;IDE. Below is the step to program the&amp;nbsp;MAX32630FTHR with Arduino IDE. Please note that, it can be only used with Arduino IDE 1.8.x. I tried using Arduino 2.3.8, but it does not work.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:5264px;max-width:819px;"  height="5264" src="https://community.element14.com/resized-image/__size/1638x10528/__key/communityserver-discussions-components-files/452/image_5F00_2026_2D00_04_2D00_30_5F00_002543939.png" width="819" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;Once the board is installed. I tried to program the board. The setup for programming the board is as shown in figure below&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;img loading="lazy" alt="image" style="max-height:524px;max-width:393px;"  height="524" src="https://community.element14.com/resized-image/__size/786x1048/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_04_2D00_30_5F00_00_2D00_30_2D00_44.jpg" width="393" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;Programming the MAX32630FTHR setup.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;img loading="lazy" alt="image" style="max-height:533px;max-width:399px;"  height="533" src="https://community.element14.com/resized-image/__size/798x1066/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_04_2D00_30_5F00_00_2D00_31_2D00_52.jpg" width="399" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;Both the usb need to be connected. The usb on the MAX32630FTHR is for power up the device. And the usb connecting the pico is for programming purpose.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;Once the this is done. I try to upload a simple Blink example, to verify. First choose the board as shown in the image below&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:559px;max-width:796px;" height="559" src="https://community.element14.com/resized-image/__size/1592x1118/__key/communityserver-discussions-components-files/452/pastedimage1777481343886v6.png" width="796"  /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;Next choose the programmer as shown in image below&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:555px;max-width:695px;" height="555" src="https://community.element14.com/resized-image/__size/1390x1110/__key/communityserver-discussions-components-files/452/pastedimage1777481384485v7.png" width="695"  /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;Once done, i tested the simple blink program and it works. Below is the&amp;nbsp;demo video&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/452/video_5F00_2026_2D00_04_2D00_30_5F00_00_2D00_55_2D00_04.mp4"&gt;community.element14.com/.../video_5F00_2026_2D00_04_2D00_30_5F00_00_2D00_55_2D00_04.mp4&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;The next thing that i would like to test is the Oled FeatherWing&amp;nbsp;which i am using to display the data. For connection between the MAX32630FTHR and the oled i am using the Ethernet FeatherWing. The setup for this is shown in the figure below&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:573px;max-width:429px;"  height="573" src="https://community.element14.com/resized-image/__size/858x1146/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_04_2D00_30_5F00_01_2D00_18_2D00_30.jpg" width="429" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;Once the sample code is uploaded, the oled works.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:560px;max-width:420px;"  height="560" src="https://community.element14.com/resized-image/__size/840x1120/__key/communityserver-discussions-components-files/452/photo_5F00_2026_2D00_04_2D00_30_5F00_01_2D00_42_2D00_04.jpg" width="420" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;The code for the oled is as shown below.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-align:left;"&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;Adafruit_GFX.h&amp;gt;
#include &amp;lt;Adafruit_SSD1306.h&amp;gt;

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_ADDR 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;amp;Wire);

void setup() {
  Serial.begin(9600);
  delay(1000);

  Serial.println(&amp;quot;MAX32630FTHR OLED Test&amp;quot;);

  Wire.begin();

  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(&amp;quot;OLED not found at 0x3C&amp;quot;);
    while (1);
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);

  display.println(&amp;quot;Guardian Sentinel&amp;quot;);
  display.println(&amp;quot;MAX32630FTHR&amp;quot;);
  display.println(&amp;quot;OLED OK&amp;quot;);

  display.display();

  Serial.println(&amp;quot;OLED initialized&amp;quot;);
}

void loop() {
}&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:tahoma, arial, helvetica, sans-serif;font-size:200%;"&gt;&lt;span style="font-size:75%;"&gt;&lt;span&gt;In the next post, i will share on the Ethernet FeatherWing and also the setting up of the dashboard.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Forum#5: Proposed Design — Adaptive Sentinel: Security &amp; Surveillance Intelligence Hub</title><link>https://community.element14.com/thread/56892?ContentTypeID=0</link><pubDate>Thu, 30 Apr 2026 04:37:36 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:93dc9d1b-bf47-4334-869b-6f0271bf4c2d</guid><dc:creator>skruglewicz</dc:creator><slash:comments>3</slash:comments><comments>https://community.element14.com/thread/56892?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56892/forum-5-proposed-design-adaptive-sentinel-security-surveillance-intelligence-hub/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;This Forum post outlines the architecture and the strategic logic driving the system&amp;rsquo;s coordination.&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;Design Lineage&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;The foundation of this design is rooted in the&amp;nbsp;&lt;/span&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-spaces-design-challenge/a/projects/PR101/adaptive-environmental-monitoring-and-smart-access-control" data-e14adj="t"&gt;&lt;span style="font-weight:400;"&gt;Adaptive Environmental Monitoring&lt;/span&gt;&lt;/a&gt;&lt;a href="https://www.google.com/search?q=https://www.hackster.io/stkrugle/adaptive-environmental-monitoring-sentinel-7b2432" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt; &lt;/a&gt;&amp;nbsp;&lt;span style="font-weight:400;"&gt;project. By leveraging that established architecture, the Adaptive Sentinel expands from purely environmental tracking into a proactive security framework, maintaining the core principles of modularity and edge-based intelligence.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;Basic Design: The Architectural Framework&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;The system is structured around a robust hub-to-node topology, designed for high reliability and low-latency response:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li style="font-weight:400;"&gt;&lt;b&gt;Centralized Coordination&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: At the heart of the ecosystem is the &lt;/span&gt;&lt;b&gt;Arduino UNO Q&lt;/b&gt;&lt;span style="font-weight:400;"&gt;. It serves as the primary hub, orchestrating the network, aggregating telemetry, and managing high-level logic. The use of containerized Bricks will be helpful in carrying out these tasks without compromising the core system&amp;#39;s stability.&lt;/span&gt;&lt;/li&gt;
&lt;li style="font-weight:400;"&gt;&lt;b&gt;Deployment of Edge Nodes&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: To provide a direct interface for localized relays and sensors, I intend to position &lt;/span&gt;&lt;b&gt;edge nodes based on FeatherWing&lt;/b&gt;&lt;span style="font-weight:400;"&gt; in designated building zones, acting as the primary frontline for data collection.&lt;/span&gt;&lt;/li&gt;
&lt;li style="font-weight:400;"&gt;&lt;b&gt;System Layout &amp;amp; Logic&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: The operational flow is decentralized yet unified. Edge nodes monitor local environments and transmit critical telemetry to the Arduino UNO Q hub for centralized aggregation and automated response.&lt;/span&gt;&lt;/li&gt;
&lt;li style="font-weight:400;"&gt;&lt;b&gt;Connectivity Strategy&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: I intend to establish a robust &lt;/span&gt;&lt;b&gt;UART infrastructure&lt;/b&gt;&lt;span style="font-weight:400;"&gt; to guarantee stability during the primary rollout. This wired setup will serve as a performance benchmark, providing a structured path for transitioning to wireless protocols after the integration has been thoroughly confirmed.&lt;/span&gt;&lt;/li&gt;
&lt;li style="font-weight:400;"&gt;&lt;b&gt;Sensor Integration&lt;/b&gt;&lt;span style="font-weight:400;"&gt;:&lt;/span&gt;&lt;b&gt;Sensor Strategic Integration&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: I intend to strategically select and integrate kit-supplied sensors to maximize the hardware&amp;rsquo;s efficacy in detecting security breaches and maintaining environmental awareness.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;b&gt;Visualizing the Hub-to-Node Topology&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;The following Basic Design Diagram details the mapping of FeatherWing edge nodes across various zones. By utilizing the Arduino UNO Q as the central coordinator, the architecture remains scalable.&lt;/span&gt;&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/452/pastedimage1777523732195v1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Hub-to-Node Connectivity Design: &lt;/b&gt;&lt;span style="font-weight:400;"&gt;This system utilizes a robust hub-to-node topology centered on an Arduino UNO Q coordinator, managing modular FeatherWing edge nodes for localized intelligence. The initial rollout employs a stable UART connectivity strategy. The edge nodes are deployed in two primary functional configurations: Edge Node 1 for Biometrics &amp;amp; Sentiment Analysis, and Edge Node 2 for Active Response &amp;amp; Environmental Control.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;HUB Node Architecture&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: Built on the Arduino UNO Q, the central hub functions as the primary network coordinator, aggregating telemetry from FeatherWing edge nodes. This architecture leverages a dual-processor system where the MPU handles high-level orchestration, intensive data logging, and serving the Web UI, while the MCU manages deterministic low-level communication protocols. Furthermore, the system utilizes a specialized Database BRICK to ensure the reliable storage of all telemetry data streamed from the distributed edge nodes.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Edge Node Architecture&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: Edge nodes are implemented as &lt;/span&gt;&lt;b&gt;modular expansion subsystems&lt;/b&gt;&lt;span style="font-weight:400;"&gt;. The current deployment strategy utilizes the following functional configurations for localized intelligence.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Edge Node 1 (Biometrics &amp;amp; Sentiment Analysis)&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: This node focuses on human-centric data, monitoring biometric signatures and localized sentiment to assess security states based on occupant presence and behavior.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Edge Node 2 (Active Response &amp;amp; Environmental Control)&lt;/b&gt;&lt;span style="font-weight:400;"&gt;: Serving as the primary execution layer, this node manages physical relays and automated control systems to mitigate identified threats or adjust climate variables in real-time.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;The &amp;quot;Request for Help&amp;quot;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;Before I finalize the Project Blog and lock in the implementation, I am reaching out to the community. Prior to finalizing the Project Blog and committing to this implementation, I am seeking community insights. I invite you to &lt;/span&gt;&lt;b&gt;&amp;quot;identify any loopholes&amp;quot;&lt;/b&gt;&lt;span style="font-weight:400;"&gt; or logical flaws in my current approach.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:400;"&gt;Specifically, I am interested in your thoughts on whether the transition from UART to wireless is technically sound and if there are hidden bottlenecks in the hub-to-node telemetry aggregation. My goal is to uncover any technical gaps in the orchestration of this security intelligence system before moving to final deployment.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;I value your expertise and look forward to the feedback.&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>BLE scanning and CC256X firmware uploading</title><link>https://community.element14.com/thread/56886?ContentTypeID=0</link><pubDate>Tue, 28 Apr 2026 12:02:18 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:db78488d-c1dd-4e01-a2fd-45db04a8ba9e</guid><dc:creator>Alistair</dc:creator><slash:comments>13</slash:comments><comments>https://community.element14.com/thread/56886?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56886/ble-scanning-and-cc256x-firmware-uploading/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;After thinking I had everything in place I have just got wound to the BLE scanning, and it turns out that it it not working. Basic Bluetooth functionality appraiser fine, but the BLE functionality is not there. Doh!&lt;/p&gt;
&lt;p&gt;Following a hint from online I trued the command&amp;nbsp;01 01 FE 01 00 (HCI_VS_Write_BD_Addr) and that returned&amp;nbsp;0x01&amp;nbsp;(Unknown HCI Command), and that&amp;nbsp;shown new firmware needs uploading. Has anyone done this?Any other suggestions for that matter?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Identity Protocol - Part 9 - BLE GATT Challenge/Response with BTstack</title><link>https://community.element14.com/thread/56883?ContentTypeID=0</link><pubDate>Tue, 28 Apr 2026 06:01:28 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:e95ef095-977a-4aae-ac9e-780d887835be</guid><dc:creator>arvindsa</dc:creator><slash:comments>6</slash:comments><comments>https://community.element14.com/thread/56883?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56883/identity-protocol---part-9---ble-gatt-challenge-response-with-btstack/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;It has been long time since i used Bluetooth SPP. Infact I do not think I ever used Bluetooth SPP via firmware. I think i used an RN42 module to get UART converted to Bluetooth SPP. But I have used BLE GATT so, I will be using that to exchange data between the Door and ID device.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The idea is simple enough: stop making people swipe a card and type a PIN at every single door. Instead, the ID card (a MAX32630FTHR + ATECC508A in your pocket) unlocks once via PIN, then silently does challenge-response crypto over Bluetooth every time you walk up to a door. If the card gets yanked off you, the IMU detects the tug and it locks itself. No PIN, no entry. For more details check the Part 1 of the series&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56768/identity-protocol-part-1---plan" data-contentid="d5152729d060498f812f0244641b3810" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol Part 1 - Plan&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56830/identity-protocol---part-2---django-server" data-contentid="1ab561efc7f2445b8eb20783970ed89c" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol - Part 2 - Django Server&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56840/identity-protocol---part-3---unboxing-and-blinking-with-maxim-lpsdk" data-contentid="75fef2ca1ed74f3ca296a48a29402617" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol - Part 3 - Unboxing and Blinking with Maxim LPSDK&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a class="ui-contentpeek internal-link" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56853/identity-protocol---part-4---ble-using-pan1326b-and-btstack" data-contentid="b449688fb5c8477991ced940f32ac3fa" data-contenttypeid="46448885d0e64133bbfbf0cd7b0fd6f7" data-e14adj="t"&gt;Identity Protocol - Part 4 - BLE using PAN1326B and BTstack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title="Identity Protocol - Part 5 - Interfacing a Keypad" href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56856/identity-protocol---part-5---interfacing-a-keypad" data-e14adj="t"&gt;Identity Protocol - Part 5 - Interfacing a Keypad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56861/identity-protocol---part-6---snatch-detection-with-the-bmi160-imu" data-e14adj="t"&gt;Identity Protocol - Part 6 - Snatch Detection with the BMI160 IMU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56861/identity-protocol---part-6---snatch-detection-with-the-bmi160-imu" data-e14adj="t"&gt;&lt;/a&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56874/identity-protocol---part-7---colouring-on-the-icled-featherwing" data-e14adj="t"&gt;Identity Protocol - Part 7 - Colouring on the ICLED FeatherWing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56881/identity-protocol---part-8---cryptographically-sign-with-atecc508-and-verify-with-micro-ecc" data-e14adj="t"&gt;Identity Protocol - Part 8 - Cryptographically Sign with ATECC508 and Verify with Micro-ECC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcetoc_1jn9ae2790"&gt;GATT Service Definition&lt;/h2&gt;
&lt;p&gt;BTstack generates an ATT database at plaintext &lt;code&gt;.gatt&lt;/code&gt; file. Refer: &lt;a class="url" href="https://github.com/bluekitchen/btstack/blob/master/tool/compile_gatt.py" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;https://github.com/bluekitchen/btstack/blob/master/tool/compile_gatt.py&lt;/a&gt; For our purpose, I need to detect the door and ID card to be nearby, one service to write the nonce and another for the response. I did take help of ChatGPT to generate the file. If you are new to GATT - I recommend to watch this video -&amp;nbsp;&lt;a href="https://www.youtube.com/watch?v=eHqtiCMe4NA" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;www.youtube.com/watch&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ, &amp;quot;Auth-Door&amp;quot;

PRIMARY_SERVICE, GATT_SERVICE
CHARACTERISTIC, GATT_DATABASE_HASH, READ,

// Identity Protocol Auth Service
PRIMARY_SERVICE, AAAAAAAA-0000-0000-0000-000000000001

// CHALLENGE: 32-byte nonce sent by the door, read by the card
CHARACTERISTIC, AAAAAAAA-0000-0000-0000-000000000002, READ | DYNAMIC,

// RESPONSE: 4-byte device_id followed by 64-byte signature written by the card
CHARACTERISTIC, AAAAAAAA-0000-0000-0000-000000000003, WRITE | DYNAMIC,
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="mcetoc_1jn9ae2791"&gt;For Testing two Roles, One Source File&lt;/h2&gt;
&lt;p&gt;Both the door and the card run on identical hardware (MAX32630FTHR + PAN1326B), so the test is a single C file compiled twice. A &lt;code&gt;ROLE&lt;/code&gt; make variable drives the split:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell" lang="shell"&gt;make ROLE=server    # door firmware
make ROLE=client    # card firmware
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;-DROLE_SERVER&lt;/code&gt; / &lt;code&gt;-DROLE_CLIENT&lt;/code&gt; select which half of &lt;code&gt;gatt_auth.c&lt;/code&gt; is compiled. The server advertises, serves CHALLENGE when ID card nearby, and verifies writes to RESPONSE. The client scans, connects, reads CHALLENGE, signs, and writes RESPONSE.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:450px;max-width:432px;"  src="https://community.element14.com/resized-image/__size/864x900/__key/communityserver-discussions-components-files/452/ble_2D00_gatt_2D00_sequence.png" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jn9ah6m42"&gt;The Server Side (Door)&lt;/h2&gt;
&lt;p&gt;The server&amp;#39;s packet handler wakes up three places: stack ready, client connected, and every ATT write. When client connected, we serve the once, when ATT writes to the signature service, we verify it.&lt;/p&gt;
&lt;p&gt;Even though i have only one feather to function as a ID device, i made the firmware such that it can store multiple ID Cards device name and their public key to be synced from the Django server.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;if (att_handle != RESPONSE_VALUE_HANDLE) return 0;

if (buffer_size != 68) {
    printf(&amp;quot;VERIFY FAIL, expected 68 bytes, got %u\n&amp;quot;, buffer_size);
    return 0;
}

uint32_t device_id = (buffer[0] &amp;lt;&amp;lt; 24) | (buffer[1] &amp;lt;&amp;lt; 16)
                   | (buffer[2] &amp;lt;&amp;lt; 8)  |  buffer[3];
const uint8_t *sig = buffer + 4;

// Serch for the public key from the flash. 
const uint8_t *pubkey = lookup_pubkey(device_id);
if (!pubkey) { 
    /* unknown device (not in django server, reject */ 
    return 0; 
}

// Generate the digest via the crypto chip
uint8_t digest[32];
atcac_sw_sha2_256(nonce, 32, digest);


// Verify using micro-ecc
int ok = uECC_verify(pubkey, digest, sig);
printf(ok ? &amp;quot;*** VERIFY PASS ***\n&amp;quot; : &amp;quot;*** VERIFY FAIL ***\n&amp;quot;);&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jn9ai5nn3"&gt;The Client Side (Card)&lt;/h2&gt;
&lt;p&gt;The client we make a state machine:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;typedef enum {
    STATE_IDLE,
    STATE_SCANNING,
    STATE_CONNECTING,
    STATE_DISCOVER_SERVICE,
    STATE_DISCOVER_CHARS,
    STATE_READ_CHALLENGE,
    STATE_WRITE_RESPONSE,
    STATE_DONE,
} client_state_t;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;On HCI state &lt;code&gt;HCI_STATE_WORKING&lt;/code&gt; the client calls &lt;code&gt;gap_start_scan()&lt;/code&gt; and watches for advertisements under name &amp;quot;Auth-Door&amp;quot;. When it sees one, we execute &lt;code&gt;gap_connect&lt;/code&gt;. once the state advances to &lt;code&gt;STATE_DISCOVER_SERVICE&lt;/code&gt; and a &lt;code&gt;gatt_client_discover_primary_services_by_uuid128&lt;/code&gt; call goes out with the auth service UUID.&lt;/p&gt;
&lt;p&gt;During the &lt;code&gt;STATE_READ_CHALLENGE&lt;/code&gt; phase , the 32 byte nonce has arrived from the server, the client hashes it, packs its own device ID into the first four bytes of the response buffer, and calls &lt;code&gt;atcab_sign&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;uint8_t digest[32];
atcac_sw_sha2_256(challenge, 32, digest);

response_buf[0] = (CLIENT_DEVICE_ID &amp;gt;&amp;gt; 24) &amp;amp; 0xFF;
response_buf[1] = (CLIENT_DEVICE_ID &amp;gt;&amp;gt; 16) &amp;amp; 0xFF;
response_buf[2] = (CLIENT_DEVICE_ID &amp;gt;&amp;gt;  8) &amp;amp; 0xFF;
response_buf[3] =  CLIENT_DEVICE_ID        &amp;amp; 0xFF;

atcab_sign(0, digest, response_buf + 4);

gatt_client_write_value_of_characteristic(
    handler, conn_handle, response_handle, 68, response_buf);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;device_id&lt;/code&gt; is the lower four bytes of the ATECC508A serial number which we saved during provisioning and locking of the chip along with it&amp;#39;s public key. This is the same four bytes the server will look up in its static keystore to find the public key.&lt;/p&gt;
&lt;p&gt;The ID Card&amp;#39;s LED lights up green when connecting to the door device and the door device&amp;#39;s LED turns green when the signing of nonce by ATEC508A is successfully verified by micro-ecc&lt;/p&gt;
&lt;h2 id="mcetoc_1jn9akd4n5"&gt;Result&lt;/h2&gt;
&lt;p&gt;With both bugs sorted, the UART log across two boards looks like this on a clean run.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="display:block;margin-left:auto;margin-right:auto;max-height:432px;max-width:800px;"  src="https://community.element14.com/resized-image/__size/1600x864/__key/communityserver-discussions-components-files/452/2026_2D00_04_2D00_17-gatt_2D00_auth-eccand-attec-working.PNG" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/452/blegatt.mp4"&gt;community.element14.com/.../blegatt.mp4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Again, i am using a PCB which i designed for a client to work like an breakout board for the ATTEC508A. Hence the blur.&amp;nbsp; After a successful verification, the door devices starts readvertising and i do have to reset the ID card to re-auth again.&amp;nbsp;&lt;/p&gt;
&lt;h2 id="mcetoc_1jn9ao9n77"&gt;Final Notes&lt;/h2&gt;
&lt;p&gt;Again, thanks to BTStacks awesome documentation, this was an easy three hour work after setting up ATECC508A. There was some hold up due to typo in the micro-ecc bundled by BTStack, which i thought was my problem but later I realized it was a bug. I did write the public key manually in the lookup table for this unit test, in the final unit test, I will interface W5500 to sync the public keys to the feather board.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-c" lang="c"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Using the Particle Ethernet FeatherWing with the MAX32630FTHR (Don't Forget to Set)</title><link>https://community.element14.com/thread/56882?ContentTypeID=0</link><pubDate>Mon, 27 Apr 2026 20:29:29 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:8db71070-4c6a-473b-80fc-f9857ade6860</guid><dc:creator>Alistair</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/56882?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/challenges-projects/design-challenges/smart-security-and-surveillance/f/forum/56882/using-the-particle-ethernet-featherwing-with-the-max32630fthr-don-t-forget-to-set/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;For my project I am using the &lt;a href="https://docs.particle.io/hardware/ethernet/ethernet-featherwing/" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Particle Ethernet FeatherWing&lt;/a&gt; to allow the MAX32630FTHR to communicate with the local network and enable my alarm.&lt;/p&gt;
&lt;p&gt;The Particle Ethernet FeatherWing is based around the WIZnet W5500 and under normal circumstances will work with the standard Arduino Ethernet library version 2.0.0+. This is however not compatible with the older Maxim core. It took a while but I worked round the problem, and here is my solution just in case it is helpful to someone else.&lt;/p&gt;
&lt;p&gt;Before we get into the software, we need to add some header pins to the MAX32630FTHR. My advice is to loosely place the pins in the FeatherWing and quickly solder on the corner pins. After that the header pins are held in place and the rest of the pins will be so much easier to solder.&lt;/p&gt;
&lt;p&gt;&lt;img 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/452/MAX32630FTHR-adding-pins-combined.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;My work around with the Arduino IDE 1.8 it to this is to use the older &lt;a href="https://docs.arduino.cc/libraries/ethernet2/" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Ethernet2 library&lt;/a&gt;, that is a drop in replacement to the version 1 Ethernet library but supports the W5500. This addresses most of the issues, but we still need to copy across a few files to get this to work. Here are the setup instructions...&lt;/p&gt;
&lt;p&gt;First install the &lt;a href="https://github.com/adafruit/Ethernet2/" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Ethernet2 library&lt;/a&gt; from the Arduino library manager (Sketch-&amp;gt;Include Library-&amp;gt;Manage Libraries&amp;hellip;).&lt;/p&gt;
&lt;p&gt;Once installed we need to copy the following files from the Arduino AVR core &amp;quot;%homepath%\Documents\ArduinoData\packages\arduino\hardware\avr\1.8.6\cores\arduino&amp;quot; to the Ethernet2 library directory &amp;quot;%homepath%\Documents\Arduino\libraries\Ethernet2\src&amp;quot;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Client.h&lt;/li&gt;
&lt;li&gt;Server.h&lt;/li&gt;
&lt;li&gt;IPAddress.h&lt;/li&gt;
&lt;li&gt;IPAddress.cpp&lt;/li&gt;
&lt;li&gt;Udp.h&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will note that although it would make more sense to copy the missing files to the Mamim core (&amp;quot;%homepath%\Documents\ArduinoData\packages\Maxim\hardware\arm\1.1.5\cores\arduino&amp;quot;&lt;span style="font-family:inherit;"&gt;) and not the Ethernet2 library, but doing this uncovers yet more issues that need to be addressed, so lets take the easy road on this occasion.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So after this modification, and including Ethernet2.h instead of Ethernet.h our standard Ethernet applications will compile but not run. We still need to tell the library what pin to use in our setup code. From &lt;a href="https://learn.adafruit.com/assets/34337" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;the schematic&lt;/a&gt; we can see the chip select is on pin 22 if the featherwing connector (traditionally GPIO10) and that is mapped to pin 7 on CON12 (P5.4 /SDIO 2) according to the &lt;a href="https://www.analog.com/media/en/technical-documentation/eval-board-schematic/max32630fthr-schematic.pdf" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;MAX32630FTHR schematic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, in English, just add &amp;ldquo;Ethernet.init(P5_4);&amp;rdquo; to setup() before calling &amp;ldquo;Ethernet.begin&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;And that is it. Here is a cut down version of the WebClient example to set with&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;SPI.h&amp;gt;
#include &amp;lt;Ethernet2.h&amp;gt;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = &amp;quot;www.google.com&amp;quot;;

EthernetClient client;

void setup() {

Serial.begin(115200);
Serial.println(&amp;quot;Starting...&amp;quot;);

Ethernet.init(P5_4);
Ethernet.begin(mac);

delay(1000);
Serial.println(&amp;quot;connecting...&amp;quot;);

if (client.connect(server, 80)) {
Serial.println(&amp;quot;connected&amp;quot;);

client.println(&amp;quot;GET /search?q=arduino HTTP/1.1&amp;quot;);
client.println(&amp;quot;Host: www.google.com&amp;quot;);
client.println(&amp;quot;Connection: close&amp;quot;);
client.println();
}
else {
Serial.println(&amp;quot;connection failed&amp;quot;);
}
}

void loop()
{
if (client.available()) {
char c = client.read();
Serial.print(c);
}

if (!client.connected()) {
Serial.println();
Serial.println(&amp;quot;disconnecting.&amp;quot;);
client.stop();
while (true);
}
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>