X-Git-Url: http://dolda2000.com/gitweb/?p=kokare.git;a=blobdiff_plain;f=kokare.c;h=f7033d8d29b16e6067445fa70ca1436a5dce9089;hp=18379e9fc53a88f343caf6437bfc1f6e18c36898;hb=HEAD;hpb=314156469153a9cbf5a74660c1d69808ad35a924 diff --git a/kokare.c b/kokare.c index 18379e9..f7033d8 100644 --- a/kokare.c +++ b/kokare.c @@ -1,15 +1,17 @@ #include #include +#include #include +#include -#define SEGA 128 -#define SEGB 64 -#define SEGC 4 -#define SEGD 16 -#define SEGE 32 -#define SEGF 2 -#define SEGG 1 -#define SEGP 8 +#define SEGA 4 +#define SEGB 2 +#define SEGC 1 +#define SEGD 32 +#define SEGE 64 +#define SEGF 16 +#define SEGG 8 +#define SEGP 128 uint8_t font[16] = { SEGA | SEGB | SEGC | SEGD | SEGE | SEGF, @@ -34,36 +36,58 @@ uint8_t dsp[2] = {0, 0}; char leda = 0; char ledc = 0; /* Timer */ -char of = 0; -int oticks = 0; +volatile int oticks = 0; +unsigned long mnow; /* Pulse counter */ -char pstate = 0; +volatile char pstate = 0; char pval = 0; /* Switch */ -char sstate = 0; +volatile char sstate = 0; int stime = 0; /* Temp sensor */ -char tstate = 0; -char tlock = 0; +volatile char tstate = 0; +volatile char tlock = 0; unsigned long tstart; unsigned long ttime; unsigned long ttimea = 10000; +char tavgok = 0; +/* Conversion loop */ +int tempk; +volatile ktok = 0; /* Zero-cross detector*/ +volatile char zok = 0; +volatile char ztime = 0; /* Triac */ +char trstate = 0; +char tron = 0; +volatile char trtime; +volatile char trdelay = 0; void init(void) { - /* Timer init */ + /* Timer init + * Timer 0 cycles the Triac + * Timer 1 is used for global timing + * Timer 2 cycles the LED display + */ + OCR0A = 100; + TCCR0A = 2; + TCCR0B = 1; + TIMSK0 = 2; TCCR1A = 0; TCCR1B = 1; TIMSK1 = 1; + OCR2A = 16; + TCCR2A = 2; + TCCR2B = 4; + TIMSK2 = 2; /* * B0..2 = Pulse sensor * B3..5 = ISP * B6..7 = CLK */ - DDRB = 0x00; + DDRB = 0x38; PORTB = 0x07; PCMSK0 = 0x07; PCICR = 0x01; @@ -112,10 +136,10 @@ unsigned char bindisp(unsigned char num) return(ret); } -void display(char num) +void display(char num, char d0, char d1) { - dsp[0] = font[(num / 10) % 10]; - dsp[1] = font[num % 10]; + dsp[0] = font[(num / 10) % 10] | (d0?SEGP:0); + dsp[1] = font[num % 10] | (d1?SEGP:0); } void disphex(unsigned char num) @@ -126,54 +150,60 @@ void disphex(unsigned char num) unsigned long getticks(void) { - return(TCNT1 + (((unsigned long)oticks) << 16)); + uint16_t v; + unsigned long r; + + cli(); + v = TCNT1; + r = v + (((unsigned long)oticks) << 16); + if((TIFR1 & 0x01) && !(v & 0x8000)) + r += 0x10000; + sei(); + return(r); } void ledcycle(void) { - static uint16_t last = 0; uint8_t c, d, v; - if(TCNT1 - last > 500) { - last = TCNT1; - if(++leda >= 8) { - leda = 0; - if(++ledc >= 2) - ledc = 0; - } - if(dsp[ledc] & (1 << leda)) { - if(leda < 6) { - c = 1 << leda; - d = 0; - } else { - c = 0; - d = 0x10 << (leda - 6); - } - d |= ledc?0x40:0x80; + if(++leda >= 8) { + leda = 0; + if(++ledc >= 2) + ledc = 0; + } + if(dsp[ledc] & (1 << leda)) { + if(leda < 6) { + c = 1 << leda; + d = 0; } else { - c = d = 0; + c = 0; + d = 0x10 << (leda - 6); } - PORTC = c; - PORTD = (PORTD & 0x0f) | d; + d |= ledc?0x40:0x80; + } else { + c = d = 0; } + PORTC = c; + PORTD = (PORTD & 0x0f) | d; } void tempcycle(void) { - unsigned long now; - - now = getticks(); if(tstate == 0) { if((PIND & 8) && (tlock == 0)) { + cli(); PORTD |= 2; - tstart = now; + sei(); + tstart = mnow; tstate = 1; } } else if(tstate == 1) { - if(now - tstart > 1000) { + if(mnow - tstart > 1000) { + cli(); PORTD &= ~2; + sei(); tstate = 0; - tstart = now; + tstart = mnow; } } } @@ -184,22 +214,178 @@ void calcavg(void) tlock = 2; ttimea = ((ttimea * 15) + ttime) >> 4; tlock = 0; + tavgok = 1; + } +} + +void convcycle(void) +{ + static char state = 0; + static unsigned long last = 0; + static float a, ra, l, t; + + /* + * Theoretically: + * t = RC * ln(2) => R = t / (C * ln(2)) + * R = A * exp(B / T) => T = B / ln(R / A) + * T = B / ln(t / (A * C * ln(2))) + * Where: + * t = The measured time (s) + * R = The resistance of the thermistor (Ohm) + * C = The capacitance of the capacitor (F) + * T = The temperature (K) + * A, B are the thermistor-specific constants + * + * In the following code: + * a = ttimea as float + * C = 1e-6 / (A * C * ln(2)) + * ra = a * C + * l = ln(ra) + * t = B / l + * Note, temperature is in Kelvin + */ +#define C 10.819112 /* A is 0.1333469 */ +#define B 4020.0 + if(state == 0) { + if((mnow - last > 200000) && tavgok) { + a = (float)ttimea; + state = 1; + tavgok = 0; + last = mnow; + } + } else if(state == 1) { + ra = a * C; + state = 2; + } else if(state == 2) { + l = log(ra); + state = 3; + } else if(state == 3) { + t = B / l; + state = 4; + } else if(state == 4) { + tempk = (int)t; + ktok = 1; + state = 0; } } int main(void) { - int cur; + int state, cur, run, rstate, delta; + unsigned long utime; - cur = 0; + state = 1; + cur = eeprom_read_byte(0); + if(cur < 0) + cur = 0; + if(cur > 100) + cur = 100; + run = 0; + rstate = 0; + utime = getticks(); init(); sei(); - display(0); + if(cur < 100) + display(cur, 0, 0); + else + dsp[0] = dsp[1] = SEGG; + while(1) { - ledcycle(); + mnow = getticks(); tempcycle(); calcavg(); + convcycle(); +#if 1 + /* + * User interface + */ + if(state == 0) { + /* Display temperature */ + if(ktok) { + ktok = 0; + if((tempk >= 273) && (tempk <= 372)) { + display(tempk - 273, 0, run); + } else { + dsp[0] = SEGG; + dsp[1] = SEGG | (run?SEGP:0); + } + } + if(pval != 0) + state = 1; + if(sstate == 2) { + sstate = 0; + if(stime > 10) + state = 2; + else + run = !run; + } + } else if(state == 1) { + /* Temp setting */ + if(pval != 0) { + cur += pval; + pval = 0; + if(cur < 0) + cur = 0; + if(cur > 100) + cur = 100; + utime = mnow; + } + if(mnow - utime > 2000000) { + state = 0; + eeprom_write_byte(0, cur); + } + if(sstate == 2) { + run = !run; + sstate = 0; + } + if(cur < 100) { + display(cur, 0, run); + } else { + dsp[0] = SEGG; + dsp[1] = SEGG | (run?SEGP:0); + } + } else if(state == 2) { + /* Display raw temp time reading */ + if(ttimea < 20000) { + display((ttimea / 100) % 100, 1, ttimea >= 10000); + } else { + display(ttimea / 1000, 0, 0); + } + if(sstate == 2) { + state = 0; + sstate = 0; + } + } + /* + * Set Triac to match temperature + */ + if(run) { + delta = cur - (tempk - 273); + if(rstate == 0) { + if(delta > 0) { + tron = 1; + if(delta > 8) { + /* For some reason, the Triac currently doesn't + * trigger on one of the AC half-cycles below 0.7 + * ms. */ + trdelay = 7; + } else { + trdelay = 75 - (delta * 5); + } + } else { + tron = 0; + rstate = 1; + } + } else if(rstate == 1) { + tron = 0; + if(delta >= 2) + rstate = 0; + } + } else { + tron = 0; + } +#endif /* dsp[0] = bindisp((ttimea & 0xff00) >> 8); dsp[1] = bindisp(ttimea & 0x00ff); @@ -207,6 +393,10 @@ int main(void) /* disphex((ttimea & 0xff000) >> 12); */ +#if 0 + /* + Temp display + */ if(ttimea < 20000) { display((ttimea / 100) % 100); dsp[0] |= SEGP; @@ -215,8 +405,45 @@ int main(void) } else { display(ttimea / 1000); } - +#endif +#if 0 + /* + * ZVD debug + */ + if(zok) { + if(++cur > 99) + cur = 0; + display(cur); + zok = 0; + } +#endif +#if 0 /* + Phony Triac control + */ + if(pval != 0) { + cur += pval; + if(cur < 0) + cur = 0; + if(cur > 99) + cur = 99; + display(cur); + trdelay = 99 - cur; + pval = 0; + } + if(sstate == 2) { + tron = !tron; + sstate = 0; + } + if(tron) + dsp[1] |= SEGP; + else + dsp[1] &= ~SEGP; +#endif +#if 0 + /* + Pulse counter display + */ cur += pval; pval = 0; if(sstate == 2) { @@ -233,12 +460,16 @@ int main(void) } else { display(cur); } - */ + if(PINB & 4) + dsp[1] |= SEGP; +#endif } } ISR(SIG_INTERRUPT0) { + ztime = 0; + zok = 1; } ISR(SIG_INTERRUPT1) @@ -256,30 +487,52 @@ ISR(SIG_INTERRUPT1) } } +ISR(SIG_OUTPUT_COMPARE0A) +{ + if(trstate == 0) { + ztime++; + if(tron && (ztime >= trdelay)) { + PORTD |= 1; + trstate = 1; + trtime = 0; + } + } else if(trstate == 1) { + trtime++; + if(trtime >= 5) { + PORTD &= ~1; + trstate = 0; + } + } +} + +ISR(SIG_OUTPUT_COMPARE2A) +{ + ledcycle(); +} + ISR(SIG_OVERFLOW1) { - of = 1; oticks++; } ISR(SIG_PIN_CHANGE0) { - if((sstate == 0) & ((PINB & 1) == 0)) { + if((sstate == 0) && !(PINB & 4)) { stime = oticks; sstate = 1; } - if((sstate == 1) & ((PINB & 1) == 1)) { + if((sstate == 1) && (PINB & 4)) { stime = oticks - stime; sstate = 2; } if(pstate == 0) { if((PINB & 2) == 0) { pstate = 1; - } else if((PINB & 4) == 0) { + } else if((PINB & 1) == 0) { pstate = 2; } } else if(pstate == 1) { - if((PINB & 4) == 0) { + if((PINB & 1) == 0) { pval++; pstate = 3; } else { @@ -293,7 +546,7 @@ ISR(SIG_PIN_CHANGE0) pstate = 0; } } else { - if((PINB & 2) && (PINB & 4)) + if((PINB & 2) && (PINB & 1)) pstate = 0; } }