Changeset 506
- Timestamp:
- 05/27/09 00:35:35 (3 years ago)
- Location:
- trunk/electronics/avr/2008-mcc
- Files:
-
- 5 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/electronics/avr/2008-mcc/main.m4
r416 r506 94 94 95 95 96 void delay_ms(uint16_t t) { 96 void delay_ms(uint16_t t) 97 { 97 98 while (t--) _delay_ms(1); 98 99 } 100 101 void calibrate() 102 { 103 pwm_set(0); 104 delay_ms(250); 105 pwm_set(255); 106 delay_ms(1000); 107 pwm_set(-255); 108 delay_ms(1000); 109 pwm_set(0); 110 delay_ms(5000); 111 } 112 99 113 100 114 int main() … … 109 123 110 124 pwm_init(); 125 pwm_set(0); 126 127 //while (1) 128 // calibrate(); 129 130 111 131 // spi_init(); 112 132 // mcp_init(Loopback, msg_handler1); -
trunk/electronics/avr/2008-mcc/mkfile
r369 r506 1 1 <$RHRTELEC/avr/mkhdr 2 2 3 MCU_SPEED=20000000 3 MCU_SPEED=20000000ULL 4 4 TARG=pid 5 5 OFILES=\ -
trunk/electronics/avr/2008-mcc/pid.m4
r432 r506 33 33 int16_t set_point; 34 34 int16_t ticks; 35 int16_t distance;36 35 uint8_t disabled; 36 int8_t enc_inc; 37 38 #define MAX_I_TERM (INT16_MAX-1) 39 #define PWM_MAX 255 37 40 38 41 /* All gains scaled by 128 */ … … 50 53 int16_t error_sum; 51 54 int16_t last_error; 55 int16_t max_error; 56 int16_t max_error_sum; 52 57 53 58 } PID; … … 94 99 PID.Ki = nKi; 95 100 PID.Kd = nKd; 101 PID.max_error = INT16_MAX / (nKp + 1); 102 PID.max_error_sum = MAX_I_TERM / (nKi + 1); 103 PID.error_sum = 0; 96 104 } 97 105 … … 131 139 PIN_INPUT(ENCA); 132 140 PIN_INPUT(ENCB); 133 PIN_INPUT(KILL); 134 141 PIN_INPUT(ENCPOL); 142 PIN_INPUT(DISI); 143 PIN_OUTPUT(DIS); 144 PIN_SET(DIS); 145 135 146 pid_disable(); 136 //pid_set_gain(190, 17, 120); 147 148 if (PIN_LEVEL(ENCPOL)) 149 enc_inc = 1; 150 else 151 enc_inc = -1; 152 137 153 /* Interrupt on rising edge */ 138 154 EICRA |= 0b00001100; 139 155 EIMSK |= 0b00000010; 140 156 141 PID.Kp = eeprom_read_word((uint16_t *)EAkp); 142 PID.Ki = eeprom_read_word((uint16_t *)EAki); 143 PID.Kd = eeprom_read_word((uint16_t *)EAkd); 157 pid_set_gain(eeprom_read_word((uint16_t *)EAkp), eeprom_read_word((uint16_t *)EAki), eeprom_read_word((uint16_t *)EAkd)); 158 PID.error_sum = 0; 144 159 145 160 /* Use Timer0 to trigger PID update … … 150 165 #if PIDUPDATE == PID50HZ 151 166 TCCR0B = 0b00000101; 152 OCR0A = 194; 167 OCR0A = 194; // Actually, this is 100Hz 153 168 #elif PIDUPDATE == PID100HZ 154 169 TCCR0B = 0b00000101; … … 160 175 } 161 176 177 162 178 /* INT1 is encoder channel A 163 179 * To enable interrupt on rising edge of INT1: … … 167 183 ISR(INT1_vect) 168 184 { 169 cli();170 185 if (PIN_LEVEL(ENCB)) 171 enc_count ++;186 enc_count += enc_inc; 172 187 else 173 enc_count --;174 sei(); 175 } 188 enc_count -= enc_inc; 189 } 190 176 191 177 192 /* PID update loop */ 178 193 ISR(TIMER0_COMPA_vect) 179 194 { 195 int32_t rv, tmp; 196 180 197 ticks = enc_count; 181 PID.error = set_point - enc_count;182 198 enc_count = 0; 183 199 184 PID.p = PID.Kp * PID.error; 185 186 PID.error_sum += PID.error; 200 PID.error = set_point - ticks; 201 202 if (PID.error >= PID.max_error) 203 PID.p = INT16_MAX; 204 else if (PID.error < -PID.max_error) 205 PID.p = -INT16_MAX; 206 else 207 PID.p = PID.Kp * PID.error; 208 209 210 tmp = PID.error_sum + PID.error; 211 if (tmp >= PID.max_error_sum) 212 PID.error_sum = PID.max_error_sum; 213 else if (tmp < -PID.max_error_sum) 214 PID.error_sum = -PID.max_error_sum; 215 else 216 PID.error_sum = tmp; 217 187 218 PID.i = PID.Ki * PID.error_sum; 188 219 189 220 190 PID.d = PID.Kd * (PID. error - PID.last_error);221 PID.d = PID.Kd * (PID.last_error - PID.error); 191 222 PID.last_error = PID.error; 192 223 193 224 194 if (PIN_LEVEL(KILL) == 0 || disabled) 195 pwm_set(0); 196 else 197 pwm_set((PID.p + PID.i + PID.d) >> 7); 198 199 200 } 201 225 rv = (PID.p + PID.i + PID.d) / 128; 226 227 if (rv >= PWM_MAX) 228 rv = PWM_MAX; 229 else if (rv < -PWM_MAX) 230 rv = -PWM_MAX; 231 232 pwm_set(rv); 233 234 if (PIN_LEVEL(DISI)) { 235 PIN_SET(DIS); 236 } else { 237 PID.error_sum = 0; 238 PIN_CLR(DIS); 239 } 240 } 241 -
trunk/electronics/avr/2008-mcc/pins.m4
r383 r506 14 14 define(TXD, `DDRD, PORTD, PIND, PD1') 15 15 16 define(KILL, `DDRD, PORTD, PIND, PD5') 16 define(DISI, `DDRD, PORTD, PIND, PD7') 17 define(DIS, `DDRB, PORTB, PINB, PB2') 17 18 19 define(ENCPOL, `DDRD, PORTD, PIND, PD5') -
trunk/electronics/avr/2008-mcc/pwm.m4
r386 r506 12 12 void pwm_init() 13 13 { 14 PIN_OUTPUT(PWM);15 16 14 /* f_pwm = f_clk/(2 * n * TOP) */ 17 TCCR1A = 0b10 100000;15 TCCR1A = 0b10000000; 18 16 TCCR1B = 0b00010010; 19 17 20 ICR1 = 1 0000;18 ICR1 = 12500; 21 19 pwm_set(0); 20 PIN_OUTPUT(PWM); 22 21 } 23 22 … … 27 26 * 1500 = neutral 28 27 * 2000 = full forward 29 * sp should always be in the range [-256, 255]30 28 */ 31 29 void pwm_set(int16_t sp) 32 30 { 33 if (sp >= 255) 34 sp = 255; 35 else if (sp <= -256) 36 sp = -256; 31 int16_t tmp; 37 32 38 OCR1A = 1500 + (sp << 1); 33 tmp = sp * 2; 34 if (tmp > 512) 35 tmp = 512; 36 else if (tmp < -512) 37 tmp = -512; 39 38 39 tmp += 1875; 40 OCR1A = tmp; 40 41 } 41 42 42 43 int16_t pwm_get() 43 44 { 44 return (OCR1A - 1 500) >> 1;45 return (OCR1A - 1875) / 2; 45 46 } 46 47

