Parasitic Capacitance: A Real-World Case in Embedded Systems

Parasitic Capacitance / Stray Capacitance

Yu-Cheng (Morton) Kuo
Nerd For Tech
4 min readDec 28, 2023

--

As an Embedded Systems Engineer, I encountered this case a couple of weeks ago while testing and debugging the lightweight Modbus master device code in Python that I had crafted for the Modbus protocol.

Outline
(1) Phenomenon
(2) Debugging
(3) Conclusion
(4) References

(1) Phenomenon

Figures: The testing result

Two weeks ago, when I was testing the Modbus master device code I had developed in Python on my laptop, which was communicating with the slave device (a board we made with STM32F407 MCU) in the magnetic bearing compressor central air conditioning systems, I observed an unseen phenomenon:

The messages read would disappear approximately every 20 to 50 times of read operations (in terms of the median) regardless of the timeout settings (timeout for the read and write operations in the pyserial module) (showing similar boxplots from a timeout of 0.02s to a timeout of 1.00s).

  • [Remark] The same Modbus master device code worked fine when communicating with the slave device (STM32F303 MCU, Nucleo series, a teaching board)

The testing Python code for the resulting figures above:

if __name__ == "__main__":
controller = Controller()

def test_read_single_register(controller, iterations=3, max_attempts=200):

crash_counts = []
for _ in range(iterations):
# Open the port
if controller.client.is_open == 0:
controller.client.open()

controller.crash_count = 0
successful_reads = 0 # Track successful reads before a crash
for attempt in range(1, max_attempts + 1):
try:
controller.read_single_register(start_address=32, slave_ID=MODBUS_SLAVE_ID)
successful_reads += 1 # Increment on successful read
except Exception:
crash_counts.append(successful_reads) # Record successful reads before crash
break
else:
crash_counts.append(successful_reads) # Record successful reads if no crash

# Close the port
controller.close()
time.sleep(0.2)

return crash_counts

crash_counts = test_read_single_register(controller, iterations=50)
print(crash_counts)

print()
if controller.client.is_open:
controller.close()

(2) Debugging

Let’s start with the clues at this point.

  • Clue 01: The transmission worked perfectly on the teaching board STM32F303 without any failures during the same testing process.
  • Clue 02: The phenomenon occurs irrespective of the timeout settings’ length.

Moving on, my mentor and I decided to dive into the hardware arena using an oscilloscope with 2 test probes and the live expression section in the STM32 CubeIDE. Under the hood of Modbus, which operates at the application layer (layer 7) of the OSI model, we adopt UART, which lies at the physical layer (layer 1) and the data link layer (layer 2). Hence, we wrote a program on the PC that focused on an 8-bit (the basic transmission unit of UART) buffer reading data from a fixed chunk of memory (with fixed values) on the slave device.

We had the master device read an 8-bit message and then set the 8-bit buffer to 0s after fetching the data from the buffer. When the data received was not consistent with the expected data, we stopped the program and checked what had happened to the 8-bit buffer. Here are some typical results we got:

[1] Complete data: 01 03 00 20 00 01 85 C0

[2] Incomplete data: 01 03 00

[3] Two 8-bit data at one time: 01 03 00 20 00 01 85 C0 01 03 00 20 01 85 C0

  • Clue 03: The missing data is continuous. However, if the missing data is caused by high electric currents from other machines nearby, the missing data is usually discrete.

(3) Conclusion

Let’s recap the clues we have at hand:

  • Clue 01: The transmission worked perfectly on the teaching board STM32F303 without any failures during the same testing process.
  • Clue 02: The phenomenon occurs irrespective of the timeout settings’ length.
  • Clue 03: The missing data is continuous. However, if the missing data is caused by high electric currents from other machines nearby, the missing data is usually discrete.
Figures: The signal of a square wave and the wave affected by parasitic capacitance [2][3][4]

In conclusion, the problem likely stemmed from parasitic capacitance on the board we made for the STM32F407 MCU; we must contact the electrical engineering colleagues in charge of PCB layout to determine whether it’s due to parasitic capacitance and to lay out a modified version of the board.

Also, parasitic capacitance (or stray capacitance) is also common in the cell cable [3]. Here’s a solution to the parasitic capacitance in the cell cable.

To minimize stray capacitance between an electrochemical cell and the Faraday cage, move the cell away from the walls toward the center of the shield. Prop up the cell off the floor of the shield using a non-conductive object (e.g., block of wood, textbook). [3]

--

--

Yu-Cheng (Morton) Kuo
Nerd For Tech

CS/DS blog with C/C++/Embedded Systems/Python. Embedded Software Engineer. Email: yc.kuo.28@gmail.com