STM32F407VG Traffic control system

Thread Starter

Hamnah-Malik

Joined Nov 25, 2024
7
I am trying to make a three way traffic controlling system i have already configured and made my block diagram i am using ultra sonic sensors to control the traffic lights so that if the sensor detects more traffic the time for the light to stay green increases i am also using a sensor for the pedestrians but my code isnt working correctly the sensors arent taking readings correctly and the lights arent function as i want i am attaching my code below please help me pinpoint the issue

Mod: please use Code quotes

C-like:
#include "stm32f4xx.h"


// Delay using SysTick

void delay_us(int us) {

    SysTick->LOAD = 16 - 1;  // 1 us tick at 16 MHz

    SysTick->VAL = 0;

    SysTick->CTRL = 5;       // ENABLE + CLKSOURCE


    for (int i = 0; i < us; i++) {

        while (!(SysTick->CTRL & (1 << 16)));

    }


    SysTick->CTRL = 0;

}


void delay_ms(int ms) {

    for (int i = 0; i < ms; i++) {

        delay_us(1000);

    }

}


void GPIO_Init(void) {

    // Enable clocks for GPIOA, GPIOB, and GPIOE

    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOEEN;


    // GPIOA0–A8 as outputs (traffic lights)

    GPIOA->MODER &= ~(0x3FFFF);

    GPIOA->MODER |=  (0x15555);  // 01 = output


    GPIOA->OTYPER &= ~(0x1FF);   // Push-pull

    GPIOA->OSPEEDR |=  (0x3FFFF);

    GPIOA->PUPDR   &= ~(0x3FFFF);


    // PA9 = TRIG A (output), PA10 = ECHO A (input, default)

    GPIOA->MODER &= ~(3 << (9 * 2));

    GPIOA->MODER |=  (1 << (9 * 2)); // PA9 output


    // PB10 (TRIG B), PB12 (TRIG C), PB5 (TRIG Pedestrian) -> output

    GPIOB->MODER &= ~((3 << (10 * 2)) | (3 << (12 * 2)) | (3 << (5 * 2)));

    GPIOB->MODER |=  ((1 << (10 * 2)) | (1 << (12 * 2)) | (1 << (5 * 2)));


    // PB11 (ECHO B), PB13 (ECHO C), PB4 (ECHO Pedestrian) -> input (default)


    // PB8, PB9: Pedestrian LEDs -> output

    GPIOB->MODER &= ~((3 << (8 * 2)) | (3 << (9 * 2)));

    GPIOB->MODER |=  ((1 << (8 * 2)) | (1 << (9 * 2)));


    GPIOB->OTYPER &= ~((1 << 5) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 12));

    GPIOB->OSPEEDR |= ((3 << (5 * 2)) | (3 << (8 * 2)) | (3 << (9 * 2)) |

                       (3 << (10 * 2)) | (3 << (12 * 2)));

    GPIOB->PUPDR &= ~((3 << (4 * 2)) | (3 << (5 * 2)) |

                      (3 << (8 * 2)) | (3 << (9 * 2)) |

                      (3 << (10 * 2)) | (3 << (12 * 2)));

                                           

    // Enable clock for GPIOE

    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;


    // Set PE7 as output (Debug LED)

    GPIOE->MODER &= ~(3 << (7 * 2));  // Clear mode

    GPIOE->MODER |= (1 << (7 * 2));   // Set as output


    GPIOE->OTYPER &= ~(1 << 7);       // Push-pull

    GPIOE->OSPEEDR |= (3 << (7 * 2)); // High speed

    GPIOE->PUPDR &= ~(3 << (7 * 2));  // No pull-up, no pull-down

}


// Ultrasonic distance reading in cm

uint32_t read_distance_cm(GPIO_TypeDef* TRIG_PORT, int trig_pin, GPIO_TypeDef* ECHO_PORT, int echo_pin) {

    TRIG_PORT->ODR &= ~(1 << trig_pin);

    delay_us(2);

    TRIG_PORT->ODR |= (1 << trig_pin);

    delay_us(10);

    TRIG_PORT->ODR &= ~(1 << trig_pin);


    int timeout = 30000;

    while (!(ECHO_PORT->IDR & (1 << echo_pin)) && timeout--);


    int count = 0;

    timeout = 30000;

    while ((ECHO_PORT->IDR & (1 << echo_pin)) && timeout--) {

        delay_us(1);

        count++;

    }


    return count / 58;

}


