This shows you the differences between two versions of the page.
|
pm:prj2026:andrei.batasev:dorian.gilca [2026/05/09 21:05] dorian.gilca created |
pm:prj2026:andrei.batasev:dorian.gilca [2026/05/25 09:55] (current) dorian.gilca |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Adaptive Cruise Control Vehicle ====== | ====== Adaptive Cruise Control Vehicle ====== | ||
| + | |||
| ===== Introduction ===== | ===== Introduction ===== | ||
| - | What it does: | + | **What it does:** |
| - | This project consists of a small autonomous vehicle capable of maintaining a constant safe distance from a target vehicle or object in front of it. | + | This project consists of a small autonomous vehicle capable of maintaining a constant safe distance from a target object or vehicle in front of it. |
| - | Its purpose: | + | **Its purpose:** |
| - | The main goal is to implement a real-time closed-loop control system (Adaptive Cruise Control) on an 8-bit microcontroller. It demonstrates bare-metal embedded programming by utilizing hardware interrupts, hardware timers, and a PID (Proportional-Integral-Derivative) control algorithm. | + | The main goal is to implement a real-time closed-loop control system (Adaptive Cruise Control) on an 8-bit microcontroller. It demonstrates bare-metal embedded programming by utilizing hardware interrupts, hardware timers, and custom serial protocols, completely avoiding high-level abstractions like Arduino libraries. |
| - | The starting idea: | + | **The starting idea:** |
| The idea is inspired by modern Advanced Driver Assistance Systems (ADAS) used in the automotive industry to prevent rear-end collisions and improve driving comfort. | The idea is inspired by modern Advanced Driver Assistance Systems (ADAS) used in the automotive industry to prevent rear-end collisions and improve driving comfort. | ||
| - | Why it is useful: | + | **Why it is useful:** |
| It serves as a highly practical demonstration of low-level hardware control, bridging the gap between theoretical micro-processor architecture and real-world physical applications. | It serves as a highly practical demonstration of low-level hardware control, bridging the gap between theoretical micro-processor architecture and real-world physical applications. | ||
| ===== General Description ===== | ===== General Description ===== | ||
| - | The system uses an array of ultrasonic sensors mounted on the front to continuously measure the distance to the vehicle ahead. | + | The system uses an ultrasonic sensor mounted on the front to continuously measure the distance to the obstacle ahead. |
| - | Based on the calculated distance error (the difference between the desired safe distance and the actual measured distance), a PID control algorithm calculates the necessary adjustments. These adjustments are sent as PWM signals to a TB6612FNG motor driver, enabling the car to smoothly accelerate or brake. An optical encoder on the rear wheel provides closed-loop speed feedback to ensure accurate motor control. Optionally, the front steering is controlled by a servo motor to follow the target's trajectory. | + | Based on the calculated distance, a proportional control algorithm calculates the necessary speed adjustments to maintain a safe gap. The system smoothly interpolates the motor speed using hardware PWM based on the target's distance. If the target is too close (under 25 cm), the vehicle applies the brakes. If the target is within the tracking range (25 cm - 85 cm), it adjusts the speed dynamically to follow it. |
| - | Block Diagram: | + | **Block Diagram:** |
| - | //To be uploaded// | + | |
| + | |||
| + | {{:pm:prj2026:andrei.batasev:schema_bloc.jpg?300|}} | ||
| ===== Hardware Design ===== | ===== Hardware Design ===== | ||
| - | List of components: | + | **List of components:** |
| + | * Arduino UNO (ATmega328P Microcontroller) serving as the main processing unit. | ||
| + | * L293D Motor Drive Shield (featuring the 74HC595 shift register). | ||
| + | * 1x HC-SR04 Ultrasonic Sensor. | ||
| + | * 2x DC TT Motors (Rear-wheel or 4-wheel drive configuration). | ||
| + | * 2x 18650 Li-Ion Batteries (7.4V total) with holder. | ||
| + | * Robot car chassis with wheels. | ||
| + | * Dupont connecting wires. | ||
| - | Arduino Nano (ATmega328P Microcontroller) | + | **Electrical Schematic:** |
| - | 3x HC-SR04+ Ultrasonic Sensors | ||
| - | TB6612FNG Motor Driver | ||
| - | 1x DC Motor with Optical Encoder (Rear traction) | + | {{:pm:prj2026:andrei.batasev:schema_electrica.jpg?300|}} |
| - | 1x Servo Motor (Front steering) | ||
| - | LM2596 Step-Down Voltage Regulator | + | ===== Software Design ===== |
| - | 2x 18650 Li-Ion Batteries with holder | + | <code c> |
| + | #include <avr/io.h> | ||
| + | #include <avr/interrupt.h> | ||
| + | #include <util/delay.h> | ||
| + | #include <stdio.h> | ||
| - | Breadboard and Dupont connecting wires | + | #define PM_BAUD 9600 |
| - | Electrical Schematic: | + | #define TRIG_PIN PC0 |
| - | //To be uploaded after the circuit design is finalized.// | + | #define ECHO_PIN PC1 |
| - | ===== Software Design ===== | + | #define LATCH_PIN PB4 |
| + | #define CLK_PIN PD4 | ||
| + | #define EN_PIN PD7 | ||
| + | #define DATA_PIN PB0 | ||
| - | Development Environment: | + | #define M1_A 2 |
| + | #define M1_B 3 | ||
| + | #define M2_A 1 | ||
| + | #define M2_B 4 | ||
| - | PlatformIO / Arduino IDE (using pure C/C++ and register-level programming) | + | volatile uint16_t timer_val = 0; |
| + | volatile uint8_t echo_done = 0; | ||
| - | Libraries and 3rd-party sources: | + | static int _usart0_putchar(char c, FILE *stream) { |
| + | if (c == '\n') _usart0_putchar('\r', stream); | ||
| + | while (!(UCSR0A & (1<<UDRE0))); | ||
| + | UDR0 = c; | ||
| + | return 0; | ||
| + | } | ||
| - | Standard AVR libc (<avr/io.h>, <avr/interrupt.h>) | + | static FILE USART0_stdout = FDEV_SETUP_STREAM(_usart0_putchar, NULL, _FDEV_SETUP_WRITE); |
| - | No high-level Arduino libraries (like analogWrite or pulseIn) will be used for core functionalities, to adhere to the course requirements. | + | void usart_init() { |
| + | UBRR0H = (unsigned char)(103>>8); //br9600 | ||
| + | UBRR0L = (unsigned char)103; | ||
| + | UCSR0B = (1<<RXEN0) | (1<<TXEN0); //act transmisia | ||
| + | UCSR0C = (1<<USBS0) | (3<<UCSZ00); //8b | ||
| + | stdout = &USART0_stdout; | ||
| + | } | ||
| - | Algorithms and Structures: | + | void shift_out_data(uint8_t data) { |
| + | PORTB &= ~(1<<LATCH_PIN); | ||
| + | |||
| + | for(int i=0; i<8; i++) { //pt fiecare bit | ||
| + | PORTD &= ~(1<<CLK_PIN); | ||
| + | if(data & (1 << (7-i))) { | ||
| + | PORTB |= (1<<DATA_PIN); //punem val d | ||
| + | } else { | ||
| + | PORTB &= ~(1<<DATA_PIN); | ||
| + | } | ||
| + | PORTD |= (1<<CLK_PIN); //ridicam si coboram pin clock | ||
| + | } | ||
| + | |||
| + | PORTB |= (1<<LATCH_PIN); | ||
| + | } | ||
| - | PID Controller: A mathematical algorithm to smoothly calculate the motor speed based on the distance error. | + | void motors_init() { |
| + | DDRB |= (1<<LATCH_PIN) | (1<<DATA_PIN) | (1<<PB3); | ||
| + | DDRD |= (1<<CLK_PIN) | (1<<EN_PIN) | (1<<PD3); | ||
| - | Pin Change Interrupts (PCINT): Used to read the echo signals from the ultrasonic sensors without blocking the CPU. | + | PORTD &= ~(1<<EN_PIN); |
| - | Hardware Timers: Configured at the register level to generate the fast PWM signals for the motor driver and the precise signal for the servo motor. | + | TCCR2A = (1<<COM2A1) | (1<<COM2B1) | (1<<WGM21) | (1<<WGM20); |
| + | TCCR2B = (1<<CS22); | ||
| + | |||
| + | OCR2A = 0; // punem viteza in registrii | ||
| + | OCR2B = 0; | ||
| - | ===== Obtained Results ===== | + | shift_out_data(0); |
| + | } | ||
| - | //This section will be updated after the hardware assembly and software implementation// | + | void set_motor_dir(int m1_fwd, int m1_rev, int m2_fwd, int m2_rev) { |
| + | uint8_t shift_data = 0; | ||
| + | if (m1_fwd) shift_data |= (1<<M1_A); | ||
| + | if (m1_rev) shift_data |= (1<<M1_B); | ||
| + | if (m2_fwd) shift_data |= (1<<M2_A); | ||
| + | if (m2_rev) shift_data |= (1<<M2_B); | ||
| + | shift_out_data(shift_data); | ||
| + | } | ||
| - | ===== Conclusions ===== | + | void sonar_init() { |
| + | DDRC |= (1<<TRIG_PIN); //pc0 output | ||
| + | DDRC &= ~(1<<ECHO_PIN); | ||
| - | //This section will be updated at the end of the project// | + | TCCR1A = 0; |
| + | TCCR1B = (1<<CS11); | ||
| - | ===== Download ===== | + | PCICR |= (1<<PCIE1); |
| + | PCMSK1 |= (1<<PCINT9); | ||
| + | } | ||
| - | //Source code and schematics will be uploaded here in a .zip archive and linked to a public GitHub repository at the end of the semester.// | + | ISR(PCINT1_vect) { |
| + | if (PINC & (1<<ECHO_PIN)) { | ||
| + | TCNT1 = 0; | ||
| + | } else { | ||
| + | timer_val = TCNT1; | ||
| + | echo_done = 1; | ||
| + | } | ||
| + | } | ||
| - | ===== Journal ===== | + | int get_distance() { |
| + | echo_done = 0; | ||
| + | |||
| + | PORTC &= ~(1<<TRIG_PIN); | ||
| + | _delay_us(2); | ||
| + | PORTC |= (1<<TRIG_PIN); | ||
| + | _delay_us(10); | ||
| + | PORTC &= ~(1<<TRIG_PIN); | ||
| - | 09.05.2026: Chosen the project topic, validated the idea with the laboratory assistant, and completed the initial OCW documentation (Introduction, General Description, Hardware List). | + | uint32_t timeout = 60000; |
| + | while(!echo_done && timeout > 0) { | ||
| + | timeout--; | ||
| + | } | ||
| - | ===== Bibliography/Resources ===== | + | if(timeout == 0) return 400; |
| - | Hardware Resources: | + | return timer_val / 116; |
| + | } | ||
| - | ATmega328P Datasheet | + | int map_speed(int x, int in_min, int in_max, int out_min, int out_max) { |
| + | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | ||
| + | } | ||
| - | HC-SR04+ Ultrasonic Sensor specifications | + | int main() { |
| + | usart_init(); | ||
| + | motors_init(); | ||
| + | sonar_init(); | ||
| + | |||
| + | sei(); | ||
| + | printf("ACC System Bare Metal Started\n"); | ||
| - | TB6612FNG Motor Driver datasheet | + | int safe_dist = 25; |
| + | int max_dist = 85; | ||
| + | |||
| + | while(1) { | ||
| + | int dist = get_distance(); | ||
| + | if(dist == 0 || dist > 400) dist = 400; | ||
| + | |||
| + | printf("Dist: %d cm\n", dist); | ||
| + | |||
| + | if (dist > max_dist) { | ||
| + | set_motor_dir(0, 0, 0, 0); | ||
| + | OCR2A = 0; | ||
| + | OCR2B = 0; | ||
| + | } else if (dist > safe_dist) { | ||
| + | int speed = map_speed(dist, safe_dist, max_dist, 115, 220); | ||
| + | set_motor_dir(1, 0, 1, 0); | ||
| + | OCR2A = speed; | ||
| + | OCR2B = speed; | ||
| + | } else { | ||
| + | set_motor_dir(0, 0, 0, 0); | ||
| + | OCR2A = 0; | ||
| + | OCR2B = 0; | ||
| + | } | ||
| + | |||
| + | _delay_ms(50); | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | **Development Environment:** | ||
| + | * VS Code with PlatformIO (using pure C and register-level programming). | ||
| + | |||
| + | **Libraries and 3rd-party sources:** | ||
| + | * Standard AVR libc (<avr/io.h>, <avr/interrupt.h>, <util/delay.h>, <stdio.h>). | ||
| + | * **Zero** high-level Arduino libraries (like `analogWrite`, `digitalWrite`, or `pulseIn`) were used. | ||
| + | |||
| + | **Algorithms and Hardware Features utilized:** | ||
| + | * **Bit-Banging for Shift Register:** The L293D shield uses a 74HC595 shift register to control motor directions. A custom synchronous serial protocol was implemented (`shift_out_data`) to manually push bits to the latch, clock, and data pins using direct port manipulation (`PORTB`, `PORTD`). | ||
| + | * **Hardware Timers (Fast PWM):** Timer2 was configured at the register level (`TCCR2A`, `TCCR2B`) to generate a pure hardware Fast PWM signal on pins OC2A and OC2B. This controls the motor speed without utilizing CPU cycles. | ||
| + | * **Pin Change Interrupts (PCINT) & Timer1:** To avoid blocking the CPU while waiting for the ultrasonic echo, the Echo pin was mapped to a Pin Change Interrupt (`PCINT1_vect`). Timer1 counts the micro-seconds in the background, making the distance reading asynchronous and highly efficient. | ||
| + | * **Custom USART Stream:** The USART module was initialized manually (`UBRR0`, `UCSR0`), and the standard output stream (`stdout`) was redirected to the serial port, allowing the use of `printf()` for clean, professional real-time debugging. | ||
| + | |||
| + | ===== Obtained Results ===== | ||
| + | |||
| + | The system reacts accurately and smoothly to dynamic environments. | ||
| + | * The custom non-blocking ultrasonic reading accurately updates the distance without hanging the main loop. | ||
| + | * The proportional mapping successfully overcomes the static friction of the DC motors by setting a calculated minimum PWM threshold (115), ensuring the car starts moving reliably even at low speeds. | ||
| + | * The car smoothly decelerates as it approaches the 25 cm safety threshold and completely halts to prevent collisions. | ||
| + | |||
| + | **Final Project Photo:** | ||
| + | |||
| + | |||
| + | |||
| + | {{:pm:prj2026:andrei.batasev:2111.jpeg?200|}} | ||
| + | {{:pm:prj2026:andrei.batasev:999.jpeg?200|}} | ||
| + | ===== Conclusions ===== | ||
| + | |||
| + | Implementing this project in a bare-metal C environment provided profound insights into the internal workings of the ATmega328P microcontroller. Stripping away the Arduino framework forced a deeper understanding of memory mapping, the crucial difference between polling and hardware interrupts, and the complexity of generating custom serial signals (bit-banging). The project successfully replicates an industrial ADAS concept on an 8-bit architecture. | ||
| + | |||
| + | ===== Download ===== | ||
| + | {{:pm:prj2026:andrei.batasev:dorian_gilca.zip|Project Archive - Source Code and PlatformIO Configuration}} | ||
| + | |||
| + | ===== Journal ===== | ||
| + | |||
| + | * **09.05.2026**: Chosen the project topic and completed the initial OCW documentation. | ||
| + | * **17.05.2026**: Assembled the hardware components, tested the L293D motor shield, and resolved DC motor wiring issues. | ||
| + | * **19.05.2026**: Fully migrated to VS Code / PlatformIO. Successfully implemented bare-metal code integrating PCINT for the HC-SR04 sensor, Timer2 Fast PWM for motor speed, and custom bit-banging for directional control. Tuned the PWM thresholds to overcome static friction. | ||
| + | |||
| + | ===== Bibliography/Resources ===== | ||
| - | Software Resources: | + | **Hardware Resources:** |
| + | * ATmega328P Datasheet (Microchip Technology) | ||
| + | * HC-SR04 Ultrasonic Sensor Specifications | ||
| + | * L293D Motor Shield Schematic & 74HC595 Datasheet | ||
| - | AVR Libc Reference Manual | + | **Software Resources:** |
| + | * AVR Libc Reference Manual | ||
| + | * PlatformIO Documentation | ||