Skip to content

Week 11 : Networking and communications

PCB CNC milling not available at time of writing at the workspace. Thus, tests were mainly done on breadboard. The final result-with the CNC milling- could be seen further below

Networking refers to the connection of multiple devices that enables communication and the exchange of data between them. This approach offers several advantages as it enables modularity:

  • Reduce interference of signals i.e. separating voltage and signal buses
  • Allowing individual parts of a system to be developed, tested, and replaced

Week 11 assignment could be categorized as follows:

  • Group assignment

    • Direct wired/wireless communication between two nodes
  • Individual assignment

    • Wired/wireless integration (to designed embedded microcontroller system)
Basics of hardware communications

Hardware communication can be categorized into wired and wireless methods.

  • Wired

    • Communication method (how bits are transmitted):

      • Peripherals
        • PIO : Programmable processor inside (certain) microcontrollers for custom I/O behavior (e.g. want more than one I2C/SPI bus)
        • GPIO : Basic digital pins. Can be used for bit-banging (method of sending and receiving data manually through software and the GPIOs instead of using dedicated hardware peripheral and so could behave like the PIO)
        • Hardware specific peripherals :
          • UART/USART
          • I2C
          • SPI
      • Asynchronous serial communication (UART)

        • No shared clock signal between devices. Instead both sides must agree in advance on parameters such as the baud rate (number of bits transmitted per second). 9600 baud means each bit takes approximately 1 / 9600 ≈ 0.000104 sec (104 µs) to transmit.
        • Standards :
          • RS - 232 : Older standard using higher voltage levels (12 V)
          • RS - 485 : Used in industry
        • Communication schemes for multiple devices (methods or rules that define how devices exchange data on a network):
          • Serial broadcast : sending a message to all nodes on a network/bus. The master sends command through TX and all microcontrollers for example receive it on RX. IDs are assigned to devices so that it is clear if the message is meant for them or not.
          • Hop-count : sending message based on the number of devices that it has passed through. First device for example sends a message with hop = 0. Each device then incremenents the hop count as it forwardes the message. Advantage of this method is that no device IDs or address is needed (e.g. LED strips).
          • Broad-hop : Combination of serial broadcast and hop-count. Each devices could activate immediately and at the same time no device IDs or address is needed.
      • Synchronous serial communication

        • Receiver/slave and sender/master is used interchangeably.
        • Shared clock signal between devices. Master control the pulses/timing of the connected devices.
        • Types :
          • I2C/TWI :
            • Variations : QWIC from SparkFun, STEMMA (Adafruit)
            • Uses two lines :
              • SDA (serial data Line) : Carries data
              • SCL (serial clock line)
              • Implication : Data can go both direction, but only one direction at a time
            • Communication steps :
              • Start. Master initiates communication. SDA low. SCL high (high always mean that device should read, low means reject).
              • Master sends 7-bit address of the slave (i.e. select which device) and the R/W (read or write) bit. This is required because data can only go one direction at a time
              • At the 9th bit, the slave/received responds with ACK (i.e. acknowledged) or NACK (i.e. not acknowledged) and is represented by SDA low and SDA high respectively
              • Stop. SDA high. SCL high.
          • SPI :
            • Uses four lines :
              • MOSI (master out, slave in) : Carries data from master to slave
              • MISO (master in, slave out) : Carries data from slave to master
              • CS (chip select) : slave select i.e. activates a specific slave device
              • SCK : serial clock
              • Implication : Data can go both direction and at the same time
            • Communication steps :
              • Master selects slave. CS low
              • MOSI and MISO can run at the same time, and so the equivalent of ACK at I2C is simply the response from example the MISO
              • Stop signal. CS high
      • Communication protocol (rules, structure and system behaviour. Built on top of communication method):
        • USB :
          • Human interface device (HID) : keyboard, mouse, game controller, etc
          • Musical instrument digital interface (MIDI) : synthesizers, drumpads. Instead of raw data, it sends musical messages or instructions to create sound(Note ON, note OFF, velocity or how hard the button is pressed, control changes such as knobs and sliders)
        • Ethernet : widely used for local area networks (LANs). Operates at the layer 2 of the OSI (i.e. MAC) model
          • Note : Use the modules, not the chips.
        • CAN/LIN : Industrial application
        • MODBUS : Industrial application
        • DMX : Commonly used for street lighting systems

