/// A to D test code // NOTE -- Aref is pin 32 / *#**include** **<**Mega32.h**>* *#**include** **<**stdio.h**>* // sprintf *#**include** **<**stdlib.h**>* *#**include** **<**math.h**>* ///I like these definitions /*#*define begin { *#*define end } *#*define LCDwidth 16 //characters ///calc constants /*#*define clock_tick 6.25e-8 *#*define mps2 6.0956392045e-2 ///convert to disp units //#define velocity_convert .0981 // m/s // .0981 * .001 m/km /3600 /*#*define velocity_convert 0.35316 //km/hr *#*define distance_convert .000000981//m *#*define hp_convert 0.0003725 ///State machine state names /*#*define MaybePush 1 *#*define MaybePush1 2 *#*define Push 3 *#*define NoPush 4 *#*define MaybeNoPush 5 ///State machine for program /*#*define Calibrate 0 *#*define GetWeight 1 *#*define Measure 2 *#*define Type 3 *#*define ZeroGWait 4 *#*define Accel 1 *#*define Velocity 2 *#*define Distance 3 *#*define HP 4 *#*define Time 5 ///calistate /*#*define zero 1 *#*define one 2 *#*define negone 3 *#*define Display 4 ///type states /*#*define zero60 1 *#*define zero30 2 *#*define quarter 3 *#*define eighth 4 *#*define brake 5 *#*define zero100 0 ///sub state /*#*define Stop_Measure 0xff *#*define Start_Measure 0x00 //* Use an 1x16 alphanumeric LCD connected to PORTC as follows: [LCD] [AT90S8515 DIP40] 1 GND- 20 GND 2 +5V- 40 VCC 3 VLC 10k trimpot wiper (trimpot ends go to +5 and gnd) 4 RS - 21 PC0 5 RD - 22 PC1 6 EN - 23 PC2 11 D4 - 25 PC4 12 D5 - 26 PC5 13 D6 - 27 PC6 14 D7 - 28 PC7 3.22 =-1g 3.82 =0g 4.57= 1g *// *#*asm .equ __lcd_port=*0x15* *#*endasm *#**include** **<**lcd.h**>* // LCD driver routines *char* lcd_buffer_g[*4*]; /// LCD display buffer /*char* lcd_buffer_g2[*4*]; *char* lcd_buffer_v[*10*]; *char* lcd_buffer_d[*10*]; *char* lcd_buffer_t[*10*]; *char* lcd_buffer[*10*]; *double* zerog,oneg,negoneg;///calibration values / *char* lcd_buffer_w[*5*]; *int* Ain ; ///raw A to D number /*double* voltage ; ///scaled input voltage /*double* current_g,previous_g,current_v, previous_v,current_d,previous_d,maxg,maxv; *double* truev,trued; *double* weight;///weight of car + person /*unsigned* *int* dispCounter; *float* finaltime;/// count to when to update lcd /*char* ProgState, substate, stateIter,firstint,isdone; ///state var, and state loop counter /*char* currentOut,dispState,buttonState,caliState,typeState; *double* hp,maxhp,max1g,maxn1g; *double* bottomslope; *char* stopCondition , AutoStart; *double* round(*double*,*char* ); *void* main(*void*) begin /// initialize the LCD for 16 char wide / lcd_init(LCDwidth); ///initialize the display / lcd_clear(); ///clear the display / ///init the A to D converter / ///channel zero/ left adj / / ADMUX = 0b00100000; ///enable ADC and set prescaler to 1/64*8MHz=125,000 / ADCSR = *0x80* + *0x06*; MCUCR = 0b00001000; ///choose ADC mode / DDRD = *0x00*; ///input / PORTD= *0xFF*; ///init timer 1 to generate time base for measuring / OCR1A = *2500*; ///generate 10msec time base / TCCR1B = *11*; ///pre-scalar at 64; clear-on-match / TCCR1A = *0x00*; ///turn off pwm and oc lines / TIMSK = *0x10*; ///enable interrupt T1 cmp / firstint= *1*; dispCounter = *0*; isdone =*0*; dispState= *0*; caliState = one; typeState = zero60; AutoStart= *0*; stopCondition=*1*; buttonState = NoPush; substate = Stop_Measure; maxn1g = *128*; #asm sei #endasm ///collect weight information / /// measure and display loop / stateIter = *0*; ProgState = Calibrate; ///weight = 0; / *while* (*1*) { *switch*(typeState) { *case* zero60: *if* (truev >= *97* && ProgState == Measure) finaltime = (*float*)dispCounter/*100*; *break*; *case* zero30: *if* (truev >= *48*.*5* && ProgState == Measure) finaltime = (*float*)dispCounter/*100*; *break*; *case* zero100: *if* (truev >= *159* && ProgState == Measure) finaltime = (*float*)dispCounter/*100*; *break*; *case* quarter: *if* (trued >= .*398* && ProgState == Measure) finaltime = (*float*)dispCounter/*100*; *break*; *case* eighth: *if* (trued >= .*199* && ProgState == Measure) finaltime = (*float*)dispCounter/*100*; *break*; *case* brake: *if* (current_g==*0* && dispCounter > *150* && ProgState == Measure) finaltime = (*float*)dispCounter/*100*; *break*; } } } ///timer 1 overflow ISR /interrupt [TIM1_COMPA] *void* t1_cmpA(*void*) { *switch*(ProgState){ ///semi-auto matic calibrtion / *case* Type: *switch*(typeState) { *case* zero60: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/00-60mph/"/); *break*; *case* zero30: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/00-30mph/"/); *break*; *case* zero100: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/0-100mph/"/); *break*; *case* quarter: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/1/4 mile/"/); *break*; *case* eighth: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/1/8 mile/"/); *break*; *case* brake: lcd_clear(); lcd_gotoxy(*0*,*0*); lcd_putsf(/"/brake/"/); *break*; } *switch* (buttonState) { *case* NoPush: *if* (PIND==0b11111101) buttonState = MaybePush; *break*; ///if pushed / *case* MaybePush: *if* (PIND==0b11111101) { buttonState = Push; typeState = (typeState+*1*)%*6*;///wrap around / } *else* buttonState= NoPush; *break*; *case* Push: *if* (PIND==0b11111101) { } *else* buttonState = MaybeNoPush; *break*; *case* MaybeNoPush: *if* (PIND==0b11111101) buttonState = Push; *else* buttonState= NoPush; *break*; } *if* (PIND==0b11111011) ProgState = GetWeight; *break*; *case* Calibrate: *if* (stateIter==*0*) { lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Calibrate/"/); lcd_gotoxy(*0*,*1*); lcd_putsf(/"/1G VERT/"/); buttonState = NoPush; stateIter++; } ADCSR = ADCSR | *0x40*; Ain = ADCH; voltage = (*double*)Ain ; lcd_buffer[*1*] = *0*; lcd_gotoxy(*8*,*1*); itoa(Ain,lcd_buffer); lcd_puts(lcd_buffer); *switch* (buttonState) { *case* NoPush: *if* (PIND==0b11111101) buttonState = MaybePush; *switch* (caliState) { *case* one: ///when searching for 1 g point take max sample / max1g= fmax(max1g,voltage); *break*; *case* negone: ///take min for neg 1 g / maxn1g = fmin(maxn1g,voltage); *break*; } *break*; ///if pushed / *case* MaybePush: *if* (PIND==0b11111101) { buttonState = Push; ///voltage = (voltage/256)*4.92 ; / *switch* (caliState) { *case* one: oneg= max1g; caliState = negone; ///set up next poart / lcd_gotoxy(*0*,*1*); lcd_putsf(/"/-1G VERT/"/); *break*; *case* negone: ///negoneg = voltage; / negoneg= maxn1g; ProgState = Type; caliState = Display;///ensure it doesn't go back thr / /// do some serious calc / zerog = (oneg+ negoneg)/*2*.*0*;///extrapolate 0g / bottomslope = (oneg-negoneg)/*2*.*0*; ///slope / lcd_clear(); *break*; } } *else* buttonState= NoPush; *break*; *case* Push: *if* (PIND==0b11111101) { } *else* buttonState = MaybeNoPush; *break*; *case* MaybeNoPush: *if* (PIND==0b11111101) buttonState = Push; *else* buttonState= NoPush; *break*; } *break*; *case* GetWeight: ///pin4 is hardware reset / lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Enter Weight(kg)/"/); *if* (PIND==0b11111101) { weight = weight + *5*; } *else* *if* (PIND==0b11111011) { weight = weight - *5*; weight = fmax(weight,*0*); } *if* (PIND==0b11111110) { ProgState = ZeroGWait; buttonState = NoPush; stateIter=*0*; } lcd_gotoxy(*0*,*1*); ftoa(weight,*0*,lcd_buffer_w); lcd_puts(lcd_buffer_w); *break*; *case* ZeroGWait: //* lcd_gotoxy(0,0); ftoa(oneg,2,lcd_buffer_g); lcd_puts(lcd_buffer_g); lcd_gotoxy(8,0); ftoa(negoneg,2,lcd_buffer_g); lcd_puts(lcd_buffer_g); lcd_gotoxy(0,1); ftoa(zerog,2,lcd_buffer_g); lcd_puts(lcd_buffer_g); /*// *if* (stateIter==*0*) { lcd_clear(); lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Level:0.0g/"/); stateIter++; } ADCSR = ADCSR | *0x40*; Ain = ADCH; voltage = (*double*)Ain ; ///find g values / *if* (voltage< zerog-*10*) { current_g = (voltage - zerog)/bottomslope; }/// in g-units / *else* *if* (voltage>zerog+*10*) { current_g = (voltage - zerog)/bottomslope; }/// in g-units / *else* {current_g = *0*.*0*;} *if* (PIND == 0b11111101){///auto or manual start? / AutoStart++; AutoStart=AutoStart%*2*; } *switch* (buttonState) { *case* NoPush: *if* (PIND==0b11111011) buttonState = MaybePush; *break*; *case* MaybePush: *if* (PIND==0b11111011) { dispCounter = *0*; ProgState = Measure; buttonState = NoPush; *if* (AutoStart==*0*) { substate= Start_Measure; } lcd_clear(); } *else* buttonState= NoPush; *break*; *case* Push: *if* (PIND==0b11111011) { } *else* buttonState = MaybeNoPush; *break*; *case* MaybeNoPush: *if* (PIND==0b11111011) buttonState = Push; *else* buttonState= NoPush; *break*; } *if* (dispCounter%*25*==*0*) { ///do display / lcd_gotoxy(*0*,*1*); ftoa(current_g,*2*,lcd_buffer_g); lcd_puts(lcd_buffer_g); lcd_gotoxy(*7*,*1*); *if* (AutoStart==*0*) { lcd_putsf(/"/Manu/"/); } *else* { lcd_putsf(/"/Auto/"/); } ///ftoa(voltage,2,lcd_buffer_g); / ///lcd_puts(lcd_buffer_g); / } *break*; *case* Measure: *switch*(typeState) { *case* zero60: *if* (truev >= *99*) stopCondition = *0*; *break*; *case* zero30: *if* (truev >= *49*) stopCondition = *0*; *break*; *case* zero100: *if* (truev >= *160*) stopCondition = *0*; *break*; *case* quarter: *if* (trued >= .*4*) stopCondition = *0*; *break*; *case* eighth: *if* (trued >= .*2*) stopCondition = *0*; *break*; *case* brake: *if* (current_g==*0* && dispCounter > *150*) stopCondition = *0*; *break*; } *if* (stopCondition==*0*) { *if* (isdone==*0*) { lcd_gotoxy(*2*,*0*); *if* (current_g > *0*) { ftoa(current_g,*2* ,lcd_buffer_g); lcd_puts(lcd_buffer_g); } *else* { ftoa(current_g,*2* ,lcd_buffer_g2); lcd_puts(lcd_buffer_g2); } ///distance / lcd_gotoxy(*10*,*0*); ftoa(current_d*distance_convert,*2* ,lcd_buffer_d); lcd_puts(lcd_buffer_d); ///velocity / lcd_gotoxy(*2*,*1*); truev = current_v*velocity_convert; ///ftoa(truev,10,lcd_buffer_v); / ftoa((*float*)finaltime/*100*,*2*,lcd_buffer_v); lcd_puts(lcd_buffer_v); isdone= *1*; currentOut= *1*; lcd_clear(); } *else*{ *switch* (buttonState) { *case* NoPush: *if* (PIND==0b11111101) buttonState = MaybePush; *break*; *case* MaybePush: *if* (PIND==0b11111101) buttonState = MaybePush1; *else* buttonState= NoPush; *break*; *case* MaybePush1: *if* (PIND==0b11111101) { buttonState = Push; *if* (currentOut ==Time) currentOut= *1*; *else* currentOut++; dispState = *0*; lcd_clear(); } *else* buttonState= NoPush; *break*; *case* Push: *if* (PIND==0b11111101) { } *else* buttonState = MaybeNoPush; *break*; *case* MaybeNoPush: *if* (PIND==0b11111101) buttonState = Push; *else* buttonState= NoPush; *break*; } *switch* (currentOut) { *case* Accel: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Max Accel(g):/"/); lcd_gotoxy(*1*,*1*); ftoa(maxg,*2*,lcd_buffer_g); lcd_puts(lcd_buffer_g); *break*; *case* Velocity: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Max Velocity(mph):/"/); lcd_gotoxy(*1*,*1*); ftoa(maxv**0*.*62*,*2*,lcd_buffer_v); lcd_puts(lcd_buffer_v); *break*; *case* Distance: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Distance:(ft)/"/); lcd_gotoxy(*1*,*1*); ftoa(trued**3280*,*3*,lcd_buffer_d); lcd_puts(lcd_buffer_d); *break*; *case* HP: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Max HP:/"/); lcd_gotoxy(*1*,*1*); ftoa(maxhp,*2*,lcd_buffer_t); lcd_puts(lcd_buffer_t); *break*; *case* Time: lcd_gotoxy(*0*,*0*); lcd_putsf(/"/Time(s):/"/); lcd_gotoxy(*1*,*1*); ftoa(finaltime,*2*,lcd_buffer_t); lcd_puts(lcd_buffer_t); }///end switch / *if* (PIND==0b11111110) { firstint= *1*; dispCounter = *0*; isdone =*0*; dispState= *0*; caliState = one; ProgState = Type; typeState = zero60; AutoStart= *0*; stopCondition=*1*; buttonState = NoPush; substate = Stop_Measure; current_g= *0*; current_d = *0*; current_v = *0*; truev = *0*; trued= *0*; lcd_clear(); stateIter= *0*; } } ///stop / } *else* *if* (substate == Start_Measure) { ///32.184975ft/s^2 = 1g / ///0.0060956392045 miles/s^2 = 1g / ///1 clock tick = 0.0000000625sec+ / ADCSR = ADCSR | *0x40*; Ain = ADCH; voltage = (*double*)Ain ; ///find g values / *if* (voltage< zerog-*10*) { current_g = (voltage - zerog)/bottomslope; }/// in g-units / *else* *if* (voltage>zerog+*10*) { current_g = (voltage - zerog)/bottomslope; }/// in g-units / *else* {current_g = *0*.*0*;} current_g=round(current_g,*2*); *if* (firstint==*1*) { current_v = *0*; ///firstint=0; / } ///integrate / current_v = current_g + previous_v; current_d = current_v + previous_d; *if* (dispCounter%*50*==*0*) { *if* (firstint==*1*) { maxg= *0*; current_v = *0*; current_d= *0*; firstint=*0*; maxhp = *0*; } /// display the voltage / ///g force / lcd_gotoxy(*0*,*0*); lcd_putsf(/"/g=/"/); lcd_gotoxy(*8*,*0*); lcd_putsf(/"/d=/"/); lcd_gotoxy(*0*,*1*); lcd_putsf(/"/t=/"/); lcd_gotoxy(*2*,*0*); *if* (current_g > *0*) { ftoa(current_g,*2* ,lcd_buffer_g); lcd_puts(lcd_buffer_g); } *else* { ftoa(current_g,*2* ,lcd_buffer_g2); lcd_puts(lcd_buffer_g2); } ///distance / lcd_gotoxy(*10*,*0*); ftoa(trued,*2* ,lcd_buffer_d); lcd_puts(lcd_buffer_d); ///velocity / lcd_gotoxy(*2*,*1*); ///ftoa(truev,10,lcd_buffer_v); / ///itoa(dispCounter,lcd_buffer_v); / ftoa((*float*)dispCounter/*100*,*2*,lcd_buffer_v); lcd_puts(lcd_buffer_v); dispCounter++; isdone= *0* ; } *else*{ dispCounter++; } ///calucate carryover values, pass over integration / truev = current_v*velocity_convert; trued = current_d*distance_convert; hp = truev* current_g**9*.*81* *weight*hp_convert; previous_g = current_g; previous_v = current_v; previous_d = current_d; *if*(dispCounter > *3*) maxg = fmax(current_g,maxg); maxv = fmax(truev,maxv); maxhp = fmax(hp,maxhp); } *else* { ADCSR = ADCSR | *0x40*; Ain = ADCH; voltage = (*double*)Ain ; ///find g values / *if* (voltage< zerog-*7*) { current_g = (voltage - zerog)/bottomslope; }/// in g-units / *else* *if* (voltage>zerog+*7*) { current_g = (voltage - zerog)/bottomslope; }/// in g-units / *else* {current_g = *0*.*0*;} *if* (fabs(current_g)>*0*.*25*) {///acceleration threshold to start measure / substate=Start_Measure; } }///end if / }///end switch / } ///rounds a float to 'places' digits including leading 0 / ///0.xxx or x.xxx or even xxxxe^ / *double* round(*double* toRound, *char* places) { *char* rounda[*10*]; ftoa(toRound,places,rounda); *return* atof(rounda); }