root/trunk/HighVoltageController.c

Revision 21, 19.2 kB (checked in by charlie, 3 years ago)

Added Peter Fleury's GPL licensed bootloader

Line 
1 #include <math.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <inttypes.h>
5 #include <avr/eeprom.h>
6 #include <avr/interrupt.h>
7 #include <avr/io.h>
8 #include <avr/pgmspace.h>
9 #include <avr/sleep.h>
10 #include <avr/wdt.h>
11 #include "RingBuffAdv/RingBuff.h"
12
13 //#include <avr/signal.h>
14 //#include <avr/iom16.h>
15
16 //#define MAX_THROTTLE 511
17 //#define MIN_THROTTLE 0
18 #define F_OSC 16000000                     /* oscillator-frequency in Hz */
19 //#define F_OSC 3686400
20 #define UART_BAUD_RATE 19200
21 #define UART_BAUD_CALC (((float)(F_OSC))/(((float)(UART_BAUD_RATE))*16.0)-1.0+0.5)
22
23
24 #define PRE_SCALED_ZERO_THROTTLE 989 // Anything bigger than 989 means 0% throttle.
25 #define PRE_SCALED_MAX_THROTTLE 683 // Anything smaller than 683 means 100% throttle.
26 #define PRE_SCALED_OPEN_CIRCUIT_THROTTLE        150     // Indicates a bad throttle.  Over ?? kOhms.
27
28 #define VREF 512  // VREF is the measurement of the current sensor at 0 volts.
29
30 #define READY 9
31 // Throttle Sensor connected to A/D Channel 2 (pin25 on atmega8)
32 #define THROTTLE 0
33 // Current Sensor connected to A/D Channel 2 (pin25 on atmega8)
34 #define CURRENT 2
35 // Temp sensor connected to A/D Channel 1 (pin24 on atmega8)
36 #define TEMPERATURE 1
37
38 #define KP 8l  // 8 corresponds to P constant of 1/4.
39 #define KI 4l  // 4 corresponds to I constant of 1/8.
40
41 #define K1 (KP << 10)
42 #define K2 (KI - K1)
43
44
45 #define MAX_CURRENT 506
46 #define THERMAL_CUTBACK_START 780       // start at 75 degC, end at 85 degC.
47
48 #define CURRENT_ARRAY_SIZE 16
49
50 #define SCALE_MUL_THROTTLE  53
51 #define SCALE_DIV_THROTTLE  5
52
53 // Define our IO pins and Ports
54 #define OVERCURRENT_TRIP  PB0
55 #define FLIPFLOP_RESET    PB2
56 #define IDLE_LED          PD6
57 #define MAIN_CONTACTOR    PD7
58
59  
60 //#define MAX_THROTTLE
61
62 // FOR CURRENT, using the LEM HASS 300, the 10 bit A/D converter outputs:
63
64 // It makes for a range of 213.
65 // I also want the throttle to have the same range as the current.
66 // Right now, 0 throttle is 0, and max throttle is 511.
67 // I need to map the current onto 0, 511.
68 // 500 amps -----> 725
69 // 0 amps   -----> 512
70
71 // READ CURRENT.
72 // IT'S IN [512, 512+213]
73 // subtract 512
74 // now its in [0, 213]
75 // times 24
76 // divide by 10.
77 // Now it's in the range [0, 511.2]
78
79
80
81 // There are 4 Analog to Digital Voltages.  The input of each will range from 0 to 5v.
82 // After the A/D conversion, the value will be between 0 and 1023.
83 // 0 will mean 0 volts was measured.  1023 will mean that 5v was measured.
84 int16_t volatile throttlePos=0;//       // the desired current.  in [0, 255].
85 int16_t volatile _throttlePos = 0;//***
86 int16_t volatile tmpCurrent = 0;//***
87 int16_t volatile tmpThrottle = 0;//***
88 int16_t volatile tmpTemp = 0;//
89 uint8_t volatile ADCMode = READY;
90 int16_t volatile pwmDuty = 0;
91 int32_t volatile pwmDutyFine = 0;//***
92 int16_t volatile errorNew = 0;//***
93 int16_t volatile errorOld = 0;//***
94
95
96 int16_t volatile temperature = 0;       // temperature measurement. Monitor the MOSFETs with a thermistor.
97 int16_t volatile current = 0;   // How much current is being used on a moment by moment basis.
98 int16_t volatile _current = 0;
99 int16_t volatile currentSum = 0;
100  
101 int16_t volatile i = 0;
102 int16_t volatile dummy = 0;
103 uint16_t volatile ISRCounter = 0;
104
105
106 uint8_t volatile relayLow = 1;
107 uint8_t volatile cSREG;//***
108
109 int16_t volatile currentPtr = 0;
110
111 int16_t volatile currBuffer[CURRENT_ARRAY_SIZE+1];
112 RingBuff_t txBuffer;
113
114 void InitUSART(uint16_t ubrr) {
115         // set baud rate
116         UBRRH = (uint8_t) (ubrr>>8);
117         UBRRL = (uint8_t) ubrr;
118
119         // Enable transmitter UART;
120 //      UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
121         UCSRB = (1 << TXEN);
122
123         //asynchronous 8N1
124         UCSRC = (1 << URSEL) | (3 << UCSZ0);
125 }
126
127
128
129 // Initialize the Pulse Width Modulator timer.
130 // Let's use timer 1, the 16 bit timer.  The others are 8 bit.
131 // 1.  Select the bits that you want set in TCCR1A.  See pg. 98 for help with this.
132 // 2.  Set the speed of your pwm by setting the bits you want in TCCR1B.  See pg. 100.
133 // 3.  Enable Pin B1 as the output for the pwm signal that you made.  See pg. 97.
134 // 4.  Initialize the value of the pwm to 0.  (may not be necessary)
135
136 // *TESTED PREVIOUSLY*
137 void InitPWM (void)
138 {
139 // We are using Mode 2 which is phase correct PWM
140 // The TCNT1 starts at BOTTOM (0) and starts counting to TOP. When it reaches TOP, the counter counts back to BOTTOM
141 // When it reaches BOTTOM, it will trigger the Timer1 Overflow interrupt (see the ISR code further down)
142 // For the PWM, as TCNT1 is increasing and it matches OCR1A it will set the OC1A I/O pin to 0
143 //              as TCNT1 is decreasing and it matches OCR1A it will set the OC1A I/O pin to 1
144         TCCR1A = _BV(COM1A1) | _BV(WGM11);  // set COM1A1 and WGM11
145
146         // Tclk = Fosc = 16MHz
147         // Tclk/1024 (from 0 to 511 and then 511 back to 0) = 16KHz freq for the Toverflow ISR
148         TCCR1B = _BV(CS10);  // pg. 100.  Pre-scaler = 1.
149
150         // Enable OC1A (the Output Compare Match A Output Pin) as the output pin of the PWM at pin B1.
151         // DDRB (Port B Data Direction Register) bit 1 must be set to 1 to make Pin B1 act as the
152         //   Output Pin for the PWM.
153         // On reset all pins are set to 0 or output
154         PORTB &= ~_BV(PB1); // this sets PB1 (the pwm output) to 0 at startup
155         DDRB = _BV(PB1); // Enable pin b1 to act as an output.  Pg. 52.
156
157         // OCR1A is the throttle value. 
158         // Set Initial PWM duty value to 0, both high and low bytes.
159         OCR1A = 0;
160 }
161
162 // This initializes the analog to digital converter.
163 // 1.  Enable the converter by setting the ADEN bit in ADCSRA
164 // 2.  Choose the sample speed, by messing with ADPS0, ADPS1, and ADPS2.
165 // 3.  Choose what voltage you want the converter to view as the highest.  The lowest will be 0.
166 //              To do that, you must mess with the REFS bits in the ADMUX register.
167 // 4.  Choose which A/D channel you want to use by messing with the MUX bits in ADMUX register.
168 // 5.  To start a conversion, you must set the ADSC bit in the ADCSRA.  Then you have to wait
169 //      for it to finish.  The result is in the ADC data register, so save it in some variable.
170
171 // *TESTED PREVIOUSLY*
172 void InitADC(void) {   
173         ADCSRA = _BV(ADEN);   // Enable the analog to digital converter.
174         ADCSRA |= _BV(ADPS2); // pg. 208. How fast to sample ADC? 16MHz/16
175         ADMUX = _BV(REFS0);     // Use AVcc as the reference voltage for the ADC, pg. 206
176 }
177
178
179 // This checks the Analog to Digital Converter Throttle input.
180 // 1.  Choose which ADC channel (which pin on the chip) you want to convert the voltage of. Pg. 206.
181 // 2.  Set the ADSC bit to 1.  This starts the conversion.
182 // 3.  Wait for the conversion to finish.  (Do nothing until it's done)
183 // 4.  The result is saved in ADC.  Move that result to a variable for later.
184
185 void ReadThrottle(void) {
186         throttlePos = ADC;
187
188 // zero throttle is 989 OR GREATER.  That's a 10% dead zone.
189 // Full throttle is 683
190
191 //      if (throttlePos < PRE_SCALED_OPEN_CIRCUIT_THROTTLE) {   // Bad Throttle!  More than ??kOhms from a 5k pot!
192 //              throttlePos = 0;
193 //              for (i = 0; i < 16; i++) {
194 //                      ADCSRA |= 64;   // 64  = 01000000.  So, this sets the ADSC Start Conversion Bit.
195 //                      while (ADCSRA & 64);    // Do nothing until the conversion is done.
196 //                      dummy = ADC;
197 //                      throttlePos += dummy;
198 //              }
199 //              throttlePos >>= 4; // find the average of the 16 throttle reads, to make sure it wasn't just a bad read.
200 //              if (throttlePos < PRE_SCALED_OPEN_CIRCUIT_THROTTLE) {  // if the average of 16 throttle reads was bad...
201 //                      OCR1A = 0;  // make sure PWM duty is 0.  Kill the throttle.
202 //                      while (1) {
203 //                              wdt_reset();  // get a new dang throttle!  hahaha!
204                                                                 // don't let the watchdog reset the program.
205 //                      }
206 //              }
207 //      }
208
209         if (throttlePos < PRE_SCALED_MAX_THROTTLE) // 683 is max throttle this time.
210                 throttlePos = PRE_SCALED_MAX_THROTTLE; // 683
211
212
213         if (throttlePos > PRE_SCALED_ZERO_THROTTLE) // 989, allowing for 10% dead zone.
214                 throttlePos = PRE_SCALED_ZERO_THROTTLE; // 989.
215
216         throttlePos -= PRE_SCALED_MAX_THROTTLE;
217         // Now throttlePos is in [0, 306].
218         throttlePos = (PRE_SCALED_ZERO_THROTTLE - PRE_SCALED_MAX_THROTTLE) - throttlePos;
219         // Now, 0 throttle is 0, and max throttle is 306.
220         //
221         //throttlePos *= 1.66;
222         // do throttlePos*53/32.
223         throttlePos *= SCALE_MUL_THROTTLE;  // multiply by SCALE_MUL_THROTTLE
224         throttlePos >>= SCALE_DIV_THROTTLE;     // divide by SCALE_DIV_THROTTLE
225         // now throttlePos is in [0, 507], about identical to current range.
226         // this is important because the PWM range is 0 to 511, where 0 means 0% duty, and 511 means 100% duty.
227 }
228
229 // *TESTED IN SIMULATOR*
230 void ReadCurrent(void) {
231         current = ADC;
232
233         // Current starts in [512, 512 + 213]  (if it's in 0 to 500 amps for the LEM 300)
234         // vRef is defined at the top. It is the calibrated "0" value.
235         if (current < VREF) // if slightly below 0, just call it 0.
236                 current = VREF;
237         current -= VREF;
238         // now, for the LEM 500, it's in the range [0,128].
239         currentSum -= currBuffer[currentPtr];
240         currBuffer[currentPtr] = current;
241         currentSum += current;
242         _current = currentSum >> 2;  // "divide by 16, multiply by 4" = divide by 4
243         if (currentPtr == CURRENT_ARRAY_SIZE - 1)
244                 currentPtr = 0;
245         else
246                 currentPtr++;
247         //_current is average current
248 }
249
250 // *TESTED PREVIOUSLY*
251
252 //void ReadTemperature(void) {
253 //      ADMUX &= (0b11110000);  // This sets MUX to 0000, and leaves the top 4 bits unchanged.
254                                                 // pg. 206
255                                                 // I'd like to suggest defining a TEMPERATURE at the top
256 //  ADMUX |= TEMPERATURE;  // TEMPERATURE, the temperature monitor.                                       
257
258         // Read temperature.
259         // Pg. 198.
260         //ADCSRA |= 64; // 64  = 01000000.  So, this sets the ADSC Start Conversion Bit.
261 //      ADCSRA |= _BV(ADSC);  // Start Conversion
262 //      while (ADCSRA & 64);    // Do nothing until the conversion is done.
263 //      temperature = ADC;
264 //}
265
266 // *TESTED PREVIOUSLY*
267
268 void HighPedalLockout(void) {
269 //      pwmDuty = 0;
270         OCR1A = 0;
271         do {
272                 // Select channel 0.
273                 ADMUX &= (0b11110000);  // = 11110000.  So, this sets MUX to 0000, and leaves the top 4 bits unchanged.
274         // pg. 206
275
276         // Read throttle position.
277         // Pg. 198.
278
279                 ADCSRA |= _BV(ADSC);    // Start Conversion
280                 while (ADCSRA & 64);    // Do nothing until the conversion is done.
281                 throttlePos = ADC;
282
283                 wdt_reset(); 
284         } while (throttlePos < PRE_SCALED_ZERO_THROTTLE);  // I'm not doing all the rescaling and shifting for this part.
285         throttlePos = 0;
286 }
287
288 // At 8 MHz, a 'for' loop of 100 iterations takes 280 microseconds according to the debugging simulator.
289 // To call the function takes 4.6 microseconds.
290 // So, a delay of 21 is about one PWM period.  2 nand gates in series need 1 microsecond to change
291 // their state, so at least a delay of 1 is fine for resetting the flip flop.
292
293 // It is important to have Optimization turned off in Configuration Options.
294 // The optimizations don't let you do a loop for no reason.
295 // *TESTED IN SIMULATOR*
296 // watch out for the watchdog timeout if you use too large of a delay.
297
298 // http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
299 void Delay(int k) {
300         // int m;
301         int volatile m;
302         for (m = 0; m < k; m++);
303         return;
304 }
305
306 void BigDelay(int k) {
307         int m, n;
308        
309         for (m = 0; m < k; m++) {
310                 for (n = 0; n < 1000; n++);
311         }
312 }
313
314 // This checks for and deals with an overcurrent event. If there is an overcurrent event,
315 // it clears the overcurrent event by pulsing port b2 low for a moment, which resets the hardware flip-flop.
316
317 // *TESTED IN SIMULATOR*
318
319 void ResetOverCurrentEvent() {
320 // for things configured as inputs, to read the value of the input, you read pinb, not portb!
321 // TO SET VALUES, YOU MUST USE PORTB, NOT PINB!
322
323         // if pin b0 is 1, then an overcurrent event has occurred. 
324         // if (PINB & 1) {      // clear overcurrent event.
325         if (PINB & _BV(OVERCURRENT_TRIP)) {     // clear overcurrent event.
326                 // At this point, portb2 is high.  It was initialized high at the beginning.
327                 // clear the overcurrent event.  Bring port b2 low...
328                 PORTB &= ~_BV(FLIPFLOP_RESET); // Clear FLIPFLOP   aka &= 11111011b
329                 Delay(2);
330                 // Now bring port b2 high again...  This clears the overcurrent event.
331                 PORTB |= _BV(FLIPFLOP_RESET); // Reset FLIPFLOP
332                 pwmDuty--;
333                 if (pwmDuty < 0)
334                         pwmDuty = 0;
335 //              pwmDutyFine -= (1 << 15);
336 //              if (pwmDutyFine < 0)
337 //                      pwmDutyFine = 0;
338 //              OCR1A = (pwmDutyFine >> 15);
339         }
340         return;
341 }
342
343
344 ISR (ADC_vect) {
345         if (ADCMode == CURRENT) {
346                 //current=ADC;
347                 ReadCurrent();
348         }
349
350         else if (ADCMode==THROTTLE) {
351                 //throttlePos=ADC;
352                 ReadThrottle();
353         }
354 //      else {  // it's temperature
355 //              temperature=ADC;
356 //      }
357         ADCMode=READY; //signify that we are ready for another reading
358 }
359
360 // Based on the setting in the Timer1 InitPWM() function this ISR will be called at ~16KHz
361 ISR (TIMER1_OVF_vect) {
362         ResetOverCurrentEvent();  // Maybe turn on after 'n' cycles of being off,
363                                                           //  where n is a function of PWM duty?
364
365         if (ADCMode==READY) {           //wait for last adc request to finish
366                 ISRCounter++;
367                 ADCMode = CURRENT;  // This is the default
368
369 //              if ((ISRCounter & 32767) == 32767) { // 32767 = 0b0111111111111111.  This happens every 2 seconds.
370 //                      ADCMode=TEMPERATURE;
371 //                      ISRCounter = 0;
372 //              }
373
374                 if ((ISRCounter & 15) == 15) // 15 = 0b1111.
375                         ADCMode = THROTTLE;
376
377                 ADMUX &= 0b11110000; // zero out the MUX
378                 ADMUX |= ADCMode; //select channel
379                 ADCSRA |= 64;//start adc conversion
380         }
381 }
382
383
384 ISR (TIMER2_OVF_vect) {
385                         //place 8 bit values in the tx FIFO
386                     Buffer_StoreElement(&txBuffer, (uint8_t) (tmpThrottle >>8)); // Store value for throttleH into ringbuff
387                     Buffer_StoreElement(&txBuffer, (uint8_t) tmpThrottle); // Store value for throttleL into ringbuff           
388                     Buffer_StoreElement(&txBuffer, (uint8_t) (tmpCurrent >>8)); // Store value for currentH into ringbuff
389                     Buffer_StoreElement(&txBuffer, (uint8_t) tmpCurrent); // Store value for currentL into ringbuff
390                     Buffer_StoreElement(&txBuffer, (uint8_t) (pwmDuty >>8)); // Store value for currentH into ringbuff
391                     Buffer_StoreElement(&txBuffer, (uint8_t) pwmDuty); // Store value for currentL into ringbuff
392                         Buffer_StoreElement(&txBuffer, (uint8_t) 0xF0); // Sync Byte
393                         Buffer_StoreElement(&txBuffer, (uint8_t) 0xFF); // Sync Byte
394
395
396                     //enable USART "TX buffer empty" interrupt
397                     UCSRB |= _BV(UDRIE);
398 }
399
400
401 // *TESTED IN SIMULATOR*
402 // Pin b0 is going to be a flag to let the controller know that the hardware shut off the mosfets.
403 // Pin b0 is 0 if the hardware has not shut off the mosfets.  If you read the value of pin b0 is
404 // 1, then a hardware overcurrent shutdown has occurred.  You then have a delay, and clear the
405 // hardware overcurrent event by changing port b2 from 1 to 0, and then back to 1.
406 // First pin b0 needs to be initialized as an input and pin b2 initialized as an output.
407
408 // *TESTED IN SIMULATOR*
409 void InitializeIOPins(void) {
410
411         //DDRB |= 4;    // Configure PINB2 as output
412         DDRB |= _BV(FLIPFLOP_RESET);    // Configure PINB2 as output
413         // The stupid documentation says this next step might be necessary.  See pg. 52.
414         PORTB &= ~_BV(FLIPFLOP_RESET); // Clear only B2   aka &= 11111011b
415
416         // Pulsing pin b2 low for a moment guarantees that the state of the flip flop in the hardware overcurrent
417         // shutdown circuit is known.
418         PORTB |= _BV(FLIPFLOP_RESET); // Reset FLIPFLOP_RESET
419         Delay(5);
420         PORTB &= ~_BV(FLIPFLOP_RESET); // Clear FLIPFLOP_RESET   aka &= 11111011b
421         Delay(5);
422         PORTB |= _BV(FLIPFLOP_RESET); // RESET FLIPFLOP_RESET
423
424         DDRD |= _BV(MAIN_CONTACTOR);  // configure pin MAIN_CONTACTOR for output.  It is a relay that turns on the main contactor.
425         DDRD |= _BV(IDLE_LED);  // configure pin IDLE_LED for output.  It is the IDLE LED.  Pulse it every second for Chris.
426
427         // Now configure pin b0 as an input pin.  It will be the indicator of when a hardware overcurrent
428         // shutdown has occurred.  Reading a 0 from this pin means there has NOT been an
429         // overcurrent shutdown, so everything is working normally.  Reading a 1 from this pin means
430         // that an overcurrent shutdown has happened.  So, output a trip reset at port b2 to turn the mosfet driver back on.
431         
432         // setting DDRB bit 'n' to 0 makes that bit configured for input.
433         DDRB &= ~_BV(PB0); // DDRB = XXXXXXX0  Configure PINB0 as input.
434         PORTB |= _BV(PB0);      // Maybe unnecessary intermediate step.  See page 52.
435         PORTB &= ~_BV(PB0); // PORTB = XXXXXXX0 Turn off the pull-up resistor at pin b0.
436         return;
437 }
438
439
440
441 ISR (USART_UDRE_vect) {
442   if (txBuffer.Elements > 0) {
443     UDR =  Buffer_GetElement(&txBuffer); //place data for transmission
444         //UDR = txBuffer.Elements;
445         }
446   else
447     UCSRB &= ~_BV(UDRIE);  //disable interrupt
448 }
449
450
451 int main (void) {
452         InitADC();      // initialize the analog to digital converter
453         InitializeIOPins(); // pin b0 acts as an input, pin b2 acts as an output.
454         InitUSART(UART_BAUD_CALC);
455         Buffer_Initialize(&txBuffer); // Init buffer (also clears/flushes/resets)
456
457         wdt_enable(WDTO_2S);
458
459         for (currentPtr = 0; currentPtr < CURRENT_ARRAY_SIZE; currentPtr++)
460                 currBuffer[currentPtr] = 0;
461         currentPtr = 0;
462
463         HighPedalLockout();
464     InitPWM();
465
466         // Finally, enable interrupts for the timer and the A/D converter.  It causes problems if you
467         // enable them too early. 
468         ADCSRA |= _BV(ADIE);  // Enable an interrupt to happen each time an A/D conversion is finished.
469         // Enable Timer1 Overflow Interrupt
470         TIMSK = _BV(TOIE1) | _BV(TOIE2);        // make an interrupt happen each time the timer reaches the bottom.
471         TCCR2 = _BV(CS22) | _BV(CS21) | _BV(CS20);
472    
473         sei();  // Enable interrupts
474
475         while (1) { // do this forever 
476                 cSREG = SREG; /* store SREG value */
477                 cli();  // disable interrupts
478
479                 tmpTemp = temperature;
480                 tmpCurrent = _current;
481                 tmpThrottle = throttlePos;
482                 SREG = cSREG;
483
484                
485
486                 _throttlePos = tmpThrottle;
487
488                 // The temperature is an input from the A/D converter.  It is in the range of 0 to 1023.
489                 // These numbers are specific to the Thermistor Part# B57862S103F40 from Digikey.
490
491                 // 25 degC      327
492                 // 30 degC      377
493                 // 35 degC      429
494                 // 40 degC      480
495                 // 45 degC      537
496                 // 50 degC      580
497                 // 55 degC      626
498                 // 60 degC      670
499                 // 65 degC      710
500                 // 70 degC      746
501                 // 75 degC      779
502                 // 80 degC      808
503                 // 85 degC      834
504                 // 90 degC      857
505                 // 95 degC      877
506                 // 100 degC     895
507
508                 // This shifts the current limit down based on how hot the controller is.
509                 // If the temperature is about 70 degC, the current limit is 437 amps.
510                 // If the temperature is about 75 degC, the current limit is about 250 amps.
511                 // At around 80 degC, the current limit is 0.
512 /*
513                 if (tmpTemp > THERMAL_CUTBACK_START) {  // start of thermal cutback.
514                         if (tmpTemp < THERMAL_CUTBACK_START+8) // _throttlePos = 7/8*tmpThrottle.
515                                 _throttlePos = (7*tmpThrottle) >> 3;
516
517                         else if (tmpTemp < THERMAL_CUTBACK_START + 16)  // _throttlePos = 6/8*tmpThrottle;
518                                 _throttlePos = (6*tmpThrottle) >> 3;           
519
520                         else if (tmpTemp < THERMAL_CUTBACK_START + 24)  //                              = 5/8*tmpThrottle;
521                                 _throttlePos = (5*tmpThrottle) >> 3;
522
523                         else if (tmpTemp < THERMAL_CUTBACK_START + 32)  //                              = 4/8*tmpThrottle;
524                                 _throttlePos = tmpThrottle >> 1;               
525
526                         else if (tmpTemp < THERMAL_CUTBACK_START + 40)  //                              = 3/8*tmpThrottle;
527                                 _throttlePos = 3*(tmpThrottle >> 3);
528
529                         else if (tmpTemp < THERMAL_CUTBACK_START + 48)  //                              = 2/8*tmpThrottle;
530                                 _throttlePos = tmpThrottle >> 2;
531
532                         else if (tmpTemp < THERMAL_CUTBACK_START + 56)  //                              = 1/8*tmpThrottle;
533                                 _throttlePos = tmpThrottle >> 3;
534
535                         else
536                                 _throttlePos = 0;
537                 }
538 */
539 //              errorNew = _throttlePos - tmpCurrent;
540 //              pwmDutyFine += (((int32_t)(errorNew - errorOld)) << 13) + (int32_t)(errorOld << 2);
541 //              pwmDutyFine += K1*errorNew + K2*errorOld;
542 //              errorOld = errorNew;
543
544
545                 if (pwmDuty < _throttlePos)
546                         pwmDuty++;
547                 else if (pwmDuty > _throttlePos)
548                         pwmDuty--;
549 //              if (pwmDutyFine > (511l << 15))
550 //                      pwmDutyFine = (511l << 15);
551 //              else if (pwmDutyFine < 0l)
552 //                      pwmDutyFine = 0l;
553
554                 //pwmDuty = (int16_t)(pwmDutyFine >> 15);
555
556                 OCR1A = pwmDuty;
557                 wdt_reset();
558         }
559         return (0);
560 }
Note: See TracBrowser for help on using the browser.