Here is the schematic for the crosswalk system:
The code and the schematic were based on this state machine diagram:
Here is the schematic for the crosswalk system:
The code and the schematic were based on this state machine diagram:
You can see the commented code we used below:
/** * \file * * \brief Empty user application template * */ /** * \mainpage User Application template doxygen documentation * * \par Empty user application template * * Bare minimum empty user application template * * \par Content * * -# Include the ASF header files (through asf.h) * -# "Insert system clock initialization code here" comment * -# Minimal main function that starts with a call to board_init() * -# "Insert application code here" comment * */ /* * Include header files for all drivers that have been imported from * Atmel Software Framework (ASF). */ /* * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> */ #include <asf.h> #include <delay.h> #include <avr/io.h> #include <stdio.h> #include <conf_example.h> int adc_result; //Function to get the result from the ADC pin and save it to the above global variable static void adc_handler(ADC_t *adc, uint8_t ch_mask, adc_result_t result) { adc_result = 0; #ifdef CONF_BOARD_OLED_UG_2832HSWEG04 gfx_mono_draw_filled_rect(0,0,128,32,GFX_PIXEL_CLR); #endif adc_result = (uint8_t)result; } //this function checks if a "pedestrian" is at the intersection //if the result from the ADC pin is between 100 and 200, then return true //otherwise return false bool checkForPedestrian(ADC_t *adc, uint8_t ch_mask) { adc_start_conversion(adc, ch_mask); if(adc_result > 100 && adc_result < 200) return true; else return false; } //draw a walk sign using ASCII characters on the screen void drawWalkSign() { gfx_mono_draw_string(" O", 10, 10, &sysfont); gfx_mono_draw_string(" v|\\", 10, 17, &sysfont); gfx_mono_draw_string(" / \\", 10, 25, &sysfont); } //draw a don't walk hand on the screen using ASCII characters void drawHand() { gfx_mono_draw_string("^^^^", 30, 0, &sysfont); gfx_mono_draw_string("|||||^", 28, 7, &sysfont); gfx_mono_draw_string("||||| |", 28, 14, &sysfont); gfx_mono_draw_string("\\____/", 30, 23, &sysfont); } //draw a timer bar on the screen and also make the speaker beep void drawBar(struct pwm_config buzzer) { int count = 0; int count_2 = 0; //this will delay the whole process by 14 seconds while(count < 140) { //draw a rectangle that grows across the screen gfx_mono_draw_rect(0, 0, count, 6, GFX_PIXEL_SET); count += 10; count_2++; //turn the speaker on pwm_start(&buzzer,100); //wait for a second delay_ms(1000); //turn the speaker off pwm_start(&buzzer, 50); } //turn the speaker completely off pwm_start(&buzzer, 0); //reset the ADC result adc_result = 0; } int main (void) { //initialize everything board_init(); sysclk_init(); gfx_mono_init(); ioport_set_pin_high(LCD_BACKLIGHT_ENABLE_PIN); //PWM configs for the various LEDs struct pwm_config green; struct pwm_config red; struct pwm_config yellow; struct pwm_config walk; struct pwm_config green_2; struct pwm_config red_2; struct pwm_config yellow_2; struct pwm_config buzzer; /* Set up a PWM channel with 500 Hz frequency. Here we will output 4 different pulse trains on 4 pins of the A3BU Xplained.*/ pwm_init(&red, PWM_TCC0, PWM_CH_A, 500); //this is SDA on J1 on the A3BU Xplained pwm_init(&green, PWM_TCC0, PWM_CH_B, 500); //On A3BU Xplained board, SCL on J1 pwm_init(&yellow, PWM_TCC0, PWM_CH_C, 500);//On A3BU Xplained board, RXD on J1 pwm_init(&walk, PWM_TCC0, PWM_CH_D, 500); //On A3BU Xplained board, TXD on J1 pwm_init(&red_2, PWM_TCE0, PWM_CH_A, 500); //this is SDA on J1 on the A3BU Xplained pwm_init(&green_2, PWM_TCE0, PWM_CH_B, 500); //On A3BU Xplained board, SCL on J1 pwm_init(&yellow_2, PWM_TCE0, PWM_CH_C, 500);//On A3BU Xplained board, RXD on J1 pwm_init(&buzzer, PWM_TCE0, PWM_CH_D, 2000); //On A3BU Xplained board, TXD on J1 // Set each of the 4 PWM channel duty cycles independently, and start them going pwm_start(&red,100); pwm_start(&green,100); pwm_start(&yellow,100); pwm_start(&walk,100); pwm_start(&red_2,100); pwm_start(&green_2,100); pwm_start(&yellow_2,100); pwm_start(&buzzer,0); /*************************/ //ADC initialization steps /*************************/ struct adc_config adc_conf; struct adc_channel_config adcch_conf; sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); // Initialize configuration structures. adc_read_configuration(&ADCB, &adc_conf); adcch_read_configuration(&ADCB, ADC_CH0, &adcch_conf); /* Configure the ADC module: * - unsigned, 12-bit results * - VCC voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering * - temperature sensor enabled * - callback function */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE); adc_write_configuration(&ADCB, &adc_conf); adc_set_callback(&ADCB, &adc_handler); /* Configure ADC channel 0: * - single-ended measurement from temperature sensor * - interrupt flag set on completed conversion * - interrupts disabled */ adcch_set_input(&adcch_conf, ADCCH_POS_PIN1, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCB, ADC_CH0, &adcch_conf); // Enable the ADC adc_enable(&ADCB); //ON and OFF duty cycle values int ON = 100; int OFF = 0; //bool to check for pedestrians in the intersection bool pedestrian = false; //loop forever while(1) { //as long as there is no pedestrian at the intersection //leave the green and red_2 LEDs on, and the rest off while(!pedestrian) { pwm_start(&red,OFF); pwm_start(&green,ON); pwm_start(&yellow,OFF); pwm_start(&red_2,ON); pwm_start(&green_2,OFF); pwm_start(&yellow_2,OFF); //check the ADC pin to see if a pedestrian is at the intersection pedestrian = checkForPedestrian(&ADCB, ADC_CH0); } /***a pedestrian has pressed the button, now transition***/ //reset pedestrian value pedestrian = false; //wait for a half second delay_ms(500); //turn green off and turn yellow on pwm_start(&green,OFF); pwm_start(&yellow,ON); //wait for 3 seconds delay_ms(3000); //turn yellow off and turn red on pwm_start(&yellow,OFF); pwm_start(&red,ON); //wait for 2 seconds delay_ms(2000); //turn red_2 off and turn green_2 on pwm_start(&green_2,ON); pwm_start(&red_2,OFF); //clear the LCD screen gfx_mono_init(); //draw the walk signs and the timer bar, and start the speaker drawWalkSign(); drawBar(buzzer); //clear the LCD screen gfx_mono_init(); //draw the Don't Walk hand drawHand(); //wait for 5 seconds to prevent a pedestrian from immediately pushing the button again delay_ms(5000); //as long as there is no pedestrian at the intersection //leave the green_2 and red LEDs on, and the rest off while(!pedestrian) { pwm_start(&red_2,OFF); pwm_start(&green_2,ON); pwm_start(&yellow_2,OFF); pwm_start(&red,ON); pwm_start(&green,OFF); pwm_start(&yellow,OFF); //check the ADC pin to see if a pedestrian is at the intersection pedestrian = checkForPedestrian(&ADCB, ADC_CH0); } /***a pedestrian has pressed the button, now transition***/ //reset pedestrian value pedestrian = false; //wait for a half second delay_ms(500); //turn green_2 off and turn yellow_2 on pwm_start(&green_2,OFF); pwm_start(&yellow_2,ON); //wait for 3 seconds delay_ms(3000); //turn yellow_2 off and turn red_2 on pwm_start(&yellow_2,OFF); pwm_start(&red_2,ON); //wait for 2 seconds delay_ms(2000); //turn red off and turn green on pwm_start(&green,ON); pwm_start(&red,OFF); //clear the LCD screen gfx_mono_init(); //draw the walk signs and the timer bar, and start the speaker drawWalkSign(); drawBar(buzzer); //clear the LCD screen gfx_mono_init(); //draw the Don't Walk hand drawHand(); //wait for 5 seconds to prevent a pedestrian from immediately pushing the button again delay_ms(5000); /***Repeat the whole process again***/ } }
C Code created in Atmel Studio 7 that dictates the actions of our LCD and circuit
The fundamental goal of this project was to recreate the same type of crosswalk that could be found at the intersection of Eastern Parkway and Speed School. The scope of the project contained two stop lights (6 LEDs Total), walk/don’t walk graphics, battery powered crosswalk button, a sounding buzzer for echolocation, and a “time remaining” indicator.
The A3BU board worked well for all functions that we needed to complete this project. The board provided us with enough GPIO pins to provide power control for 6 of the 3V LED’s, as well as frequency pulse with modulation to control the buzzer. An analog -to-digital converter (ADC) pin was also utilized to detect digital-hi’s when the crosswalk button was pressed. The battery provided a voltage that would then be tested against a certain range, and if the value was in that range, the crosswalk logic would trigger.
LED Layout with A3BU, buzzer, and button.
The LCD display served a large purpose as it displayed all of our crosswalk functions. When the crosswalk button was pressed and the light turns red, a ASCII graphic of a “walkman” appears letting you know its safe to cross. A incremented bar also appears, gradually growing larger allowing the walker to see how much time they have left to cross. Once this timer ends, an ASCII “stop-hand” appears, letting the user know it’s no longer safe to cross.
LCD displaying the ‘walkman’ and the timer bar at the top
The buzzer was turned off and on by varying the duty cycle on the GPIO output, while the pitched was changed by editing the frequency of the pulses. Here is a video displaying all the functions.