7 layers of networking :

This table maps the 7 OSI layers to embedded networking technologies, with the role descriptions included inline.

OSI Layer Role Embedded / Networking Examples
7. Application User-level protocol; what the device/application actually uses HTTP (web, runs with TCP), MODBUS TCP, MQTT (usually for IoT and low power devices), USB HID/MIDI
6. Presentation Handles encryption, compression, and data representation SSL/TLS (HTTPS), JSON / XML, MIDI packet formatting
5. Session Keeps track of ongoing conversations between devices TCP sessions, MQTT persistent sessions, WebSocket sessions
4. Transport Ensures data is delivered correctly and in order; manages ports (tells OS which application/service should handle incoming or outgoing network traffic. Without port numbers, computer will not know whether incoming data is meant for browser, email, or some other app, because all share the same IP address). TCP (client establishes a connection with server, data is sent in packets and each packet is acknowledged, lost packets are retransmitted), UDP (client sends packets to server no ACK, server receives what it can and missing packets are ignored); Modbus TCP; socket = combination of IP + port + transport protocol. Analogy: user's apartment number
3. Network Determines how data reaches the correct device across networks the correct device across networks IPv4/IPv6 (e.g. 192.168.1.1), DNS (human-readable IP names, e.g. www.tim.com), routing tables, Zigbee network addresses. Analogy: street address of the apartment
2. Data Link / MAC Prevents collisions, wraps data in frames, decides who talks when, unique identifier assigned to a network chip. Analogy is the apartment door name at the mailbox Ethernet MAC addresses, I²C/SPI master-slave rules, Wi-Fi CSMA/CA (listen first, transmit if idle; if busy, wait random time). Analogy: apartment door/mailbox name
1. Physical The hardware layer; bits moving over wires or wireless signals Ethernet cables, fiber optics, SPI/I²C/UART signals, Wi-Fi radio
  • Lower layers (1–2) → mostly handled by hardware (SPI, I²C, Ethernet, CAN controller)
  • Middle layers (3–4) → handled by hardware + software stacks (IP stack, TCP/UDP stack). Stacks here is defined as collection of software components that works together to implement a certain functionality.
  • Upper layers (5–7) → handled in firmware or application code (HTTP, MQTT, USB HID/MIDI)
  • Note :

    • Fabacademy generally focuses on layer 1 to 3
    • Virtual private network (VPN) :
      • Creates a secure, encrypted tunnel over the public Internet
      • Internet service providers may intentionally slow down specific traffic (throttling) and so with VPN it could be faster
      • Steps :
        • Your device sends data → VPN software encrypts it
        • Encrypted data is sent through the Internet to a VPN server
        • VPN server decrypts the data
        • VPN server forwards the request to the destination server (e.g. website)
        • Response comes back → VPN server encrypts it again
        • Your device receives and decrypts it
  • Wireless :

    • Frequency
      • Higher frequency, shorter wavelength. Carry more data but absorbed or reflected by obsatcles more easily (e.g. 2.4 GHz Wi-Fi), could be even just line of sight.
      • Lower frequency, longer wavelength. Carry less data, but travels farther and through walls (e.g. 433 MHz LoRa)
    • Capacity
      • Amount of data that a channel can carry reliably. Measured in bits per second (bps or Mbps).
      • Bandwidth : Range of frequencies a channel can use to transmit data. Measured in Hz. Higher
      • Signal-to-noise ratio (SNR) : Strength of desired signal vs background noise. Measured in dB.
      • High capacity = High bandwidth, high SNR
      • Note : In the ocean not much interference
    • Band : Range of radio frequencies grouped together for a specific type of communication. Example 2.400-2.4835 is equals to 2.4 GHz ISM band
      • Industrial, scientific, medical (ISM) bands are frequency ranges reserved for unlicensed used. Meaning anyone can use it without special government license.
      • IEEE standards for wireless communication :
    • Network model :

      • Client - server : device request data (client) or a device hosts data (server). Requires access points (AP) like Wi-Fi routers that manages wireless clients to connect to a network (e.g. converts digital data to radio waves at physical layer, then manages MAC addresses, prevents collissions, schedules timing of the communication between clients at the data link layer). Example: An ESP32 Wi-Fi module requests the current time from a server on the Internet. The request goes through a Wi-Fi router (AP), which forwards the data and sends back the response.
      • Mesh networking :Devices (nodes) communicate directly with each other without requiring a central AP. Data can hop through multiple intermediate nodes to reach its destination. Some nodes, called meshcore, manage routing and may connect the mesh to the Internet (e.g. Raspberry pi), while meshtatic or edge nodes relay data and perform sensing or actuation.
    • Technology :

      Technology Type Range Frequency Data Rate Power Usage Internet Support
      Wi-Fi RF 50–100 m 2.4 / 5 GHz 10–600 Mbps 100–1000 mW Yes
      Bluetooth (BLE) RF 10–50 m 2.4 GHz 125 kbps–2 Mbps 1–10 mW Indirect (via phone/gateway)
      RFID / NFC RF 0.04–0.1 m 13.56 MHz / 125–134 kHz 106–424 kbps ~0 mW (passive) No
      LoRa RF 2–15 km 433 / 868 / 915 MHz 0.3–50 kbps 10–100 mW No (requires LoRaWAN)
      Optical (IR) Light 1–10 m 400–800 THz 10–100 kbps 10–50 mW No
      • Radio Frequency (RF)

        • Wi-Fi

          • Requires access point (router)
          • Wireless local network (also LAN, see ethernet). Internet comes from the internet service provider and router/access point acts as a gateway between the two.
        • Bluetooth :

          • Bluetooth Low Energy (BLE) is a subset. nRF Toolbox by Nordic can be used for testing and communication
        • Radio Frequency Identification (RFID):
          • Near Field Communication (NFC) is a subset. No battery required. Harvest energy from the reader's electromagnetic field.
        • LoRA (Long Range)
          • LoRAWAN is a network protocol built on LoRA. Can be deployed as private or public networks
      • Optical (Light-based communication). Higher frequency than RF

        • Uses infrared or visible light
        • No licensing

