Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2026:andrei.batasev:dorian.gilca [2026/05/23 18:05]
dorian.gilca
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:**
Line 16: Line 17:
 ===== 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 driverenabling ​the car to smoothly accelerate or brakeAn 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 ​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 brakesIf 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 ​Nano (ATmega328P Microcontroller) +  * Arduino ​UNO (ATmega328P Microcontroller) ​serving as the main processing unit. 
-  * 3x HC-SR04Ultrasonic ​Sensors +  * L293D Motor Drive Shield (featuring the 74HC595 shift register). 
-  * TB6612FNG Motor Driver +  * 1x HC-SR04 Ultrasonic ​Sensor. 
-  * 1x DC Motor with Optical Encoder ​(Rear traction) +  * 2x DC TT Motors ​(Rear-wheel or 4-wheel drive configuration). 
-  * 1x Servo Motor (Front steering) +  * 2x 18650 Li-Ion Batteries ​(7.4V total) ​with holder
-  * LM2596 Step-Down Voltage Regulator +  * Robot car chassis with wheels. 
-  * 2x 18650 Li-Ion Batteries with holder +  * Dupont connecting wires.
-  * Breadboard and Dupont connecting wires+
  
 **Electrical Schematic:​** **Electrical Schematic:​**
-//To be uploaded after the circuit design is finalized.//+ 
 + 
 + 
 +{{:​pm:​prj2026:​andrei.batasev:​schema_electrica.jpg?​300|}} 
  
 ===== Software Design ===== ===== Software Design =====
  
 +<code c>
 +#include <​avr/​io.h>​
 +#include <​avr/​interrupt.h>​
 +#include <​util/​delay.h>​
 +#include <​stdio.h>​
 +
 +#define PM_BAUD 9600
 +
 +#define TRIG_PIN PC0
 +#define ECHO_PIN PC1
 +
 +#define LATCH_PIN PB4
 +#define CLK_PIN ​  PD4
 +#define EN_PIN ​   PD7
 +#define DATA_PIN ​ PB0
 +
 +#define M1_A 2
 +#define M1_B 3
 +#define M2_A 1
 +#define M2_B 4
 +
 +volatile uint16_t timer_val = 0;
 +volatile uint8_t echo_done = 0;
 +
 +static int _usart0_putchar(char c, FILE *stream) {
 +    if (c == '​\n'​) _usart0_putchar('​\r',​ stream);
 +    while (!(UCSR0A & (1<<​UDRE0)));​
 +    UDR0 = c;
 +    return 0;
 +}
 +
 +static FILE USART0_stdout = FDEV_SETUP_STREAM(_usart0_putchar,​ NULL, _FDEV_SETUP_WRITE);​
 +
 +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;​
 +}
 +
 +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); ​
 +}
 +
 +void motors_init() {
 +    DDRB |= (1<<​LATCH_PIN) | (1<<​DATA_PIN) | (1<<​PB3);​
 +    DDRD |= (1<<​CLK_PIN) | (1<<​EN_PIN) | (1<<​PD3);​
 +
 +    PORTD &= ~(1<<​EN_PIN);​
 +
 +    TCCR2A = (1<<​COM2A1) | (1<<​COM2B1) | (1<<​WGM21) | (1<<​WGM20);​
 +    TCCR2B = (1<<​CS22);​
 +    ​
 +    OCR2A = 0; // punem viteza in registrii
 +    OCR2B = 0;
 +
 +    shift_out_data(0);​
 +}
 +
 +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);​
 +}
 +
 +void sonar_init() {
 +    DDRC |= (1<<​TRIG_PIN);​ //pc0 output
 +    DDRC &= ~(1<<​ECHO_PIN); ​
 +
 +    TCCR1A = 0;
 +    TCCR1B = (1<<​CS11);​
 +
 +    PCICR |= (1<<​PCIE1);​
 +    PCMSK1 |= (1<<​PCINT9);​
 +}
 +
 +ISR(PCINT1_vect) {
 +    if (PINC & (1<<​ECHO_PIN)) {
 +        TCNT1 = 0;
 +    } else {
 +        timer_val = TCNT1;
 +        echo_done = 1;
 +    }
 +}
 +
 +int get_distance() {
 +    echo_done = 0;
 +    ​
 +    PORTC &= ~(1<<​TRIG_PIN);​
 +    _delay_us(2);​
 +    PORTC |= (1<<​TRIG_PIN);​
 +    _delay_us(10);​
 +    PORTC &= ~(1<<​TRIG_PIN);​
 +
 +    uint32_t timeout = 60000;
 +    while(!echo_done && timeout > 0) {
 +        timeout--;
 +    }
 +
 +    if(timeout == 0) return 400;
 +
 +    return timer_val / 116;
 +}
 +
 +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;
 +}
 +
 +int main() {
 +    usart_init();​
 +    motors_init();​
 +    sonar_init();​
 +    ​
 +    sei();
 +    printf("​ACC System Bare Metal Started\n"​);​
 +
 +    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:​** **Development Environment:​**
-  * PlatformIO ​/ Arduino IDE (using pure C/C++ and register-level programming)+  * VS Code with PlatformIO (using pure C and register-level programming).
  
 **Libraries and 3rd-party sources:** **Libraries and 3rd-party sources:**
-  * Standard AVR libc (<​avr/​io.h>,​ <​avr/​interrupt.h>​) +  * Standard AVR libc (<​avr/​io.h>,​ <​avr/​interrupt.h>, <​util/​delay.h>,​ <stdio.h>). 
-  * No high-level Arduino libraries (like analogWrite or pulseIn) ​will be used for core functionalities,​ to adhere to the course requirements.+  * **Zero** ​high-level Arduino libraries (like `analogWrite`, `digitalWrite`, ​or `pulseIn`were used.
  
-**Algorithms and Structures:** +**Algorithms and Hardware Features utilized:** 
-  * **PID Controller:** A mathematical algorithm ​to smoothly calculate ​the motor speed based on the distance error+  * **Bit-Banging for Shift Register:** The L293D shield uses a 74HC595 shift register to control motor directions. ​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`). 
-  * **Pin Change Interrupts (PCINT):​** ​Used to read the echo signals from the ultrasonic ​sensors without blocking ​the CPU+  * **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
-  * **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.+  * **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 ===== ===== Obtained Results =====
  
-//This section will be updated after the hardware assembly ​and software implementation//​+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 ===== ===== Conclusions =====
  
-//This section will be updated at the end of the project//+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 ===== ===== Download =====
- +{{:​pm:​prj2026:​andrei.batasev:​dorian_gilca.zip|Project Archive - Source Code and PlatformIO Configuration}}
-//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.//+
  
 ===== Journal ===== ===== Journal =====
  
-  * **09.05.2026**:​ Chosen the project topic, validated the idea with the laboratory assistant, ​and completed the initial OCW documentation ​(IntroductionGeneral DescriptionHardware List).+  * **09.05.2026**:​ Chosen the project topic and completed the initial OCW documentation
 +  * **17.05.2026**:​ Assembled the hardware componentstested the L293D motor shieldand 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 ===== ===== Bibliography/​Resources =====
  
 **Hardware Resources:​** **Hardware Resources:​**
-  * ATmega328P Datasheet +  * ATmega328P Datasheet ​(Microchip Technology) 
-  * HC-SR04Ultrasonic Sensor ​specifications +  * HC-SR04 Ultrasonic Sensor ​Specifications 
-  * TB6612FNG ​Motor Driver datasheet+  * L293D Motor Shield Schematic & 74HC595 Datasheet
  
 **Software Resources:​** **Software Resources:​**
   * AVR Libc Reference Manual   * AVR Libc Reference Manual
 +  * PlatformIO Documentation
pm/prj2026/andrei.batasev/dorian.gilca.1779548710.txt.gz · Last modified: 2026/05/23 18:05 by dorian.gilca
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0