Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions docs/wiredmbus-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# TSS721ADR Wired M-Bus Module Documentation (S0 Baseboard)

## Overview

The **TSS721ADR** is a **Wired M-Bus (Meter-Bus) transceiver** designed for reliable communication with **wired M-Bus compliant utility meters**, such as **water, heat, gas, and electricity meters**.

On the **S0 Baseboard**, the TSS721ADR enables **direct physical connection** to wired M-Bus meters and acts as the **physical layer interface** between the meters and the S0 board.

This module allows the S0 board to collect meter data from the Baseboard and forward it to SuperMQ via protocols like MQTT, CoAP, HTTP and the rest.

---

## What is Wired M-Bus?

**Wired M-Bus (EN 13757-2 / EN 13757-3)** is a European standard for wired meter reading. It supports:

- Multi-drop bus topology
- Long cable lengths
- Low power consumption at the meter
- Reliable communication in industrial environments

Wired M-Bus is commonly used in:

- Apartment buildings
- Industrial facilities
- District heating systems
- Utility metering cabinets

---

## Role of the TSS721ADR on the S0 Board

The TSS721ADR performs the following functions:

- Provides **voltage level shifting** and **signal conditioning** for the M-Bus line
- Handles **current modulation and detection**
- Protects the MCU from direct exposure to the M-Bus line
- Enables **half-duplex communication** over the M-Bus

S0 communicates with the TSS721ADR using the **UART interface**, while the TSS721ADR interfaces with the **M-Bus lines (MBUS+ / MBUS−)**.

---

## Key Features of the TSS721ADR

- Fully compliant with **Wired M-Bus standards**
- Supports **master mode operation**
- Integrated current limiting and line protection
- Operates from a single supply voltage
- UART-based interface to the host MCU
- Industrial-grade reliability

---

## Hardware Connections (Typical)

### MCU ↔ TSS721ADR

| Signal | Description |
| ------ | ---------------- |
| TX | UART TX to MCU |
| RX | UART RX from MCU |
| VB | Power supply |
| GND | Ground |

### TSS721ADR ↔ Meter Bus

| Signal | Description |
| ------ | ------------ |
| MBUS+ | M-Bus line |
| MBUS− | M-Bus return |

---

## How to Test the TSS721ADR Module

### 1. Prerequisites

Before testing, ensure you have:

- S0 Baseboard powered
- S0, or a microcontroller of your choice powered and programmed
- A **wired M-Bus compatible meter** or a (12-42)V DC power supply connected at the MBUS lines with the proper M-Bus wiring (polarity observed)
- Serial logging enabled on the S0 or Microcontroller of your choice
- Correct UART configuration (typically 2400 or 9600 baud)

---

### 2. Electrical Verification

1. Measure voltage on the **M-Bus lines**:
- Typical M-Bus idle voltage: **(12–42) V**
2. Verify the TSS721ADR is powered correctly

---

### 3. UART Communication Test

Configure the MCU UART connected to the TSS721ADR:

- Baud rate: **2400 / 9600**
- Data bits: **8**
- Parity: **Even**
- Stop bits: **1**

Send a simple test frame from the MCU and observe UART activity.