Source: ChatGPT by OpenAI, April 2026

Direct wired/wireless communication between two nodes

In previous weeks, wired communication has already been explored multiple times. Therefore, the experiment this time primarily focuses on testing wireless communication between nodes. The XIAO ESP32C3 supports Bluetooth Low Energy (BLE), and so its functionality is tested to evaluate its usability and communication range.

The I2C communication with the microcontroller will be further investigated - building on the work from week 6 :Electronics design - using a logic analyzer to better understand and decode the data.

Bluetooth communication (2x XIAO ESP32C3)

A node consist of a XIAO ESP32C3 and is connected to an OLED display to show the status of the connection (i.e. connected or disconnected). The task of the corresponding nodes are as follows :

  • One acts as the server, advertising its presence and responding to data requests through services. Characteristics are individual pieces of information within those services, which clients can read or write.
  • One acts as the client. Scans nearby BLE devices and connects to the server.

It could be seen that the two devices could disconnect if a certain distance threshold is passed.

The code used for this experiment is primarily based on the official Seeed Studio example for BLE communication on the XIAO ESP32C3. It is adapted to fit the experiment setup and the code could be seen at the admonitions below. Since it works with the "pointers" concept, some explanations are also given below.

Basic info about pointers/scope resolution operator

A pointer is a variable that does not store a value directly, but instead stores the memory address of another variable or object. An example is given below :

BLEServer* pServer;
pServer = BLEDevice::createServer();
pServer->createService(SERVICE_UUID);

Where :

  • BLEServer a blueprint for a BLE server object. Essential to be called.
  • * is a pointer (stores the address of a BLEServer object)
  • pServer is variable name. Can also be other name
  • -> is a function that basically request the variable to access the address and use the function of the object
  • :: uses the original function of an object by the developer

Source: ChatGPT by OpenAI, April 2026

Server OLED x XIAO ESP32C3 BLE code

Server waits for client to connect, reacts through callbacks and updates the OLED respectively, and can notify client of any changes in the characteristic value.

