Make values and control flow predictable
Practise integer values, conditions, loops and functions using small examples. Give each function one clear responsibility. Before running a program, predict its output for a normal case and a boundary case.
Data sizes matter when representing readings and counters. Choose a representation that matches the range you need and think about what happens at its limits.
Connect a value to an observation
A reading printed over serial provides a bridge between the program and the circuit. If it is wrong, decide whether the issue begins in the input signal, the peripheral configuration or the interpretation of the result.
Keep hardware access and the decision based on a reading easy to distinguish. A threshold function can be checked with known values even before the real sensor is connected.
Grow toward a small application
After simple inputs and outputs, timers and interrupts introduce timing and events. Communication adds another source of data. Integrate these progressively rather than copying an entire application you cannot explain. The goal is to know where each value comes from and why each output changes.