Example code for this test can be found in the [Wired MBUS test code](https://github.com/absmach/s0-docs/blob/mbus-work/test-codes)
96 changes: 96 additions & 0 deletions docs/wirelessmbus-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# RC-S2LP Wireless M-Bus Transceiver

## Overview, Hardware Connection, and Test Procedure

## Introduction

The **RC-S2LP** is a sub-GHz RF transceiver module based on the **STMicroelectronics S2-LP** radio IC. It is commonly used in **Wireless M-Bus (wM-Bus)**, **smart metering**, and **low-power IoT gateway** applications operating in the **868 MHz ISM band**.

In the **S0 board**, the RC-S2LP is responsible for receiving and transmitting Wireless M-Bus frames from devices such as heat meters, water meters, and gas meters.

---

## What the RC-S2LP Module Is Used For

The RC-S2LP enables:

- Wireless M-Bus communication (T1, T2, C1, C2 modes)
- Sub-GHz long-range communication
- Low-power RF reception from battery-powered meters
- Gateway-to-meter RF communication
- Custom proprietary RF protocols

Typical applications include:

- Smart utility meters
- IoT gateways
- Industrial telemetry
- Building automation systems

---

## Key Specifications

| Feature | Description |
| ----------------- | --------------------------------- |
| RF IC | STMicroelectronics S2-LP |
| Frequency Band | 868 MHz ISM band |
| Modulation | 2-FSK, GFSK, OOK, MSK |
| Data Rate | Up to 500 kbps |
| Output Power | Up to +14 dBm |
| Sensitivity | Down to −130 dBm (mode-dependent) |
| Interface | SPI |
| Operating Voltage | 1.8 V – 3.6 V |
| Low-Power Modes | Sleep, Standby |

---

## Hardware Connection

The RC-S2LP communicates with the host MCU using **SPI** and several control signals.

### Required Signals

| Signal | Description |
| ------ | --------------- |
| MOSI | SPI Master Out |
| MISO | SPI Master In |
| SCK | SPI Clock |
| CS | SPI Chip Select |
| VCC | 3.3 V supply |
| GND | Ground |
| RF | 868 MHz antenna |

---

### Example Connection (ESP32)

| RC-S2LP Pin | MCU Pin |
| ----------- | -------- |
| MOSI | SPI MOSI |
| MISO | SPI MISO |
| SCK | SPI SCK |
| CS | GPIO |
| VCC | 3.3V |
| GND | GND |

⚠️ Ensure a **proper 868 MHz antenna** is connected before transmitting.

---

## Software Test Procedure

### Test Objective

The test verifies that:

- The RC-S2LP is powered correctly
- SPI communication is functional
- Registers can be read and written
- RF transmission and reception work

---

## SPI Communication Test

Example code for this test can be found in the [Wireless MBUS test code](https://github.com/absmach/s0-docs/blob/mbus-work/test-codes)
4 changes: 3 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ nav:
- COAP-DTLS: coaps.md
- MQTTS: mqtts.md
- HTTPS: https.md

- Module Tests:
- Wired MBUS: wiredmbus-testing.md
- Wireless MBUS: wirelessmbus-testing.md
46 changes: 46 additions & 0 deletions test-codes/MBUS_test_code.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// TSS721A + ESP32 UART Test

// UART pins
#define MBUS_RX 18 // ESP32 receives from TSS721A TXD
#define MBUS_TX 19 // ESP32 transmits to TSS721A RXD


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

Serial.println("TSS721A ESP32 M-Bus Test Starting...");

Serial1.begin(2400, SERIAL_8E1, MBUS_RX, MBUS_TX);
// M-Bus default: 2400 baud, Even parity, 1 stop

Serial.println("Ready. Listening for M-Bus data...");

}

void loop() {
// Read data from M-Bus
while (Serial1.available()) {
byte b = Serial1.read();
Serial.print("RX: 0x");
Serial.println(b, HEX);
}

// Send test every 5 sec
static uint32_t last = 0;
if (millis() - last > 20000) {
last = millis();

while (Serial1.available()) {
byte b = Serial1.read();
Serial.print("RX: 0x");
Serial.println(b, HEX);
}

byte pingFrame[] = { 0x10, 0x40, 0x40, 0x16 }; // Standard M-Bus SND-NKE
Serial1.write(pingFrame, sizeof(pingFrame));

Serial.println("TX: Sent SND-NKE frame (reset command)");
}

}
126 changes: 126 additions & 0 deletions test-codes/WMBUS_test.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include <SPI.h>

// SPI Pins for ESP32C6
#define PIN_SPI_MOSI 23
#define PIN_SPI_MISO 19
#define PIN_SPI_SCK 18
#define PIN_SPI_CS 5

// Optional Interrupt Pin
#define PIN_GDO0 4

// S2LP Command Strobes / Registers
#define CMD_SRES 0xFE // RESET
#define CMD_SNOP 0x00 // NO OP

// Define buffer size for TX / RX
#define BUFFER_SIZE 64

SPIClass *vspi = NULL;

void rcS2lpWriteReg(uint8_t reg, uint8_t value) {
digitalWrite(PIN_SPI_CS, LOW);
vspi->transfer(reg | 0x00); // WRITE
vspi->transfer(value);
digitalWrite(PIN_SPI_CS, HIGH);
}

uint8_t rcS2lpReadReg(uint8_t reg) {
digitalWrite(PIN_SPI_CS, LOW);
vspi->transfer(reg | 0x80); // READ
uint8_t value = vspi->transfer(0);
digitalWrite(PIN_SPI_CS, HIGH);
return value;
}

void rcS2lpStrobe(uint8_t cmd) {
digitalWrite(PIN_SPI_CS, LOW);
vspi->transfer(cmd);
digitalWrite(PIN_SPI_CS, HIGH);
}

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

Serial.println("RC-S2LP Wireless M-Bus SPI Test");

pinMode(PIN_SPI_CS, OUTPUT);
digitalWrite(PIN_SPI_CS, HIGH);

pinMode(PIN_GDO0, INPUT);

// Initialize VSPI
vspi = new SPIClass(VSPI);
vspi->begin(PIN_SPI_SCK, PIN_SPI_MISO, PIN_SPI_MOSI);

// Hardware reset RC-S2LP if needed (wire RESET pin)
// pinMode(PIN_RESET, OUTPUT);
// digitalWrite(PIN_RESET, LOW);
// delay(100);
// digitalWrite(PIN_RESET, HIGH);
// delay(100);

// Reset chip
Serial.println("Sending chip reset...");
rcS2lpStrobe(CMD_SRES);
delay(100);

// Read version / part number (example register)
uint8_t partnum = rcS2lpReadReg(0x01); // PARTNUM register addr
Serial.print("Part Number: 0x"); Serial.println(partnum, HEX);

// Set some basic registers (Example — see datasheet)
Serial.println("Configuring basic registers...");
rcS2lpWriteReg(0x02, 0x01); // Example: Write some register

Serial.println("Ready!");
}