For more details on the code i.e. programming language, please refer to resources online.

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// ----- OLED (128x64 I2C) -----
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDRESS 0x3C
#define PIN_SDA 6
#define PIN_SCL 7

// ----- BLE UUIDs -----
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define DEVICE_NAME         "thexiao"

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

BLEServer* pServer;
BLECharacteristic* pCharacteristic;

bool deviceConnected = false;
bool lastState = false; // track OLED updates

// OLED helper
void oledShow(const char* a, const char* b, const char* c, const char* d) {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println(a);
    display.println(b);
    display.println(c);
    display.println(d);
    display.display();
}

// BLE callbacks
class ServerCallbacks : public BLEServerCallbacks {
    void onConnect(BLEServer* server) override {
        deviceConnected = true;
        Serial.println("Device Connected");
    }

    void onDisconnect(BLEServer* server) override {
        deviceConnected = false;
        Serial.println("Device Disconnected");

        // Restart advertising
        delay(100);
        pServer->getAdvertising()->start();
        Serial.println("Advertising restarted");
    }
};

void setup() {
    Serial.begin(115200);

    // Initialize OLED
    Wire.begin(PIN_SDA, PIN_SCL);
    if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
        Serial.println(F("SSD1306 begin failed"));
        while (true) delay(1000);
    }
    oledShow("thexiao", "booting...", "", "");

    // BLE init
    BLEDevice::init(DEVICE_NAME);
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new ServerCallbacks());

    BLEService* pService = pServer->createService(SERVICE_UUID);

    // BLE characteristic with READ, WRITE, NOTIFY
    pCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ |
        BLECharacteristic::PROPERTY_WRITE |
        BLECharacteristic::PROPERTY_NOTIFY
    );

    pCharacteristic->setValue("you found me!!");
    pCharacteristic->addDescriptor(new BLE2902()); // required for NOTIFY

    pService->start();

    // Start advertising
    BLEAdvertising* adv = BLEDevice::getAdvertising();
    adv->addServiceUUID(SERVICE_UUID);
    adv->setScanResponse(true);
    BLEDevice::startAdvertising();

    oledShow("thexiao", "hiding in RF", "find me...", "");
}

void loop() {
    // Only update OLED when connection state changes
    if (deviceConnected != lastState) {
        lastState = deviceConnected;

        if (deviceConnected) {
            oledShow("YOU FOUND ME", "ok u win", "hello!", "");
        } else {
            oledShow("thexiao", "still hiding", "...", "...");
        }
    }
    delay(100);
}
Client OLED x XIAO ESP32C3 BLE code

Client seeks the server, connects when found, reads data and shows status on OLED, and keeps trying if disconnected

For more details on the code i.e. programming language, please refer to resources online.

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDRESS 0x3C
#define PIN_SDA 6
#define PIN_SCL 7

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

#define DEVICE_NAME_TARGET "thexiao"

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

BLEScan *pBLEScan = nullptr;
BLEClient *pClient = nullptr;

volatile bool wantConnect = false;
volatile bool connected = false;
BLEAddress *pTargetAddr = nullptr;

// Store last seen device info
String lastName = "";
int lastRSSI = 0;

// OLED helper
void oledShow(String a, String b, String c, String d) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(a);
display.println(b);
display.println(c);
display.println(d);
display.display();
}

// Client callbacks
class ClientCallbacks : public BLEClientCallbacks {
void onConnect(BLEClient *c) {
    connected = true;
}

void onDisconnect(BLEClient *c) {
    connected = false;
    wantConnect = false;

    if (pTargetAddr) {
    delete pTargetAddr;
    pTargetAddr = nullptr;
    }

    if (pBLEScan) {
    pBLEScan->clearResults();
    pBLEScan->start(0, false);
    }
}
};

// Scan callbacks
class ScanCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {

    // Save last seen device for display
    if (advertisedDevice.haveName()) {
    lastName = advertisedDevice.getName();
    } else {
    lastName = "(no name)";
    }
    lastRSSI = advertisedDevice.getRSSI();

    // Show scanning activity on OLED
    if (!connected && !wantConnect) {
    oledShow("Scanning...",
            lastName,
            "RSSI: " + String(lastRSSI),
            "");
    }

