MicroPython for Microcontrollers Module 4
Buses and device drivers: I2C, SPI and UART interview questions
Interview questions on “Buses and device drivers: I2C, SPI and UART”: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
How do I2C, SPI and UART differ?
-
Fresher
Why does an I2C bus need pull-up resistors?
-
Fresher
Why should a driver take its bus as an argument instead of creating it?
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Mid to senior
A sensor answers every read on the bench, but mounted at the end of a 1 m cable it raises OSError 5 every few minutes on a Pico's hardware I2C at 400 kHz. How do you find the cause, and what do you change in the hardware and in the code?
- What it tests
- Reading EIO as a missing acknowledgement, the effect of pull-ups, cable capacitance and bus speed on I2C edges, and code that retries a transfer without hiding a real fault.
- First step
- EIO means a byte was not acknowledged, so the sensor did not see its address or a byte cleanly. A longer cable adds capacitance, and with weak pull-ups the edges rise too slowly at 400 kHz. Look at SCL and SDA with a scope or a logic analyser, then try 100 kHz and stronger pull-ups before touching the code.
- Follow-ups
-
- Which pull-up value would you try, and why not the smallest one?
- How many times should the code retry, and what does it do after the last try?
- When is SoftI2C the better choice here?
From the lesson I2C, SPI and UART from MicroPython
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A module sends text lines ending in \r\n at 9,600 baud. The parser does line = uart.read() and sometimes sees half lines, and over days the board starts raising MemoryError. What is wrong, and how do you build the reader?
- What it tests
- That a UART read returns what has arrived rather than a message, timeouts that return None, and readers built on preallocated buffers and readinto().
- First step
- Explain what read() returns: the bytes that arrived before the timeout, which can end anywhere in a line. Each call also makes a new bytes object, and string handling of the parts makes more. Keep the unfinished line in a bytearray made once, read with readinto() into a second fixed buffer, and split on b"\n".
- Follow-ups
-
- What should happen to a line longer than the buffer?
- How do you size the UART's receive buffer for a loop that runs every 100 ms?
- When would you use UART.IRQ_RXIDLE instead of polling?
From the lesson I2C, SPI and UART from MicroPython
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A colleague's sensor driver creates I2C(0) in __init__, keeps register numbers as plain globals, returns floats and calls readfrom_mem() on every reading. It must now run on an ESP32 board, under SoftI2C and in CI. Review it: what do you change, in what order, and why?
- What it tests
- Turning a board-locked driver into a portable one: injection, const() names, preallocated reads, integer conversions, an ID check and host tests, ordered by risk and payoff.
- First step
- Start with the change that makes all the others possible: take the bus as the first argument, so the ESP32 board, SoftI2C and a fake in CI can all be passed in. Then write a fake bus and a few tests that pin today's behaviour before touching the rest, so each later change is checked.
- Follow-ups
-
- What do the tests pin down before you refactor anything?
- How do you keep the old constructor working for existing users?
- Which of the changes saves the most RAM, and how would you measure it?
From the lesson Write a reusable device driver class
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A driver starts each measurement by writing 0x01 to the sensor's control register. After someone added a call that sets averaging to 16 samples in bits 2 and 1 of the same register, the readings are as noisy as before. Explain what happens, fix it, and say how a test on a computer would have caught it.
- What it tests
- Recognising a lost read-modify-write, the expressions that set one bit or one field, and a fake bus that keeps a register map so tests can check the bits after an operation.
- First step
- Write down the register after each step: set_averaging(16) leaves 0b100, then writing 0x01 replaces the whole byte with 0b001, which clears the averaging code to 0, one sample. The measurement must read the register and write back ctrl | 0x01 instead.
- Follow-ups
-
- How do you change the averaging field itself without touching bit 0?
- Is the fix safe if an interrupt handler also writes this register?
- What would the test assert, exactly?
From the lesson Write a reusable device driver class
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
All MicroPython for Microcontrollers interview questions · The MicroPython for Microcontrollers track