void loop() {
static uint32_t lastSend = 0;

// Example: Transmit a test packet every 5 seconds
if (millis() - lastSend > 5000) {
lastSend = millis();

Serial.println("Sending test packet...");

// Build test packet
uint8_t packet[] = "HELLO FROM ESP32-C6";
uint8_t packetSize = sizeof(packet);

// Send strobe for TX FIFO loading (depends on S2LP FIFO interface)
digitalWrite(PIN_SPI_CS, LOW);
vspi->transfer(0x66); // WRITE FIFO command (example)
for (uint8_t i = 0; i < packetSize; i++) {
vspi->transfer(packet[i]);
}
digitalWrite(PIN_SPI_CS, HIGH);

// Strobe TX (example)
rcS2lpStrobe(0x35); // STX

Serial.println("Packet sent!");
}

// Example: Basic receive check
if (digitalRead(PIN_GDO0) == HIGH) {
Serial.println("Packet received!");
uint8_t rxBuf[BUFFER_SIZE];

// Read RX FIFO (example)
digitalWrite(PIN_SPI_CS, LOW);
vspi->transfer(0x7F); // READ FIFO command
for (uint8_t i = 0; i < BUFFER_SIZE; i++) {
rxBuf[i] = vspi->transfer(0);
}
digitalWrite(PIN_SPI_CS, HIGH);

Serial.print("Data: ");
for (uint8_t i = 0; i < BUFFER_SIZE; i++) {
Serial.write(rxBuf[i]);
}
Serial.println();
}
}