void sensors_aquire_inputbutton() { if(!sensors_en.inputbutton) return; static int button_pressed = 0; if(!button_pressed && button_is_pressed(&button_user1)) { button_pressed = 1; } else if(button_pressed && !button_is_pressed(&button_user1)) { button_pressed = 0; } sensors.inputbutton.state = button_pressed; }
// Displays the temperature, in C or F. void temp_test() { static int display_c = 0; // 0 for F, 1 for C int temperature; if(display_c) temperature = read_temperature_c(); else temperature = read_temperature_f(); // display temperature; it is in tenths of a degree print_long(temperature/10); print("."); print_long(temperature%10); // character 0xDF is the degree symbol print_character('\xdf'); if(display_c) print_character('C'); else print_character('F'); // allow the user to switch between modes if(button_is_pressed(BUTTON_A)) display_c = 1; if(button_is_pressed(BUTTON_C)) display_c = 0; delay_ms(100); }
void ir_test() { unsigned int sensors[5]; // an array to hold sensor values if(button_is_pressed(BUTTON_C)) read_line_sensors(sensors, IR_EMITTERS_OFF); else read_line_sensors(sensors,IR_EMITTERS_ON); unsigned char i; for(i=0; i<5; i++) { // Initialize the array of characters that we will use for the // graph. Using the space, an extra copy of the one-bar // character, and character 255 (a full black box), we get 10 // characters in the array. // The variable c will have values from 0 to 9, since // values are in the range of 0 to 2000, and 2000/201 is 9 // with integer math. char c = bar_graph_characters[sensors[i]/201]; // Display the bar graph characters. print_character(c); } // Display an indicator of whether IR is on or off if(button_is_pressed(BUTTON_C)) print("IR-"); else print(" C"); delay_ms(100); }
// This is the main function, where the code starts. All C programs // must have a main() function defined somewhere. int main() { // Set all five user LEDs as outputs driven low. // Otherwise, the LEDs are driven by the LCD and can appear // on or partially on. red_led(0); green_led(0); red_led2(0); green_led2(0); yellow_led(0); clear(); delay(10); // if any button is pressed, go into the old version of the test code if(button_is_pressed(ANY_BUTTON)) { print("Simple Test"); wait_for_button_release(button_is_pressed(ANY_BUTTON)); test(); // activate the simpler test code } // set up the robot initialize(); // This is the "main loop" - it will run forever. while(1) { menu_select(); } }
/** waitForButton ********************************************** * Pause until a button is pressed. * @params button -- identifier of button to wait for * tune -- sequence of notes played when button is pressed */ void waitForButton(unsigned char button, const char *tune) { while(!button_is_pressed(button)) { delay_ms(100); } play_from_program_space(tune); while (button_is_pressed(button)) ; // wait for button up delay_ms(200); }
void time_test() { static long elapsed_time = 0; static long last_read = 0; static long is_ticking = 0; static char a_is_pressed = 0; static char c_is_pressed = 0; static char last_seconds = 0; long current_time = get_ms(); if(is_ticking) elapsed_time += current_time - last_read; last_read = current_time; if(button_is_pressed(BUTTON_A) && !a_is_pressed) { // reset a_is_pressed = 1; is_ticking = 0; elapsed_time = 0; if(!is_playing()) // only play once play_from_program_space(beep_button_a); } // find the end of the button press without stopping if(!button_is_pressed(BUTTON_A)) a_is_pressed = 0; if(button_is_pressed(BUTTON_C) && !c_is_pressed) { // start/stop c_is_pressed = 1; is_ticking = !is_ticking; play_from_program_space(beep_button_c); } // find the end of the button press without stopping if(!button_is_pressed(BUTTON_C)) c_is_pressed = 0; print_long((elapsed_time/1000/60/10)%10); // tens of minutes print_long((elapsed_time/1000/60)%10); // minutes print_character(':'); print_long((elapsed_time/1000)%60/10); // tens of seconds char seconds = ((elapsed_time/1000)%60)%10; print_long(seconds); // seconds print_character('.'); print_long((elapsed_time/100)%10); // tenths of seconds print_long((elapsed_time/10)%10); // hundredths of seconds // beep every second if(seconds != last_seconds && elapsed_time != 0 && !is_playing()) play_from_program_space(timer_tick); last_seconds = seconds; }
unsigned char motor_wait(unsigned int time_ms) { unsigned char button; unsigned long time = get_ms(); while (get_ms() - time < time_ms) { // check if top or bottom buttons have been pressed button = button_is_pressed(TOP_BUTTON | MIDDLE_BUTTON); if (button != 0) // if so, turn off motors and LEDs, return button ID { set_motors(0, 0); return button; } lcd_goto_xy(10, 0); print("cur: "); print_unsigned_long(x2_get_motor_current(MOTOR1)); print(" "); lcd_goto_xy(10, 1); print("cur: "); print_unsigned_long(x2_get_motor_current(MOTOR2)); print(" "); } return 0; }
int main( void ) { /* perform battery check */ bat_check(); /* display welcome message and */ /* seed random number generator */ clear(); lcd_goto_xy(0,0); print("Welcome!"); lcd_goto_xy(0,1); print("Press B"); wait_for_button_press(BUTTON_B); /* button down */ long seed = 0; while(button_is_pressed(BUTTON_B)) /* while button not released */ seed++; srandom(seed); while(1) { clear(); /* obtain random number between 0-9 */ int val = random() % 10; /* display number */ lcd_goto_xy(0,0); print_long(val); lcd_goto_xy(0,1); print("Press B"); /* wait for user to press/release B */ wait_for_button(BUTTON_B); } }
void sleep_until_eswitch_pressed() { WDT_off(); ADC_off(); // make sure switch isn't currently pressed while (button_is_pressed()) {} empty_event_sequence(); // cancel pending input on suspend //PCINT_since_WDT = 0; // ensure PCINT won't ignore itself PCINT_on(); // wake on e-switch event // configure sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_bod_disable(); sleep_cpu(); // wait here // something happened; wake up sleep_disable(); #ifdef USE_THERMAL_REGULATION // forget what the temperature was last time we were on reset_thermal_history = 1; #endif // go back to normal running mode //PCINT_on(); // should be on already // FIXME? if button is down, make sure a button press event is added to the current sequence ADC_on(); WDT_on(); }
int main() { lcd_load_custom_character(happy, 0); lcd_load_custom_character(sad, 1); lcd_load_custom_character(indifferent, 2); lcd_load_custom_character(surprised, 3); lcd_load_custom_character(mocking, 4); clear(); // this must be called before we can use the custom characters print("mood: ?"); // initialize the random number generator based on how long we hold the button the first time wait_for_button_press(ANY_BUTTON); long seed = 0; while(button_is_pressed(ANY_BUTTON)) seed++; srandom(seed); while(1) { lcd_goto_xy(6, 0); // move cursor to the correct position char mood; do { mood = random()%5; } while (mood == prevMood); // ensure we get a new mood that differs from the previous prevMood = mood; print_character(mood); // print a random mood character wait_for_button(ANY_BUTTON); // wait for any button to be pressed } }
void sensor_graph() { unsigned int values[5]; clear(); while(!button_is_pressed(BUTTON_B)) { read_line_sensors(values,IR_EMITTERS_ON); display_values(values,TEST_LINE_SENSOR_TIMEOUT); lcd_goto_xy(6,1); print("B"); delay_ms(50); } while(button_is_pressed(ALL_BUTTONS)); }
/*----------------------------------------------------------------------------- * Function name: bat_check * Description: This function checks the voltage on the batteries and * displays a message on the LCD until the user presses B. * The message on the first line cycles between the following: * Bat Chk [-> descriptive message] * xxxxmV [-> the battery voltage] * Okay/Replace [-> whether the batteries should be replaced] ----------------------------------------------------------------------------*/ void bat_check( void ) { int firstLineType = 0; /* what should be displayed on line 1 */ /* 0-19: Bat Chk */ /* 20-39: xxxxmV */ /* 40-59: Okay/Replace */ int bat = 0; /* last read battery voltage */ /* wait for user to press button B */ while(!button_is_pressed(BUTTON_B)) { /* clear the lcd */ clear(); /* FIRST LINE */ /* set lcd position to beginning of first line */ lcd_goto_xy(0,0); /* for first line, alternate between displaying: Bat Check xxxxmV Okay/Replace */ if (firstLineType < 20) { print("Bat Chk"); } else if (firstLineType < 40) { bat = read_battery_millivolts(); print_long(bat); print("mV"); } else if (firstLineType < 60) { if (bat >= 4500) { print("Okay"); /* okay */ } else { print("Replace"); /* replace */ } } firstLineType++; firstLineType = firstLineType % 60; /* SECOND LINE */ /* set lcd position to beginning of second line */ lcd_goto_xy(0,1); print("Press B"); /* small delay */ delay_ms(50); } /* once pressed, wait a little bit */ delay_ms(500); }
void test() { unsigned char button; clear(); delay(200); print("Orangutn"); // print to the top line of the LCD delay_ms(400); // delay 200 ms lcd_goto_xy(0, 1); // go to the start of the second LCD line #if defined __AVR_ATmega328P__ print(" LV-328"); // print to the bottom line of the LCD #elif defined __AVR_ATmega168__ print(" LV-168"); // print to the bottom line of the LCD #else #error "Unrecognized device type" #endif delay_ms(1000); // delay 700 ms clear(); // clear the LCD, move cursor to start of top line print(" Temp."); do { // Perform 10-bit analog-to-digital conversions on ADC channel 6. // Average ten readings and return the result, which will be one // third of the battery voltage when the "ADC6 = VBAT/3" solder // bridge is in place on the bottom of the Orangutan PCB int Tf = read_temperature_f(); // read temp sensor on ADC6 in 0.1°F lcd_goto_xy(1, 1); // second character of the second LCD line print_long(Tf/10); // display temperature in °F print("."); // print the decimal point print_long(Tf - 10*(Tf/10)); // display the tenths digit print_character(223); // display the degree symbol character (°) print("F "); // display the units delay_ms(50); // delay for 50 ms button = button_is_pressed(ALL_BUTTONS); // check for button press } while (button == 0); // loop if no buttons are being pressed // *** MAIN LOOP *** while (1) // loop forever { if (button & TOP_BUTTON) // if the top button is pressed button = melodyTest(); // this func. loops until next button press else if (button & MIDDLE_BUTTON) // if the middle button is pressed button = IOTest(); // this func. loops until next button press else if (button & BOTTOM_BUTTON) // if the bottom button is pressed button = motorTest(); // this func. loops until next button press } }
void check_emitter_jumper() { unsigned int values[5]; clear(); // off values while(!button_is_pressed(BUTTON_C)) { read_line_sensors(values,IR_EMITTERS_OFF); lcd_goto_xy(0,0); print("IR- "); display_values(values,TEST_LINE_SENSOR_TIMEOUT); lcd_goto_xy(6,1); print("C"); delay_ms(50); } while(button_is_pressed(ALL_BUTTONS)); }
int main() { clear(); // clear the LCD print("Send serial"); lcd_goto_xy(0, 1); // go to start of second LCD row print("or press B"); // Set the baud rate to 9600 bits per second. Each byte takes ten bit // times, so you can get at most 960 bytes per second at this speed. serial_set_baud_rate(USB_COMM, 9600); // Start receiving bytes in the ring buffer. serial_receive_ring(USB_COMM, receive_buffer, sizeof(receive_buffer)); while(1) { // USB_COMM is always in SERIAL_CHECK mode, so we need to call this // function often to make sure serial receptions and transmissions // occur. serial_check(); // Deal with any new bytes received. check_for_new_bytes_received(); // If the user presses the middle button, send "Hi there!" // and wait until the user releases the button. if (button_is_pressed(MIDDLE_BUTTON)) { wait_for_sending_to_finish(); memcpy_P(send_buffer, PSTR("Hi there!\r\n"), 11); serial_send(USB_COMM, send_buffer, 11); send_buffer[11] = 0; // terminate the string clear(); // clear the LCD lcd_goto_xy(0, 1); // go to start of second LCD row print("TX: "); print(send_buffer); // Wait for the user to release the button. While the processor is // waiting, the OrangutanSerial library will not be able to receive // bytes from the USB_COMM port since this requires calls to the // serial_check() function, which could cause serial bytes to be // lost. It will also not be able to send any bytes, so the bytes // bytes we just queued for transmission will not be sent until // after the following blocking function exits once the button is // released. If any of this is a concern, you can replace the // following line with: // do // { // while (button_is_pressed(MIDDLE_BUTTON)) // serial_check(); // receive and transmit as needed // delay_ms(10); // debounce the button press/release // } // while (button_is_pressed(MIDDLE_BUTTON)); wait_for_button_release(MIDDLE_BUTTON); } } }
int main() { // If button A is pressed, test the PD0/PD1 outputs if(button_is_pressed(BUTTON_A)) test_outputs(); // If button C is not pressed down, go to the demo. if(!button_is_pressed(BUTTON_C) && !test_pushbutton_tries()) demo(); // Load bar graph characters. // Together with space and the solid block at 255, this makes almost // all possible bar heights, with two to spare. unsigned char i; for(i=0;i<6;i++) { lcd_load_custom_character(bars+i,i); } clear(); pololu_3pi_init(TEST_LINE_SENSOR_TIMEOUT); if(test_pushbutton_tries()) goto pushbuttons; play_from_program_space(welcome_test); print_two_lines_delay_1s_test(welcome_test_line1,welcome_test_line2); print_two_lines_delay_1s_test(test_name_line1,test_name_line2); clear(); test_battery(); test_qtr(); test_motors(); test_pot(); pushbuttons: test_pushbuttons(); clear(); print("Success"); play("O5 c16"); while(1); }
void test() { unsigned char button; clear(); delay(200); print("Orangutn"); // print to the top line of the LCD delay_ms(400); // delay 200 ms lcd_goto_xy(0, 1); // go to the start of the second LCD line #if defined __AVR_ATmega328P__ print(" SV-328"); // print to the bottom line of the LCD #elif defined __AVR_ATmega168__ print(" SV-168"); // print to the bottom line of the LCD #else #error "Unrecognized device type" #endif delay_ms(1000); // delay 700 ms clear(); // clear the LCD, move cursor to start of top line print(" VBAT"); do { // Perform 10-bit analog-to-digital conversions on ADC channel 6. // Average ten readings and return the result, which will be one // third of the battery voltage when the "ADC6 = VBAT/3" solder // bridge is in place on the bottom of the Orangutan PCB int vbat = analog_read_average(6, 10); // 10-sample avg of ADC6 vbat = to_millivolts(vbat) * 3; // convert reading to bat. voltage (mV) lcd_goto_xy(0, 1); // go to the start of the second LCD line print_long(vbat); // display battery voltage in millivolts print(" mV "); // display the units delay_ms(50); // delay for 50 ms button = button_is_pressed(ANY_BUTTON); // check for button press } while (button == 0); // loop if no buttons are being pressed // *** MAIN LOOP *** while (1) // loop forever { if (button & TOP_BUTTON) // if the top button is pressed button = melodyTest(); // this func. loops until next button press else if (button & MIDDLE_BUTTON) // if the middle button is pressed button = IOTest(); // this func. loops until next button press else if (button & BOTTOM_BUTTON) // if the bottom button is pressed button = motorTest(); // this func. loops until next button press } }
char wait_for_250_ms_or_button_b() { int i; for(i=0; i<25; i++) { delay_ms(10); if(button_is_pressed(BUTTON_B)) return 1; } return 0; }
/** displayBattery **************************************** * Output battery level, wait for button B * @modifies lcd display has battery level output. */ void displayBattery() { int bat; const int LOW_BATTERY = 3500; const int FULL_BATTERY = 6000; double batPer; while (!button_is_pressed(BUTTON_B)) {// as long as B is not pressed bat = read_battery_millivolts();// read battery voltage batPer = (double)(bat - LOW_BATTERY)/(FULL_BATTERY-LOW_BATTERY)*100; // compute percent of full value clear(); print_long(batPer); // display value print("%"); lcd_goto_xy(0,1); print("Press B"); delay_ms(100); // wait a little bit } play_from_program_space(beep_button_b); while (button_is_pressed(BUTTON_B)) ; // wait for button up delay_ms(200); }
int main(void) { RLY_DDR = _BV(RLY_BIT); PWR_BTN_PORT |= _BV(PWR_BTN_BIT); for (;;) { if (button_is_pressed()) { toggle_relay(); _delay_ms(500); } } }
void test_leds() { while(!button_is_pressed(ALL_BUTTONS)) { clear(); printf("Check\n"); printf("Red"); red_led(1); play_frequency(440,50,15); delay_ms(250); if(button_is_pressed(ALL_BUTTONS)) break; red_led(0); delay_ms(250); if(button_is_pressed(ALL_BUTTONS)) break; clear(); printf("Check\n"); printf("Green"); green_led(1); play_frequency(880,50,15); delay_ms(250); if(button_is_pressed(ALL_BUTTONS)) break; green_led(0); delay_ms(250); } while(button_is_pressed(ALL_BUTTONS)); delay_ms(100); }
/**lineCalibration***************************************** * @descrip: a function to calibrate the sensors and display * the results in the form of a bar graph. It waits for a button * to be pressed. * @param: none * @returns: BUTTON_A, BUTTON_B or BUTTON_C depending on which was * pressed after the calibration * ***********************************************************/ unsigned char lineCalibration() { const int TURN_SPEED = 40; // motor speed for turning const int TURN_STEPS = 20; // number of samples in a half turn const int SAMPLE_DELAY = 20; // ms between samples unsigned char button; // which button is pressed at the end set_motors(-TURN_SPEED, TURN_SPEED); // start turning left for (int i = 0; i < TURN_STEPS; i++) {// some number of times calibrate_line_sensors(IR_EMITTERS_ON); delay_ms(SAMPLE_DELAY); // wait 20ms } set_motors(TURN_SPEED, -TURN_SPEED); // start turning right for (int i = 0; i < 2*TURN_STEPS; i++) {// twice as many times calibrate_line_sensors(IR_EMITTERS_ON); delay_ms(SAMPLE_DELAY); // wait 20ms } set_motors(-TURN_SPEED, TURN_SPEED); // start turning left for (int i = 0; i < TURN_STEPS; i++) {// some number of times calibrate_line_sensors(IR_EMITTERS_ON); delay_ms(SAMPLE_DELAY); // wait 20ms } set_motors(0,0); // Display calibrated values as a bar graph. unsigned int sensor[5]; // place to store sensor readings while ((button = button_is_pressed(ANY_BUTTON)) == 0) {// as long as a button is not pressed unsigned int position = read_line(sensor, IR_EMITTERS_ON); // read the sensors clear(); print_long(position); // display the value on the top line display_readings(sensor); // display the bar graph on the bottom line delay_ms(100); // wait a bit } play_from_program_space(beep_button_b); // beep for B button while (button_is_pressed(button)) ; // empty loop - wait until button released delay_ms(200); // wait a bit more return button; }
void servo() { clear(); const unsigned char demuxPins[] = { }; servos_start(demuxPins, sizeof(demuxPins)); set_servo_target(0, 1300); set_servo_speed(0, 0); while (1) { if (button_is_pressed(TOP_BUTTON)) { red_led(1); green_led(0); clear(); print("Moving Left..."); set_servo_target(0, 0); _delay_ms(400); set_servo_target(0, 200); } if (button_is_pressed(BOTTOM_BUTTON)) { red_led(0); green_led(1); clear(); print("Moving Right..."); set_servo_target(0, 0); _delay_ms(400); set_servo_target(0, 1800); } } }
// This is the main function, where the code starts. All C programs // must have a main() function defined somewhere. int main() { // if any button is pressed, go into the old version of the test code if(button_is_pressed(ALL_BUTTONS)) test(); // activate the simpler test code // set up the robot initialize(); // This is the "main loop" - it will run forever. while(1) { menu_select(); } }
void wait_with_message(char *str) { play_frequency(200, 50, 14); delay_ms(75); play_frequency(300, 50, 14); play_frequency(200, 50, 14); delay_ms(75); play_frequency(300, 50, 14); lcd_goto_xy(0,0); print(str); while(!button_is_pressed(BUTTON_B)); delay_ms(500); }
void initialize() { unsigned int counter; // used as a simple timer // This must be called at the beginning of 3pi code, to set up the // sensors. We use a value of 2000 for the timeout, which // corresponds to 2000*0.4 us = 0.8 ms on our 20 MHz processor. pololu_3pi_init(2000); // Display battery voltage and wait for button press while(!button_is_pressed(BUTTON_B)) { lcd_goto_xy(0,0); print("Press B"); delay_ms(100); } // Always wait for the button to be released so that 3pi doesn't // start moving until your hand is away from it. wait_for_button_release(BUTTON_B); delay_ms(1000); // Auto-calibration: turn right and left while calibrating the // sensors. for(counter=0;counter<80;counter++) { if(counter < 20 || counter >= 60) set_motors(40,-40); else set_motors(-40,40); // This function records a set of sensor readings and keeps // track of the minimum and maximum values encountered. The // IR_EMITTERS_ON argument means that the IR LEDs will be // turned on during the reading, which is usually what you // want. calibrate_line_sensors(IR_EMITTERS_ON); // Since our counter runs to 80, the total delay will be // 80*20 = 1600 ms. delay_ms(20); } set_motors(0,0); }
// This function is called once, from main.c. void maze_solve() { // FIRST MAIN LOOP BODY // (when we find the goal, we use break; to get out of this) while(!first_main_loop()) {} set_motors(0,0); // Simplify the learned path. You can implement this! // You can either do this at the end, or during the main loop // delay(1000); // simplify_path(); // Now enter an infinite loop - we can re-run the maze as many // times as we want to. while(1) { // Beep to show that we finished the maze. // Display battery voltage and wait for button press while(!button_is_pressed(BUTTON_B)) { clear(); print("Ready to"); lcd_goto_xy(0,1); print("go again"); delay_ms(100); } initialize(); // Wait for the user to press a button... int i; for(i=0;i<path_length;i++) { // SECOND MAIN LOOP BODY second_main_loop(i); } // Follow the last segment up to the finish. follow_segment(); // Now we should be at the finish! Restart the loop. set_motors(0,0); } }
// This function comprises the main part of the motor speed update loop. // If a button press is detected, both the red and green user LEDs are // turned off, as are the motor outputs. This function also includes // a brief delay that ensures the entire loop takes the desired amount // of time. unsigned char motorUpdate(unsigned char motor, int speed) { unsigned char button; if (motor == 0) // set the desired motor to the desired speed set_m1_speed(speed); else set_m2_speed(speed); delay_ms(2); // delay here for 2 milliseconds // check if top or bottom buttons have been pressed button = button_is_pressed(TOP_BUTTON | MIDDLE_BUTTON); if (button != 0) // if so, turn off motors and LEDs, return button ID { red_led(0); green_led(0); set_motors(0, 0); } return button; }
int main() // run once, when the sketch starts { currentIdx = 0; print("Music!"); while(1) // run over and over again { // if we haven't finished playing the song and // the buzzer is ready for the next note, play the next note if (currentIdx < MELODY_LENGTH && !is_playing()) { // play note at max volume play_note(note[currentIdx], duration[currentIdx], 15); // optional LCD feedback (for fun) lcd_goto_xy(0, 1); // go to start of the second LCD line if(note[currentIdx] != 255) // display blank for rests print_long(note[currentIdx]); // print integer value of the current note print(" "); // overwrite any left over characters currentIdx++; } // Insert some other useful code here... // the melody will play normally while the rest of your code executes // as long as it executes quickly enough to keep from inserting delays // between the notes. // For example, let the top user pushbutton function as a stop/reset melody button if (button_is_pressed(TOP_BUTTON)) { stop_playing(); // silence the buzzer if (currentIdx < MELODY_LENGTH) currentIdx = MELODY_LENGTH; // terminate the melody else currentIdx = 0; // restart the melody wait_for_button_release(TOP_BUTTON); // wait here for the button to be released } } }
void initialize() { // Set PC5 as an input with internal pull-up disabled DDRC5 &= ~(1<< PORTC5); //port 5 is an input PORTC &= ~(1<< PORTC5); // Play welcome music and display a message print_from_program_space(welcome_line1); lcd_goto_xy(0,1); print_from_program_space(welcome_line2); //play_from_program_space(welcome); delay_ms(1000); clear(); print_from_program_space(name_line1); lcd_goto_xy(0,1); print_from_program_space(name_line2); delay_ms(1000); // Display battery voltage and wait for button press while(!button_is_pressed(BUTTON_B)) { clear(); print_long(read_battery_millivolts()); print("mV"); lcd_goto_xy(0,1); print("Press B"); delay_ms(100); } // Always wait for the button to be released so that 3pi doesn't // start moving until your hand is away from it. wait_for_button_release(BUTTON_B); clear(); print("Go!"); // Play music and wait for it to finish before we start driving. play_from_program_space(go); while(is_playing()); }