Crosswalk Simulator/Stoplight Code Snippet

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

Crosswalk Simulator/Stoplight: The Big Picture

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.

Final Project pic 2

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

Final Project pic 1

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.