uint32_t get_stable_distance(GPIO_TypeDef* TRIG_PORT, int trig_pin, GPIO_TypeDef* ECHO_PORT, int echo_pin) {

    int readings = 5;

    int valid = 0;

    uint32_t total = 0;


    for (int i = 0; i < readings; i++) {

        uint32_t dist = read_distance_cm(TRIG_PORT, trig_pin, ECHO_PORT, echo_pin);

        if (dist > 0) {  // Accept all non-zero readings

            total += dist;

            valid++;

        }

        delay_ms(20);

    }


    if (valid >= 3)  // Use if at least 3 readings were successful

        return total / valid;

    else

        return 999;  // Signal: no object reliably detected

}


void set_light(int base_pin, int red, int yellow, int green) {

    GPIOA->ODR &= ~(0x7 << base_pin);

    if (red)    GPIOA->ODR |= (1 << base_pin);

    if (yellow) GPIOA->ODR |= (1 << (base_pin + 1));

    if (green)  GPIOA->ODR |= (1 << (base_pin + 2));

}


void turn_red_all() {

    set_light(0, 1, 0, 0);  // A

    set_light(3, 1, 0, 0);  // B

    set_light(6, 1, 0, 0);  // C

}


int get_green_time(uint32_t dist) {

    int green_time = 5000;

    if (dist < 20) green_time = 10000;

    if (dist < 10) green_time = 15000;

    return green_time;

}


void run_traffic_cycle(int road) {

    int base_pins[3] = {0, 3, 6};

    int base = base_pins[road];


    turn_red_all();


    int green_time = 5000;


    if (road == 0)

        green_time = get_green_time(get_stable_distance(GPIOA, 9, GPIOA, 10));

    else if (road == 1)

        green_time = get_green_time(get_stable_distance(GPIOB, 10, GPIOB, 11));

    else if (road == 2)

        green_time = get_green_time(get_stable_distance(GPIOB, 12, GPIOB, 13));


    set_light(base, 0, 0, 1); delay_ms(green_time);

    set_light(base, 0, 1, 0); delay_ms(2000);

    set_light(base, 1, 0, 0);

}


void check_pedestrian_and_run() {

    uint32_t pdist = get_stable_distance(GPIOB, 5, GPIOB, 4);  // Get distance from pedestrian sensor


    // Debugging: Check the distance reading

    if (pdist < 40) {  // If a pedestrian is detected within 40 cm

        // Turn off the red LED and turn on the green LED for pedestrian

        GPIOB->ODR &= ~(1 << 8);  // Red OFF

        GPIOB->ODR |= (1 << 9);   // Green ON


        // Debugging: Turn on the debug LED (PE7) to indicate pedestrian detected

        GPIOE->ODR |= (1 << 7);   // Debug LED ON


        delay_ms(5000);           // Pedestrian green LED stays on for 5 seconds


        // After the pedestrian has crossed, turn off the green LED

        GPIOB->ODR &= ~(1 << 9);  // Green OFF

        GPIOB->ODR |= (1 << 8);   // Red ON


        // Debugging: Turn off the debug LED (PE7) after pedestrian is done

        GPIOE->ODR &= ~(1 << 7);  // Debug LED OFF

    } else {

        // No pedestrian detected, ensure the green LED is off

        GPIOB->ODR &= ~(1 << 9);  // Green OFF

        GPIOB->ODR |= (1 << 8);   // Red ON

    }

}


int main(void) {

    GPIO_Init();

    GPIOB->ODR |= (1 << 8);  // Pedestrian red initially ON


    while (1) {

        run_traffic_cycle(0);

        check_pedestrian_and_run();


        run_traffic_cycle(1);

        check_pedestrian_and_run();


        run_traffic_cycle(2);

        check_pedestrian_and_run();

    }

}
 
Last edited by a moderator:

atferrari

Joined Jan 6, 2004
5,001
Is the increasing of time for one of the streets (assisted by sensors) required for the design? The beauty (in grid like distribution of streets) resides in the regular opening/closing of green lights in the whole area.
 

Thread Starter

Hamnah-Malik

Joined Nov 25, 2024
7
Is the increasing of time for one of the streets (assisted by sensors) required for the design? The beauty (in grid like distribution of streets) resides in the regular opening/closing of green lights in the whole area.
yes we were asked to make it like that
 
Top