    // Check for target
    if (connected || wantConnect) return;
    if (!advertisedDevice.haveName()) return;

    if (advertisedDevice.getName() != DEVICE_NAME_TARGET) return;

    // FOUND TARGET
    if (pBLEScan) pBLEScan->stop();

    if (pTargetAddr) {
    delete pTargetAddr;
    pTargetAddr = nullptr;
    }

    pTargetAddr = new BLEAddress(advertisedDevice.getAddress());
    wantConnect = true;
}
};

void setup() {
Serial.begin(115200);
Wire.begin(PIN_SDA, PIN_SCL);

if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
    Serial.println(F("SSD1306 begin failed"));
    while (true) delay(1000);
}

oledShow("seeker mode", "scanning...", "", "");

BLEDevice::init("");

pClient = BLEDevice::createClient();
pClient->setClientCallbacks(new ClientCallbacks());

pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new ScanCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(500);
pBLEScan->setWindow(49);

pBLEScan->start(0, false);
}

void loop() {
static unsigned long lastScanRestart = 0;

if (wantConnect && !connected && pTargetAddr != nullptr) {
    oledShow("WAIT WAIT", "target locked", "connecting...", "");

    if (pClient->connect(*pTargetAddr)) {
    wantConnect = false;

    BLERemoteService *svc = pClient->getService(SERVICE_UUID);
    if (svc != nullptr) {
        BLERemoteCharacteristic *ch = svc->getCharacteristic(CHARACTERISTIC_UUID);
        if (ch != nullptr && ch->canRead()) {
        Serial.println(ch->readValue());
        }
    }

    oledShow("THERE U ARE", "got u thexiao", "connected!", "!!!");
    } else {
    wantConnect = false;
    delete pTargetAddr;
    pTargetAddr = nullptr;

    if (pBLEScan) {
        pBLEScan->clearResults();
        lastScanRestart = millis();
    }

    oledShow("scan retry...", "", "", "");
    }
}

else if (connected) {
    oledShow("still linked", "to thexiao", "", "");
}

if (!connected && pBLEScan && (pTargetAddr == nullptr) && (millis() - lastScanRestart > 50)) {
    pBLEScan->start(0, false);  // restart scanning immediately
    lastScanRestart = millis();
}

delay(50);  // smaller delay for faster responsiveness
}

The XIAO ESP32C3 has built-in BLE and Wi-Fi capabilities ; however without the antennas, the microcontrollers only create small electrical signal. The antennas in fact converts it into radio waves and direct it to specific frequencies. Newer XIAO ESP32s (e.g. ESP32C6) include built-in internal antenna that is perhaps strong enough and comparable to the C3 with antennas.

Connecting the IPEX Antenna to XIAO ESP32C3 takes patience. Align and apply gentle pressure straight down until it clicks

A comparison on the range could be seen below.

10 cm

5 m

>10 m

>5 m indoor

Another stress test perhaps could be done to check the maximum range of the two antenna in the future.

Overall, it is clear that this experiment is more complex compared to previous work (i.e. one direction communication, wired). This is due not only to the increased uncertainty introduced by wireless communication, but also to the need to manage communication between two microcontrollers, including defining the response of the devices to the other.

I2C communication (XIAO ESP32C3 x OLED)

The setup and a segment of the overall signal captured from the XIAO ESP32C3 acting as a BLE client using the logic analyzer is shown below :

Note becaues it is keep on searching signal so that it give signal frequently

Converting Binary to Hexadecimal

Hexadecimal Basics:
- Hexadecimal is a base-16 number system.
- It uses digits 0–9 and letters A–F, where A = 10, B = 11, ..., F = 15.
- One hexadecimal digit represents exactly *4 binary bits

Steps to convert binary to hexadecimal:

  1. Group the binary digits into sets of four, starting from the right.
  2. Convert each 4-bit group to its hexadecimal equivalent.

Example:

Binary: 01001001
Step 1: Split into 4-bit groups → 0100 1001
Step 2: Convert each group → 0100 = 4, 1001 = 9
Hexadecimal: 0x49
Source: ChatGPT by OpenAI, April 2026

