/** * Main loop * * @copyright 2012 Institute Automation of Complex Power Systems (ACS), RWTH Aachen University * @license http://www.gnu.org/licenses/gpl.txt GNU Public License * @author Steffen Vogel */ #include #include #include #include #include #include #include #include #include "lcd.h" #include "rotary.h" #include "adc.h" #include "pid.h" #include "uart.h" #define DISPLAY_MODI 11 #define BAUDRATE 57600 #define MAGIC_BYTE 0xca #define MAGIC_LEN 16 const char *mode_str[] = { "Stop ", "Auto ", "Manual", "UART " }; const char *display_str[] = { NULL, "PWM Motor", "PWM Servo", "PID Drive: P", "PID Drive: I", "PID Stering: P", "PID Stering: I", "ADC Inductor: L", "ADC Inductor: R", "ADC Batt: Logic", "ADC Batt: Drive" }; enum channel { STERING_LEFT, STERING_RIGHT, BATT_LOGIC, BATT_DRIVE }; enum state { HALT, AUTO, MANUAL }; enum menu { OVERVIEW, PWM_DRIVE, PWM_STERING, PID_DRIVE_P, PID_DRIVE_I, PID_STERING_P, PID_STERING_I, ADC_STERING_LEFT, ADC_STERING_RIGHT, ADC_BATT_LOGIC, ADC_BATT_DRIVE, }; enum cmd { SET_STATUS, /* Mode, Display */ SET_PWM, /* Drive & Stering */ SET_PID, /* Controller state */ GET_PID /* Controller state */ }; // EEPROM int16_t pid_drive_p_ee EEMEM = 0; int16_t pid_drive_i_ee EEMEM = 0; int16_t pid_stering_p_ee EEMEM = 39; int16_t pid_stering_i_ee EEMEM = 0; int16_t pwm_drive_ee EEMEM = 0; int16_t pwm_stering_ee EEMEM = 0; // Globale Daten int16_t pwm_stering; int16_t pwm_drive; int8_t out_stering; uint8_t out_drive; int16_t adc_stering_left; int16_t adc_stering_right; int16_t adc_batt_logic; int16_t adc_batt_drive; uint8_t speed; uint16_t speed_cnt; bool speed_ovf = true; struct pid pid_drive; struct pid pid_stering; enum state mode; enum menu display; bool edit = false; bool redraw = true; /** * Parameter editieren */ void parameter_edit(int16_t *parameter, int16_t *parameter_ee, enum taster input) { switch (input) { case DGB_SW: // Editier-Modus togglen edit = !edit; break; case DGB_CW: // Wert ändern if (edit) *parameter = *parameter + 1; break; case DGB_CCW: // Wert ändern if (edit) *parameter = *parameter - 1; break; case SW_GRUEN: // Laden aus EEPROM *parameter = eeprom_read_word((uint16_t *) parameter_ee); break; case SW_BLAU: // Speichern im EEPROM eeprom_write_word((uint16_t *) parameter_ee, *parameter); break; } } /** * Startsequenz */ void greeter() { // UART uart_puts("Donaudampfschiff\r\n"); // LCD lcd_clear(); lcd_string("Donaudampfschiff"); lcd_setcursor(0, 1); lcd_string(" 4.Sem.Proj. "); _delay_ms(1500); lcd_clear(); } /** * Initialize Timers and IO Ports */ void init() { DDRB = 0xff; DDRC = 0xff; DDRD = 0b11111011; // Geschwindigkeitssensor // Falling Edge on INT0 triggers Interrupt MCUCR = (1<>1) + (( pwm_drive * (128 - abs(out_stering))) >> 8); } break; case HALT: default: out_drive = 0; out_stering = 0; } /** * Servo Tastgrad * Links 2.1ms => 4200 * Mitte 1.5ms => 3000 * Rechts 0.9ms => 1800 */ OCR1A = 3000 + (out_stering * 9); OCR2 = out_drive; } /** * Interupt Subroutine für ADC */ ISR(ADC_vect) { enum channel ch = ADMUX & ADMUX_MASK; switch (ch) { case STERING_LEFT: adc_stering_left = ADC; break; case STERING_RIGHT: adc_stering_right = ADC; break; case BATT_LOGIC: adc_batt_logic = ADC; break; case BATT_DRIVE: adc_batt_drive = ADC; break; } ADMUX = (ADMUX & ~ADMUX_MASK); ADMUX |= (ch >= 1) ? 0 : ++ch; ADCSRA |= (1<