Skip to content
Taimoor Arshad
Back to portfolio

RF Transceiver System

2025Embedded

Two custom ATmega328 boards, nRF24L01 wireless, four environmental sensors, OLED readout, LiPo, USB-C. Full board design loop in KiCad.

بسم الله الرحمن الرحيم

I wanted a hardware project that would exercise the full board-design loop, from schematic through PCB layout through soldering and bring-up. The prompt I gave myself was: two custom boards that talk to each other over RF, with real sensors on the transmitter and a live display on the receiver. The result was a matching pair of transceiver boards, both built around ATmega328 MCUs and nRF24L01 modules, with four sensors on the transmitter and an OLED on the receiver.

Why build it when off-the-shelf modules exist

The obvious question. You can buy an nRF24L01 breakout for a few dollars, plug it into a Nano, and be done in an afternoon. The point wasn't the functionality. The point was the design practice.

I wanted to feel comfortable with:

  • Schematic capture in KiCad, including hierarchical sheets for the sensor block and the power block.

  • PCB layout with proper decoupling, trace routing, and ground plane discipline.

  • USB-C power delivery, including the CC resistors and ESD protection.

  • A LiPo charging circuit with automatic power-path management, so the boards can run off USB or battery seamlessly.

  • Ordering from JLCPCB, soldering SMD parts by hand and hot air, and getting boards up first try.

Doing that on a project I picked myself, at a scope I could actually finish, taught me more than any tutorial would have.

Transmitter side

The transmitter reads four I2C sensors and packages the data into an RF packet a few times per second:

  • BMI323 — 6-axis IMU (accelerometer + gyroscope), for motion and orientation.

  • BME280 — temperature, humidity, and barometric pressure.

  • VEML7700 — ambient light sensor.

  • P3T1755DPZ — a precision temperature sensor, as a cross-check against the BME280's built-in temp reading.

The ATmega328 reads each sensor over I2C in turn, packs the readings into a fixed-size struct, and hands it to the nRF24L01 over SPI for transmission. The RF module handles retransmission and ACKs internally, so the MCU just has to fire and forget.

Receiver side

The receiver has its own nRF24L01, an ATmega328 running the same firmware base (with a different config flag), and an SSD1306 OLED for display. It receives the packet, decodes the struct, and pushes each reading to the OLED in a compact readout.

Both boards have the same power stack: USB-C input via a BQ24072RGT charger with auto power-path, a TLV1117 LDO regulating to 3.3 V, and a LiPo connector for battery operation. Status LEDs, an on/off switch, and a reset button round out the user interface.

What I got wrong

The one thing I'd fix in a rev B: the VEML7700 has a habit of stalling the transmitter when the light sensor pins full-scale in direct sunlight. The sensor sends data faster than my I2C loop was prepared to handle, and the flood clogs up the transmit cycle. I have a couple of fixes in mind. Either add an interrupt line and read the VEML7700 only when it signals a fresh reading, or throttle it in software by polling every N cycles. Both are easy. Neither made it into rev A.

The other lesson was around SMD hand-soldering. I did the first board with just a fine-tip iron and paste, and it took me most of an evening. The second board I did with a hot air gun and it took under an hour. Buy the tools before you fight the problem.

Next steps

I'd like to add a battery fuel gauge (the BQ27427YZFR is on the schematic but unpopulated in rev A) so the receiver's OLED can show the transmitter's remaining runtime. And I'd add a small optional 12 MHz crystal for cases where the internal RC clock's drift matters. Both were on the wishlist for rev A but got dropped to keep the BOM small.

Salaam.