Two packets were identified and the interpretation of it are as follows :

  • 1st packet :

    • 0x3C WR = This is the 7-bit address of the OLED device (0x3C) combined with a write (WR) operation.
    • 0x40 = The following bytes are interpreted as data bytes for the OLED.
    • 0x00 (binary: 00000000) = This byte represents pixel data with all pixels turned off.
    • 0x26 (binary: 00100110) = This byte turns on the 3rd, 4th, and 6th pixels.
    • 0x49 (binary: 01001001) = This byte turns on two pixels separated by gaps.
    • 0x49 (binary: 01001001) = The same pattern repeats for the next pixel row.
  • 2nd packet :

    • 0X23 WR :Appears to be another I2C device. This is typically the address of a BH1750 light sensor; however, since this sensor is not present in the experimental setup, the signal is likely caused by noise.
    • 0x80
    • 0x0F
    • 0xC1
    • 0x43
    • 0x45

Despite the noticeable noise on the second I2C operation (i.e. the second packet), it appears that the communication is still functioning correctly, which is evident from the first packet with the expected data bytes and the intended device, as well as the acknowledgement (ACK) bit.

Wired/wireless integration (to designed embedded microcontroller system)

The planned final project is a solar tracker system that incorporates a power management feature capable of cutting off the power supply if timely payments are not made (see final project for context).

The experiment for this assignment focuses on a simple proof-of-concept prototype with the following setup :

  • LED : The load for clear visual indication on whether the system works
  • GROVE - MOSFET : The switch. Controlling the power flow.
  • Raspberry pi 4 : The controller. Gives signal to MOSFET to turn on or off. In the coming weeks will explore token generation and payment verification. Technical details on this Single-Board Computer (SBC) are available under Details : SBC tab.
  • RFID module: Included to experiment with the SPI protocol, which has not been explored in previous assignments. For now acts as a temporary "payment verification"

Python vs MicroPython on Raspberry Pi (SBC)

The Raspberry Pi is a Single-Board Computer (SBC), which means it can run a full operating system (typically Linux). Because of this, it uses standard Python (CPython) rather than MicroPython.

The python code of the setup could be at the admonition below.

RFID x Raspberry Pi 4 x LED code
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
import time

# --- GPIO setup ---
GPIO.setwarnings(False)          # Disable pin warnings
GPIO.setmode(GPIO.BCM)

MOSFET_PIN = 17                  # GPIO controlling MOSFET/LED
GPIO.setup(MOSFET_PIN, GPIO.OUT)
GPIO.output(MOSFET_PIN, GPIO.HIGH)  # Start with device OFF

# --- RFID setup ---
reader = SimpleMFRC522()
reader.RESET_PIN = 27

print("Hold any RFID tag near the reader...")

try:
    while True:
        try:
            # Wait for a tag
            tag_id, text = reader.read()
            print(f"Tag detected! UID: {tag_id}")

            # Turn off device

The code essentially tells the LED to turn off whenever an RFID tag is present. It could be modified to accept specific tags.

The SPI signals were evaluated using the logic analyzer. It's observed that :

  • CS# (D3) is active low and it goes low for the two captured transfers. Note : This is important because SPI allows multiple devices to share the same MOSI, MISO and CLK lines.
  • CLK (D2) pulses only while CS# (D3) is low. That is the correct SPI transfer timing.
  • MOSI (D1) is sending data while CLK pulses.
  • MISO (D0) is returning bytes during those same transfers.

Indicating that the wired communication works properly. However, no further details of the SPI communication is evaluated since the SPI protocol is not standardized across all modules and requires datasheet-specific interpretation.

Further details of the SPI communication are not evaluated, since the SPI protocol is not standardized across all modules and requires datasheet-specific interpretation in comparison to for example I2C. An illustration of it could be seen below.

Feature MFRC522 RFID Module SD Card Module (SPI mode)
Command size 1 byte 6 bytes
Addressing 6-bit register 32-bit argument
Dummy byte 1 byte required for reads Sometimes needed
Example command Read register 0x09 → send 0x92 Read block → send 0x51, 0x00, 0x00, 0x00, 0x00, 0xFF

Source: ChatGPT by OpenAI, April 2026

-