void setup() { pinMode(throttle_pin, INPUT); pinMode(leftright_pin, INPUT); pinMode(forwardback_pin, INPUT); pinMode(rudder_pin, INPUT); pinMode(acceldata_pin, INPUT); pinMode(accelpower_pin, OUTPUT); pinMode(led_pin, OUTPUT); pinMode(motor1_pin, OUTPUT); pinMode(motor2_pin, OUTPUT); digitalWrite(led_pin, HIGH); //turn on signal LED before timers so it comes on immediately digitalWrite(accelpower_pin, HIGH); //turn on power for accel (if ( accel is connected to chip for power) //setup interrupts for RX pins PCattachinterrupt(throttle_pin, throttle_change); PCattachinterrupt(leftright_pin, leftright_change); PCattachinterrupt(forwardback_pin, forwardback_change); PCattachinterrupt(rudder_pin, rudder_change); SetupTimer1(); //fire up timer1 (2 bytes) - accessed via TCNT1 variable configmode = 0; //we're not in configmode to start motors_off(); //make sure those motors are off... throttle = 0; //make sure throttle is off at boot //flash LED on boot for (x = 1; x <= 20; x++) { digitalWrite(led_pin, !digitalRead(led_pin)); delay(20); } /* if ( Eprom_check = 555 ) { //load config data from eprom if ( eprom_check was set to 555 tracking_comp = tracking_comp_store; if ( load_heading == 1 ) led_adjust = led_adjust_store; if ( load_heading == 1 ) led_adjust_backup = led_adjust_store; base_accel = base_accel_store; } */ }
//sets up all the pins and interrupts void setup(void) { adc_init(); //init the ADC... set_throttle_pin_as_input(); set_leftright_pin_as_input(); set_forwardback_pin_as_input(); set_accel_data_pin_as_input(); set_accelpower_pin_as_output(); set_accelpower_pin_on(); //turn on power for accel (accel is connected to chip for power) set_led_pin_as_output(); set_motor1_pin_as_output(); set_motor2_pin_as_output(); set_led_on(); //turn on signal LED before timers so it comes on immediately //enable pin change interrupt - any changes on PORTB trigger interrupt PCMSK0 = 0xFF; PCICR = 1<<PCIE0; SetupTimer1(); //fire up timer1 (2 bytes) - accessed via TCNT1 variable motors_off(); //make sure those motors are off... //flash LED on boot for (x = 1; x <= 10; x++) { toggle_led(); _delay_ms(200); } throttle = 0; //make sure throttle is off at boot }
void loop(void) { //if throttle is lower than throttle_low - or is over 100 beyond throttle_high - bot stays powered down sei(); //enable interrupts while ( throttle < throttle_low || throttle > (throttle_high + 100)) { motors_off(); //interrupt blinking if stick isn't centered (helps to verify TX is working) if ( leftright > heading_leftthresh ) _delay_ms(200); if ( leftright < heading_rightthresh ) _delay_ms(200); //sit there and flash LED toggle_led(); _delay_ms(50); } cli(); //disable interrupts - bad things seem to happen if the RC interrupts get triggered while doing math... //Are we going forward or backwards? if ( forwardback > forwardback_forwardthresh) forward = 1; else forward = 0; if ( forwardback < forwardback_backthresh) backward = 1; else backward = 0; flashy_led = 0; accel_raw_data = read_adc(); //get accel data accel_read = accel_raw_data; //move it over to single in case we want to do floating point accel_read = accel_read - base_accel; //compensate for base (2.5v) level g = accel_read * g_per_adc_increment; //convert to g's rpm = g * 89445; //calculate RPM from g's - derived from "G = 0.00001118 * r * RPM^2" rpm = rpm / radius; rpm = pow(rpm, .5); periodms = rpm / 60; //convert RPM to duration of each spin in milliseconds if (periodms == 0) periodms = 1; //must prevent any possible division by zero!!! periodms = 1 / periodms; periodms = periodms * 1000; periodms = periodms * tracking_comp; //compensate with user-set tracking adjustment alternate_motor_cycle = !alternate_motor_cycle; //alternates alternate_motor_cycle - used to balance spin if ( forward == 1 ) periodms = periodms * forward_comp; //extra compensation if going forward if ( backward == 1 ) periodms = periodms * backward_comp; //extra compensation if going backward total_fudge_factor = fudge_factor + (fudge_factor_per_ms * periodms); periodms = periodms - total_fudge_factor; //compensate for time spent doing reads / calculations delaytime_single = periodms / 2; //sets period in MS for each half of spin //converts throttle reading from remote into percentage (400 = low, 560 = high) throttle_percent = (throttle - throttle_low) + 40; //this gives a range from about 20% to 100% throttle_percent = throttle_percent / 2; if ( throttle_percent > 100 ) throttle_percent = 100; //don't got over 100% //calculates + modifies changes to heading based on input from transmitter steering_multiplier = heading_center - leftright; steering_multiplier = steering_multiplier * turn_speed; steering_multiplier = 1 - steering_multiplier; //starts with 1 as a base value (ie - if it was 0.0 it becomes 1.0 - so there's no change in heading) delaytime_single = delaytime_single * steering_multiplier; delaytime_long = delaytime_single; digitdif = delaytime_single - delaytime_long; //code that waits X microseconds to compensate for integer math digitdif = digitdif * 10; //converts digit dif to 50's of microseconds //caps on timing if going too slow or fast if ( delaytime_long > 500) delaytime_long = 500; if ( delaytime_long < 5) delaytime_long = 5; periodms = delaytime_long * 2; //we re-use periodms (full cycle length) for LED calculations - so it needs to be updated with any timing adjustments periodms_long = periodms; //set heading beacon size and location led_on = periodms * led_adjust; led_on = led_on / 100; led_off = periodms / 3; //led signal is 33% of circle led_off = led_off + led_on; if (led_off >= periodms_long ) //if led_off is "later" or at end of cycle - shift led_off behind by one cycle { led_off = led_off - periodms_long; } if ( led_off < 1 ) led_off = led_off + periodms_long; if ( g > max_g && throttle_percent > 20 ) throttle_percent = 20; //if we're over max RPM for translation - reduce throttle //throttling full_power_spin = 0; if ( rpm < min_rpm ) full_power_spin = 1; //if we're under the minimum RPM for translation - do the full power spin! if ( rpm > max_allowed_rpm ) throttle_percent = 6; //if we're over max RPM for translation - reduce power //if throttle is at or over 50% throttle - adjust time spent in braking if ( throttle_percent > 50 ) { flashy_led = 1; //flash the LED to indicate we're in fast mode braking_length = delaytime_long * 25; braking_length = braking_length / throttle_percent; begin_brake = delaytime_long / 2; begin_brake = begin_brake - braking_length; end_brake = delaytime_long / 2; end_brake = end_brake + braking_length; if ( begin_brake < 1 ) begin_brake = 1; //make sure begin_brake isn't getting set to 0 power_kill_part1 = 0; //power_kill not used if throttle over 50% power_kill_part2 = delaytime_long; } if ( throttle_percent <= 50 ) //if throttle under 50% - kill the motors for a portion of each spin { begin_brake = 1; end_brake = delaytime_long; power_kill_length = 50 - throttle_percent; //set time in each cycle to cut power (throttling) power_kill_length = power_kill_length * delaytime_long; power_kill_length = power_kill_length / 150; power_kill_part1 = power_kill_length; power_kill_part2 = delaytime_long - power_kill_length; } if ( full_power_spin == 1 ) //if we're actually doing full power this spin (no translation) - ignore any calculations / reset variables { end_brake = 1; begin_brake = 0; power_kill_part1 = 0; power_kill_part2 = delaytime_long; } sei(); //enable interrupts - out of all the critical stuff led_ref = 0; //Do translational drift driving //Cycle 1 ("front" 180 degrees of spin) for (x = 1; x <= delaytime_long; x++) { motors_left(); //start off under full power led_ref = led_ref + 1; if ( x >= begin_brake && x < end_brake ) //switch to single motor as soon as entering braking cycle { //if sitting still if ( forward == 0 && backward == 0 ) { if ( alternate_motor_cycle == 0 ) motor1_on(); //alternates which motor is used each cycle if ( sitting still if ( alternate_motor_cycle == 1 ) motor2_on(); //this prevents unwanted "translation" due to any imbalances } //if ( going forward / back set motors appropriately (this is "where it happens") if ( forward == 1 ) motor1_on(); if ( backward == 1 ) motor2_on(); } if ( x >= end_brake ) motors_left(); //if we hit end of brake cycle - go to full power if ( x < power_kill_part1 ) motors_off(); //if th rottle is less that 100% - kill power at appropriate time if ( x > power_kill_part2 ) motors_off(); //if throttle is less that 100% - kill power at appropriate time if ( led_ref == led_on ) led_is_on_now = 1; //turn on heading led if ( led_ref == led_off ) led_is_on_now = 0; //turn off heading led if ( led_is_on_now == 1 ) { //flash the LED if we're in flashy mode - otherwise it's just on if ( flashy_led == 1 ) toggle_led(); else set_led_on(); } if ( led_is_on_now == 0 ) set_led_off(); _delay_ms(1); } for (delay_loop = 1; delay_loop < digitdif; delay_loop++) { //in theory we should wait 25 microseconds - but I'm assuming the overhead takes up 1us wait24us(); } //Cycle 2 (back 180 degrees of spin) - same as above except motors are reversed (there are some moderately-good reasons this isn't a subroutine) for (x = 1; x <= delaytime_long; x++) { motors_left(); //start off under full power led_ref = led_ref + 1; if ( x >= begin_brake && x < end_brake ) //switch to single motor as soon as entering braking cycle { //if sitting still if ( forward == 0 && backward == 0 ) { if ( alternate_motor_cycle == 0 ) motor2_on(); //alternates which motor is used each cycle if ( sitting still if ( alternate_motor_cycle == 1 ) motor1_on(); //this prevents unwanted "translation" due to any imbalances } //if ( going forward / back set motors appropriately (this is "where it happens") if ( forward == 1 ) motor2_on(); if ( backward == 1 ) motor1_on(); } if ( x >= end_brake ) motors_left(); //if we hit end of brake cycle - go to full power if ( x < power_kill_part1 ) motors_off(); //if throttle is less that 100% - kill power at appropriate time if ( x > power_kill_part2 ) motors_off(); //if throttle is less that 100% - kill power at appropriate time if ( led_ref == led_on ) led_is_on_now = 1; //turn on heading led if ( led_ref == led_off ) led_is_on_now = 0; //turn off heading led if ( led_is_on_now == 1 ) { //flash the LED if we're in flashy mode - otherwise it's just on if ( flashy_led == 1 ) toggle_led(); else set_led_on(); } if ( led_is_on_now == 0 ) set_led_off(); _delay_ms(1); } for (delay_loop = 1; delay_loop < digitdif; delay_loop++) { //in theory we should wait 25 microseconds - but I'm assuming the overhead takes up 1us wait24us(); } }
void loop() { //if throttle is lower than throttle_low - or is over 100 beyond throttle_high - bot stays powered down while ( throttle < throttle_low || throttle > (throttle_high + 100)) { motors_off(); //interrupt blinking if ( stick isn//t centered //used to help debug if ( center is off if ( leftright > heading_rightthresh ) delay(200); if ( leftright < heading_leftthresh ) delay(200); //if ( stick is pulled back (and not in configmode) - flash out highest RPM if ( forwardback < forwardback_backthresh && configmode == 0 ) { digitalWrite(led_pin, LOW); delay(500); for (y = 1; y <= max_rpm; y = y + 100) { digitalWrite(led_pin, HIGH); delay(100); digitalWrite(led_pin, LOW); delay(300); if ( throttle >= throttle_low ) y = max_rpm; //abort if throttle gets pushed up } if ( throttle < throttle_low ) delay(2000); //only wait if throttle is still low } //if ( stick is upper right - ) { toggle configmode if ( forwardback > forwardback_forwardthresh && leftright > rudder_leftthresh ) { //wait a bit to make sure stick is being held... delay(1400); if ( forwardback > forwardback_forwardthresh && leftright > rudder_leftthresh ) { if ( configmode == 0 ) { configmode = 1; //assign base_accel accel_raw_data = analogRead(acceldata_pin); base_accel = accel_raw_data; } else { configmode = 0; /* //write out new data to ROM tracking_comp_store = tracking_comp; //write out config data to ROM led_adjust_store = led_adjust; base_accel_store = base_accel; Eprom_check = 555; //write out arbitrary value to validate tracking_comp was written out */ } delay(500); } } if ( forwardback < forwardback_backthresh && leftright < rudder_rightthresh && configmode == 1 ) { ////if ( stick is held to back left while ( in config mode //reset heading adjustment //wait a bit to make sure stick is being held... delay(1400); if ( forwardback < forwardback_backthresh && leftright < rudder_rightthresh && configmode == 1 ) { tracking_comp = 1; //reset heading adjustment for ( x = 1; x <= 70; x++) { digitalWrite(led_pin, !digitalRead(led_pin)); delay(20); } digitalWrite(led_pin, LOW); delay(1000); } } //sit there and flash LED digitalWrite(led_pin, LOW); delay(50); if ( configmode == 1 ) { for ( x = 1; x <=10; x++) { delay(30); digitalWrite(led_pin, !digitalRead(led_pin)); } digitalWrite(led_pin, LOW); delay(150); } digitalWrite(led_pin, HIGH); delay(50); } //safety //if we haven't gotten the throttle reading in 5 cycles - set throttle to 0 got_throttle = got_throttle + 1; if ( got_throttle > 100 ) got_throttle = 100; if ( got_throttle > 5) throttle = 0; //reset max RPM max_rpm = 0; cli(); //disable interrupts - bad things seem to happen if the RC interrupts get triggered while doing math... //Are we going forward or backwards? if ( forwardback > forwardback_forwardthresh) { forward = 1; } else { forward = 0; } if ( forwardback < forwardback_backthresh) { backward = 1; } else { backward = 0; } flashy_led = 0; accel_raw_data = analogRead(acceldata_pin); //get accel data accel_read = accel_raw_data; //move it over to single in case we want to do floating point accel_read = accel_read - base_accel; //compensate for base (2.5v) level g = accel_read * g_per_adc_increment; //convert to g's rpm = 28.45 * radius; //calculate RPM from g's - rpm = (g/(28.45* radius ))^0.5 *1000 if (rpm == 0) rpm = 1; //must prevent any possible division by zero!!! rpm = g / rpm; rpm = pow(rpm, .5); rpm = rpm * 1000; if ( rpm > max_rpm ) max_rpm = rpm; periodms = rpm / 60; //convert RPM to duration of each spin in milliseconds if (periodms == 0) periodms = 1; //must prevent any possible division by zero!!! periodms = 1 / periodms; periodms = periodms * 1000; periodms = periodms * tracking_comp; //compensate with user-set tracking adjustment //test! periodms = 30; if ( alternate_motor_cycle == 1 ) { alternate_motor_cycle = 2; } else { alternate_motor_cycle = 1; } //alternates alternate_motor_cycle - used to balance spin //strafing if ( strafing_is_off == 0 ) //don't do strafing stuff if it's off { if ( no_led == 1 ) //skip straffing for one cycle if we had a change last time (setting no_led to 1) { no_led = 0; } else { no_led = 0; //make sure LED is recalc on unless we decide to turn it off led_adjust = led_adjust_backup; if ( rudder > rudder_leftthresh ) { if ( left_strafe == 0 ) { periodms = periodms * 1.25; //one time adjustment to turn 90 degrees no_led = 1; // led recalc off this cycle - otherwise will look glitchy } led_adjust = led_adjust - 25; left_strafe = 1; forward = 1; backward = 0; } else { if ( left_strafe == 1 ) { periodms = periodms * .75; //correct for prior straffing no_led = 1; // led recalc off this cycle - otherwise will look glitchy } left_strafe = 0; } if ( rudder < rudder_rightthresh ) { if ( right_strafe == 0 ) { periodms = periodms * .75; //one time adjustment to turn 90 degrees no_led = 1; // led recalc off this cycle - otherwise will look glitchy } led_adjust = led_adjust + 25; right_strafe = 1; forward = 1; backward = 0; } else { if ( right_strafe == 1 ) { periodms = periodms * 1.25; //correct for prior straffing no_led = 1; // led recalc off this cycle - otherwise will look glitchy } right_strafe = 0; } } } if ( forward == 1 ) periodms = periodms * forward_comp; //extra compensation if going forward if ( backward == 1 ) periodms = periodms * backward_comp; //extra compensation if going backward periodms = periodms - fudge_factor; //compensate for time spent doing reads / calculations //make sure led_adjust didn't get set above or below limits if ( led_adjust < 1 ) led_adjust = led_adjust + 100; if ( led_adjust > 100 ) led_adjust = led_adjust - 100; delaytime_single = periodms / 2; //sets period in MS for each half of spin //converts throttle reading from remote into percentage (400 = low, 560 = high) throttle_percent = (throttle - throttle_low) + 40; //this gives a range from about 20% to 100% throttle_percent = throttle_percent / 2; if ( throttle_percent > 100 ) throttle_percent = 100; //don't got over 100% //driver moves stick left and right until the bot tracks correctly //data is written into eprom next time the robot spins down in_tracking_adjust = 0; //tracking adjustment - if throttle is neither forward or back and throttle is under 50% go into tracking adjustment mode if ( configmode == 1 && forward == 0 && backward == 0 && throttle_percent < 50 ) { in_tracking_adjust = 1; flashy_led = 1; //to indicate heading adjust most - LED flashing is on if ( leftright > heading_rightthresh || leftright < heading_leftthresh ) { flashy_led = 0; //turn off flashing to show is actively being adjusted add_delay = heading_center - leftright; add_delay = add_delay * delaytime_single; // add_delay = pow(add_delay , exponential); //disabled - need to fix problem with negative values add_delay = add_delay / 1400000; //(was 14000000) tracking_comp = tracking_comp + add_delay; } } //adjust led direction if throttle is over 50% and in configmode + not going back / forward if ( configmode == 1 && forward == 0 && backward == 0 && throttle_percent >= 50 ) { in_tracking_adjust = 1; flashy_led = 0; //to indicate LED adjust most - LED flashing is off if ( leftright < heading_leftthresh ) { led_adjust = led_adjust + 1; flashy_led = 1; //turn on flashing to indicate change } if ( leftright > heading_rightthresh ) { led_adjust = led_adjust - 1; flashy_led = 1; //turn on flashing to indicate change } if ( led_adjust < 1 ) led_adjust = 100; //"wrap" around when adjusting LED direction if ( led_adjust > 100 ) led_adjust = 1; backward = 0; //don//t really go backwards led_adjust_backup = led_adjust; } if ( in_tracking_adjust == 0 ) { //don't do normal heading adjustments if we're doing tracking adjustments //normal drive heading change //this code adds or subtracts a percentage of delaytime based on the heading data from the remote //don't do if in configmode if ( leftright > heading_rightthresh || leftright < heading_leftthresh ) { add_delay = heading_center - leftright; add_delay = add_delay * delaytime_single; //add_delay = Pow(add_delay , exponential); //disabled - need to fix problem with negative values add_delay = add_delay / 700; //(was 7700) delaytime_single = delaytime_single + add_delay; } } if ( configmode == 1) throttle_percent = 50; //ignore throttle if in configmode delaytime_long = delaytime_single; digitdif = delaytime_single - delaytime_long; //code that waits X microseconds to compensate for integer math digitdif = digitdif * 10; //converts digit dif ( to 50's of microseconds for (delay_loop =1; delay_loop <= digitdif; delay_loop++) { wait25us(); } //caps on timing if going too slow or fast if ( delaytime_long > 500) delaytime_long = 500; if ( delaytime_long < 5) delaytime_long = 5; periodms = delaytime_long * 2; //we re-use periodms (full cycle length) for LED calculations - so it needs to be updated with any timing adjustments periodms_long = periodms; //set heading beacon size and location led_on = periodms * led_adjust; led_on = led_on / 100; led_off = periodms / 3; //led signal is 33% of circle led_off = led_off + led_on; if (led_off >= periodms_long ) //if led_off is "later" or at end of cycle - shift led_off behind by one cycle { led_off = led_off - periodms_long; } if ( led_off < 1 ) led_off = led_off + periodms_long; tail_start = periodms_long * 17; //code to calculate position of LED tail tail_start = tail_start / 60; tail_start = tail_start + led_off; tail_end = periodms_long * 6; tail_end = tail_end / 60; tail_end = tail_end + tail_start; if ( tail_start >= periodms_long ) { tail_start = tail_start - periodms_long; } if ( tail_end >= periodms_long ) { tail_end = tail_end - periodms_long; } if ( g > max_g && throttle_percent > 20 ) throttle_percent = 20; //if we're over max RPM for translation - reduce throttle //throttling if ( throttle_percent > throttle_percent_max ) throttle_percent = throttle_percent_max; if ( throttle_percent < throttle_percent_min ) throttle_percent = throttle_percent_min; full_power_spin = 0; cut_power = 0; if ( rpm < min_rpm ) full_power_spin = 1; //if we're under the minimum RPM for translation - do the full power spin! if ( rpm > max_allowed_rpm ) throttle_percent = 6; //if we're over max RPM for translation - reduce power //if throttle is at or over 50% throttle - adjust time spent in braking if ( throttle_percent > 50 ) { flashy_led = 1; //flash the LED to indicate we're in fast mode braking_length = delaytime_long * 25; //original braking_length = braking_length / throttle_percent; begin_brake = delaytime_long / 2; begin_brake = begin_brake - braking_length; end_brake = delaytime_long / 2; end_brake = end_brake + braking_length; if ( begin_brake < 1 ) { begin_brake = 1; //make sure begin_brake isn//t getting set to 0 power_kill_part1 = 0; //power_kill not used if throttle over 50% power_kill_part2 = delaytime_long; } } if ( throttle_percent <= 50 ) //if throttle under 50% - kill the motors for a portion of each spin { begin_brake = 1; end_brake = delaytime_long; power_kill_length = 50 - throttle_percent; //set time in each cycle to cut power (throttling) power_kill_length = power_kill_length * delaytime_long; power_kill_length = power_kill_length / 150; power_kill_part1 = power_kill_length; power_kill_part2 = delaytime_long - power_kill_length; } if ( no_led == 1 ) //kill tail if initiating strafe { tail_start = 0; tail_end = 0; } sei(); //enable interrupts - out of all the critical stuff if ( full_power_spin == 1 ) //reset variables for full power spin { end_brake = 1; begin_brake = 0; power_kill_part1 = 0; power_kill_part2 = delaytime_long; } //Do translational drift driving //Cycle 1 (front 180 degrees of spin) led_ref = 0; for (x = 1; x <= delaytime_long; x++) { motors_left(); //start off under full power led_ref = led_ref + 1; if ( x >= begin_brake && x < end_brake ) //switch to single motor as soon as entering braking cycle { //if sitting still if ( forward == 0 && backward == 0 ) { if ( alternate_motor_cycle == 1 ) motor1_on(); //alternates which motor is used each cycle if ( sitting still if ( alternate_motor_cycle == 2 ) motor2_on(); //this prevents unwanted "translation" due to any imbalances } //if ( going forward / back set motors appropriately (this is "where it happens") if ( forward == 1 ) motor1_on(); if ( backward == 1 ) motor2_on(); } if ( x >= end_brake ) motors_left; //if ( we hit end of brake cycle - go to full power if ( x < power_kill_part1 ) motors_off; //if ( throttle is less that 100% - kill power at appropriate time if ( x > power_kill_part2 ) motors_off; //if ( throttle is less that 100% - kill power at appropriate time if ( cut_power == 1 ) motors_off; //if ( this is a no-power spin if ( led_ref == led_on ) led_is_on_now = 1; //turn on heading led if ( led_ref == led_off ) led_is_on_now = 0; //turn off heading led if ( no_led == 1 ) led_is_on_now = 0; if ( led_is_on_now == 1 ) { if ( flashy_led == 1 ) { digitalWrite(led_pin, !digitalRead(led_pin)); } else { digitalWrite(led_pin, HIGH); } } if ( led_is_on_now == 0 ) digitalWrite(led_pin, LOW); turn_on_tail; // delay_1_ms; delayMicroseconds(1250); } for (delay_loop = 1; delay_loop < digitdif; delay_loop++) { //extra delay to compensate for integer math (other half done earlier) wait25us(); } //Cycle 2 (back 180 degrees of spin) - pretty much everything works the same... for (x = 1; x <= delaytime_long; x++) //each loop is 1ms (delaytime is length of 180 degrees of cycle) { motors_left; //start off under full power led_ref = led_ref + 1; if ( x >= begin_brake && x < end_brake ) { //switch to single motor as soon as entering braking cycle if ( forward = 0 && backward == 0 ) //if ( sitting still { if ( dont_alternate_motors == 1 ) //swap motors once per rotation when not moving { if ( alternate_motor_cycle == 1 ) motor1_on; if ( alternate_motor_cycle == 2 ) motor2_on; else if ( alternate_motor_cycle == 1 ) motor2_on; //alternates which motor is used each cycle if sitting still if ( alternate_motor_cycle == 2 ) motor1_on; //this prevents unwanted "translation" due to any imbalances } //if just using one wheel - this "pulses" it } //if ( going forward / back set motors appropriately (this is "where it happens") if ( forward = 1 ) motor2_on; if ( backward = 1 ) motor1_on; } if ( x >= end_brake ) motors_left; //if we hit end of brake cycle - go to full power if ( x < power_kill_part1 ) motors_off; //if throttle is less that 100% - kill power at appropriate time if ( x > power_kill_part2 ) motors_off; //if throttle is less that 100% - kill power at appropriate time if ( cut_power == 1 ) motors_off; //if this is a no-power spin if ( led_ref == led_on ) led_is_on_now = 1; //turn on heading led if ( led_ref == led_off ) led_is_on_now = 0; //turn off heading led if ( no_led == 1 ) led_is_on_now = 0; if ( led_is_on_now == 1 ) { if ( flashy_led == 1 ) { digitalWrite(led_pin, !digitalRead(led_pin)); } else { digitalWrite(led_pin, HIGH); } } if ( led_is_on_now == 0 ) digitalWrite(led_pin, LOW); turn_on_tail; // delay_1_ms; delayMicroseconds(1250); } }
void evalOpcode(unsigned char opcode) { int i; int16 opr1, opr2, opr3; unsigned int16 genPurpose = 0; if (opcode & 0b10000000) { genPurpose = gblMemPtr + 2; gblMemPtr = ((((unsigned int16)opcode & 0b00111111) << 8) + 2*fetchNextOpcode()); opr1 = fetchNextOpcode(); if (opcode & 0b01000000) { for (i = 0; i < (opr1 + 3); i++) { inputPop(); } } for (i = 0; i < opr1; i++) { inputPush (stkPop()); } inputPush (gblStkPtr); inputPush (genPurpose); inputPush(gblInputStkPtr - (opr1 + 2)); return; } switch (opcode) { case CODE_END: gblLogoIsRunning = 0; output_low (RUN_LED); // clear thes variables just in case. gblLoopAddress = 0; gblRepeatCount = 0; break; case NUM8: int8 Hi3 = fetchNextOpcode(); stkPush(Hi3); break; case NUM16: int8 Hi2 = fetchNextOpcode(); int8 Lo2 = fetchNextOpcode(); unsigned int16 teste4 = Hi2 << 8; teste4 += Lo2; stkPush (teste4); break; case LIST: stkPush(gblMemPtr + 2); //incremento de 2 em 2 gblMemPtr += (2 * fetchNextOpcode()); break; case EOL: genPurpose = stkPop(); if (genPurpose > gblMemPtr) { //printf(usb_cdc_putc,"genPurpose >>>> gblMemPtr"); gblMemPtr = genPurpose; } else { //printf(usb_cdc_putc,"genPurpose <<<< gblMemPtr"); gblMemPtr = genPurpose; gblRepeatCount = stkPop(); // repeat count //printf(usb_cdc_putc," gblRepeatCount %Lu \n",genPurpose); if (gblRepeatCount > 1) gblRepeatCount--; if (gblRepeatCount != 1) { stkPush (gblRepeatCount); stkPush (gblMemPtr); } } break; case EOLR: if (stkPop()) { // if condition is true stkPop(); // throw away the loop address gblMemPtr = stkPop(); // fetch the next command address } else { // if condition if false -> keep on looping. gblMemPtr = stkPop(); stkPush (gblMemPtr); delay_ms(5); // this prevents the waituntil loop to execute too rapidly // which has proven to cause some problems when reading sensor values. } break; case LTHING: genPurpose = 2 * fetchNextOpcode(); // index of the input variable opr1 = inputPop(); // base address in the input stack inputPush(opr1); // push the base address back to the stack. stkPush (gblInputStack[opr1 + genPurpose]); break; case STOP: case OUTPUT: if (opcode == OUTPUT){ genPurpose = stkPop(); // this is the output value } opr1 = inputPop(); // this is the proc-input stack base address gblMemPtr = inputPop(); // this is the return address opr2 = inputPop(); // this is the data stack index; // remove any remaining data that belongs to the current procedure from the data stack // Usually this is important for the STOP opcode. while (gblStkPtr > opr2){ stkPop(); } // remove the procedure inputs from the input stack while (gblInputStkPtr > opr1){ inputPop(); } // Output will push the output to the stack if (opcode == OUTPUT){ stkPush (genPurpose); } break; case REPEAT: gblLoopAddress = stkPop(); gblRepeatCount = stkPop(); // these will be poped by EOL stkPush (gblMemPtr); // address after repeat is complete if (gblRepeatCount > 1) { stkPush (gblRepeatCount); stkPush (gblLoopAddress); // address while still repeating gblMemPtr = gblLoopAddress; } else if (gblRepeatCount == 1) { gblMemPtr = gblLoopAddress; } else { // if loop count = 0 gblMemPtr = stkPop(); } break; case COND_IF: opr1 = stkPop(); // if true pointer address opr2 = stkPop(); // condition if (opr2) { stkPush(gblMemPtr); gblMemPtr = opr1; } break; case COND_IFELSE: opr1 = stkPop(); // if false pointer address opr2 = stkPop(); // if true pointer address opr3 = stkPop(); // condition stkPush(gblMemPtr); if (opr3) { gblMemPtr = opr2; } else { gblMemPtr = opr1; } break; case BEEP: beep(); break; case WAITUNTIL: gblLoopAddress = stkPop(); // these will be poped by EOLR stkPush(gblMemPtr); // address after repeat is complete stkPush (gblLoopAddress); // address while still repeating gblMemPtr = gblLoopAddress; break; case LOOP: gblLoopAddress = stkPop(); // the begining of loop gblRepeatCount = 0; // disable this counter (loop forever) stkPush(0); // this distinguishes LOOP from Repeat. (see EOL) stkPush(gblLoopAddress); // push loop address back into the stack // so that EOL will loop gblMemPtr = gblLoopAddress; break; case WAIT: gblWaitCounter = stkPop() * 4; break; case TIMER: stkPush(gblTimer); // gblTimer increases every 1ms. See in RTCC interrupt break; case RESETT: gblTimer = 0; break; case SEND: genPurpose = stkPop(); break; case IR: stkPush (gblMostRecentlyReceivedByte); gblNewByteHasArrivedFlag = 0; break; case NEWIR: stkPush (gblNewByteHasArrivedFlag); break; case RANDOM: stkPush (rand()); break; case OP_PLUS: case OP_MINUS: case OP_MULTIPLY: case OP_DIVISION: case OP_REMAINDER: case OP_EQUAL: case OP_GREATER: case OP_LESS: case OP_AND: case OP_OR: case OP_XOR: opr2=stkPop(); // second operand opr1=stkPop();// first operand switch (opcode) { case OP_PLUS: opr1+=opr2; break; case OP_MINUS: opr1-=opr2; break; case OP_MULTIPLY: opr1*=opr2; break; case OP_DIVISION: opr1/=opr2; break; case OP_REMAINDER: opr1%=opr2; break; case OP_EQUAL: opr1=(opr1==opr2); break; case OP_GREATER: opr1=(opr1>opr2); break; case OP_LESS: opr1=(opr1<opr2); break; case OP_AND: opr1=(opr1&&opr2); break; case OP_OR: opr1=(opr1||opr2); break; case OP_XOR: opr1=(opr1^opr2); break; }; stkPush(opr1); break; case OP_NOT: stkPush(!stkPop()); break; case SETGLOBAL: genPurpose = stkPop();// this is the value globalVariables[stkPop()] = genPurpose; break; case GETGLOBAL: stkPush(globalVariables[stkPop()]); break; case ASET: opr2 = stkPop();// this is the value to be stored opr1 = stkPop() * 2;// this is the array index. Each entry is two bytes wide. genPurpose = ARRAY_BASE_ADDRESS + stkPop();// this is the base address of the array. flashSetWordAddress(genPurpose + opr1); flashWrite(opr2); break; case AGET: opr1 = stkPop() * 2;// this is the array index. Each entry is two bytes wide. genPurpose = ARRAY_BASE_ADDRESS + stkPop();// this is the base address of the array. opr2 = read_program_eeprom(genPurpose + opr1); stkPush(opr2); break; case RECORD: genPurpose = stkPop(); // PCM parts (14 bit PICs like the 16F877) uses an external EEPROM for data Logging storage flashSetWordAddress(RECORD_BASE_ADDRESS + gblRecordPtr++); flashWrite(genPurpose); // save current record pointer location flashSetWordAddress(MEM_PTR_LOG_BASE_ADDRESS); flashWrite(gblRecordPtr); break; case RECALL: genPurpose = read_program_eeprom(RECORD_BASE_ADDRESS + gblRecordPtr++); stkPush(genPurpose); break; case RESETDP: gblRecordPtr = 0; break; case SETDP: gblRecordPtr = stkPop() * 2; break; case ERASE: opr1 = stkPop() * 2; for (genPurpose=0; genPurpose<opr1; genPurpose++) { flashSetWordAddress(RECORD_BASE_ADDRESS + genPurpose); flashWrite(0); } gblRecordPtr = 0; break; case OPC_MOTORS_OFF: motors_off(); break; case OPC_MOTORS_THATWAY: motors_that_way(); break; case OPC_MOTORS_THISWAY: motors_this_way(); break; case OPC_MOTORS_REVERT: motors_reverse(); break; case OPC_MOTORS_ON_FOR: case OPC_MOTORS_ON: motors_on(); if (opcode == OPC_MOTORS_ON_FOR) { set_on_for(stkPop()*4); } break; case OPC_MOTORS_POWER: motors_power(stkPop()); break; case OPC_MOTORS_ANGLE: motors_angle(stkPop()); break; case OPC_ACTIVATE_MOTORS: mtrsActive = stkPop(); break; case REALLY_STOP: start_stop_logo_machine = 1; break; case EB: stkPush(read_program_eeprom(stkPop())); break; case DB: opr1 = stkPop(); opr2 = stkPop(); flashSetWordAddress(opr2); flashWrite(opr1); break; case LOW_BYTE: stkPush(stkPop() & 0xff); break; case HIGH_BYTE: stkPush(stkPop() >> 8); break; case SENSOR1: case SENSOR2: case SENSOR3: case SENSOR4: case SENSOR5: case SENSOR6: case SENSOR7: case SENSOR8: if (opcode < SENSOR3) { i = opcode - SENSOR1; } else { i = opcode - SENSOR3 + 2; } stkPush(readSensor(i)); break; case SWITCH1: case SWITCH2: case SWITCH3: case SWITCH4: case SWITCH5: case SWITCH6: case SWITCH7: case SWITCH8: if (opcode < SWITCH3) { i = opcode - SWITCH1; } else { i = opcode - SWITCH3 + 2; } stkPush(readSensor(i)>>9); break; case ULED_ON: output_high(USER_LED); break; case ULED_OFF: output_low(USER_LED); break; case CL_I2C_START: i2c_start(); break; case CL_I2C_STOP: i2c_stop(); break; case CL_I2C_WRITE: i2c_write(stkPop()); break; case CL_I2C_READ: stkPush(i2c_read(stkPop())); break; default: start_stop_logo_machine = 1; break; }; }