🟦 SLIDE 3 — Hardware Components (mi parte)
I’ll now focus on a few key components that are especially important for the behaviour of our
car.
First, the ultrasonic sensor is our main distance sensor. It sends out an ultrasonic pulse and
then measures the time it takes for the echo to come back. From that time, the
microcontroller computes the distance to the obstacle in front of the car. We use this
information to decide when to slow down, stop, or start the obstacle avoidance maneuver.
Second, the motor driver, the L298N, is the interface between the STM32 and the DC
motors. The STM32 only provides logic-level signals, while the driver handles the higher
current needed by the motors. With simple HIGH/LOW signals for direction and PWM for
speed, we can control both wheels independently.
We also use a potentiometer connected to the ADC of the STM32. This gives us an analog
voltage that we interpret as a sort of sensitivity or ‘permission’ for the autonomous mode. If
the voltage is below a threshold, the car simply doesn’t move in automatic mode.
Finally, the Bluetooth module lets us bypass all the automatic logic and directly control the
car manually. In manual mode, each character received over Bluetooth is translated into a
movement command, like forward, backward, left, right, or stop.
🟦 SLIDE 4 — Pin Assignment (Ultrasonic, Buzzer, Potentiometer, Motors)
On this slide we focus on how the STM32 pins are assigned to the main hardware blocks of
the car.
First, for the ultrasonic sensor, we use two pins:
- The Echo signal is on PA0 and is connected to TIM2 Channel 1 in Input Capture
mode. This allows the microcontroller to precisely measure the width of the echo
pulse in hardware and then convert that time into a distance.
- The Trigger signal is on PA1 and is configured as a simple GPIO output. We only
need to generate a short HIGH pulse of about 10 microseconds, so a basic digital
output combined with a timer is enough.
For sound feedback, the buzzer is connected to PB6 and driven by TIM4 Channel 1 in
Output Compare Toggle mode. This means the timer automatically toggles the pin at a fixed
frequency, generating a clean square wave without any software delays.
The potentiometer is connected to PA5, which is an analog input of ADC1. The ADC
converts the voltage into a digital value, and we use that value as a kind of sensitivity or
permission for the autonomous mode. If the voltage is below the threshold, the car will not
move in auto mode.
Finally, we have the motor driver pins. For Motor A, IN1 and IN2 are on PB8 and PB9, and
the enable pin uses PWM from TIM3 Channel 2. For Motor B, IN3 is on PA4 and IN4 is on
PB0, with PWM on TIM3 Channel 1. The direction pins only need simple HIGH or LOW
1
signals, while the enable pins require PWM to control the speed of each wheel
independently.
🟦 SLIDE 9 — Timers as Schedulers
Here we summarize how we use timers as schedulers, not just for PWM or basic timing.
TIM5 acts as the main system heartbeat. Every 300 milliseconds it fires an interrupt that
starts the entire sensing cycle: it triggers an ADC conversion to read the potentiometer
and, if the voltage is above the threshold, it also starts the ultrasonic measurement by raising
the trigger pin.
TIM6 is configured as a one-shot timer to generate the precise 10-microsecond trigger
pulse for the HC-SR04 sensor. TIM5 sets the trigger pin HIGH and starts TIM6. When
TIM6 expires, it automatically brings the trigger pin LOW and stops itself. This guarantees a
very accurate pulse without blocking the CPU.
Finally, TIM9 is used as the obstacle avoidance sequencer. It runs every 10
milliseconds and implements a small state machine. It controls how long the car stays
stopped, how long it reverses, and how long it turns, so the maneuver is fully timed and
deterministic.
🟦 SLIDE 11 — Interrupt-Driven Architecture
An important design decision in our project is that the while(1) loop in main() is intentionally
empty. The entire system is interrupt-driven.
The external interrupt from the mode button calls HAL_GPIO_EXTI_Callback(). This is the
master controller that cycles through OFF, AUTO and MANUAL, and enables or disables
peripherals accordingly.
The timer interrupt callback, HAL_TIM_PeriodElapsedCallback(), routes events based on
which timer fired: TIM5 starts the ADC and ultrasonic trigger, TIM6 ends the trigger pulse,
and TIM9 advances the obstacle avoidance state machine.
The input capture callback, HAL_TIM_IC_CaptureCallback(), is triggered by TIM2 when the
ultrasonic echo pulse edges are detected. It calculates the distance and then calls the
autonomous control logic.
We also have HAL_ADC_ConvCpltCallback() to update the potentiometer voltage once the
conversion finishes, and HAL_UART_RxCpltCallback() for Bluetooth reception. In
summary, the car reacts to events instead of constantly polling, which makes the system
both efficient and highly responsive.
🟦 SLIDE 15 — Automatic Mode Operation Cycle
This slide shows the complete operation cycle in automatic mode.
2
● In Step 1, the TIM5 interrupt runs every 300 milliseconds. It starts an ADC
conversion to read the potentiometer and, if the voltage is above the 2-volt
threshold, it sets the trigger pin HIGH and starts TIM6 to generate the ultrasonic
pulse.
● In Step 2, the TIM6 interrupt fires after about 10 microseconds. Its only job is to bring
the trigger pin LOW again, so that the HC-SR04 emits a clean, well-defined pulse.
● In Step 3, the input capture callback of TIM2 is triggered by the ultrasonic Echo. It
records the rising and falling edges of the echo pulse, computes the time difference,
and converts it into a distance in centimeters.
● Finally, in Step 4, the Control_Auto() function is called. This function uses both the
measured distance and the last potentiometer voltage to decide whether the car
should move forward, slow down, stop, or start the obstacle avoidance maneuver.
🟦 SLIDE 16 — Obstacle Avoidance Protocol
When the distance measured by the ultrasonic sensor drops below 15 centimeters, the
car enters the obstacle avoidance protocol.
This protocol is controlled by TIM9 and the variable obstacle_state. It is divided into three
main states.
● In State 1, Pause, the car stops completely for 300 milliseconds. This ensures that
we don’t collide while deciding the next move.
● In State 2, Reverse, the car moves backwards for 500 milliseconds. This increases
the distance from the obstacle and creates space to turn safely.
● In State 3, Turn, the car turns to one side, also for 500 milliseconds. The direction
can be chosen randomly so that the car doesn’t always turn the same way in
repeated scenarios.
After finishing State 3, TIM9 stops, the state machine resets, and the system goes back
to the normal automatic cycle, where distance is measured again and the car continues
moving if it is safe.
🟦 SLIDE 19–20 — Block Diagram & Wiring / System Overview
This last diagram summarizes the overall architecture of our system.
In the block diagram, you can see how each component is connected to a specific
peripheral of the STM32: the ultrasonic sensor to TIM2 and the GPIO trigger, the motors to
TIM3 and the driver, the buzzer to TIM4, the potentiometer to the ADC, and the Bluetooth
module to USART3. All of these are orchestrated by the timers that act as schedulers in
automatic mode.
The wiring view shows the physical implementation on the car: the connections between the
STM32 board, the motor driver, the power supply, the HC-SR04 sensor on the front, the
LEDs, and the Bluetooth module.