/* Firmware for current sensor, the 89S52 Project Board. The sensor is tied to analog input channel1. Channel0 is available for experimenting with another sensors. Copyright (C) 2007, Wichit Sirichote, kswichit@kmitl.ac.th */ #include #include float read_temp1(void); float read_temp1_filter(void); sbit ADCDATA = P1^4; sbit CS = P3^6; sbit CLK = P2^4; sbit LEDDATA = P3^7; sbit STROBE = P2^5; sbit LED = P1^2; char segment[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x39}; int timer3, timer4; char cputick; char buffer[4]; unsigned int x1,x2,x3,x4,x5,x6,x7,x8,x9,x10; unsigned int temp1; int read_current(void); // return 12-bit ADC data 0 - 4095 int read_ADC(char n) { char i,channel; int k; k=0; CS=0; if(n==0) channel=0x0d; else channel=0x0f; for(i=0;i<4;i++) { CLK = 0; if(channel&8) ADCDATA = 1; else ADCDATA = 0; CLK = 1; channel <<=1; } ADCDATA = 1; CLK = 0; for(i=0;i<12;i++) { k<<=1; CLK=1; CLK=0; if(ADCDATA) k|=1; else k&=~1; } CS = 1; return k&0xfff; } // write 32-bit data to CMOS shift register 4094 void write_led() { char m,n; for(n=0;n<4;n++) { for(m=0;m<8;m++) { if(buffer[n]&0x80) LEDDATA=1; else LEDDATA=0; CLK =1; buffer[n]<<=1; CLK =0; } } STROBE=1; // strobe all 32-bit to the output ; STROBE=0; } // display temperature in celcius void update() { //temp1=read_temp1_filter()*10; //temp1=(low_pass_filter1()); // display temperature in F degrees temp1 = read_current(); buffer[0]=segment[temp1/1000]; temp1=temp1%1000; buffer[1]=segment[temp1/100]; temp1 = temp1%100; buffer[2]=segment[temp1/10]; buffer[3]=segment[temp1%10]; } /* // display ADC raw data 0-4095 for 0 to +5V input at channel 0 // select below function when calibrating the input sensor! void update() { temp1=read_ADC(1); buffer[0]=segment[temp1/1000]; temp1=temp1%1000; buffer[1]=segment[temp1/100]; temp1= temp1%100; buffer[2]=segment[temp1/10]; buffer[3]=segment[temp1%10]; } */ // print temperature to display void print_ADC() { if(++timer3>10) { timer3=0; update(); write_led(); } } // toggle LED every 50 ticks void blinkLED() { if(++timer4>50) { timer4 = 0; LED ^= 1; } } // return filtered data using 5-point moving average int low_pass_filter1(void) { x10=x9; x9=x8; x8=x7; x7=x6; x6=x5; x5=x4; x4=x3; x3=x2; x2=x1; x1=read_ADC(1); return(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)/10; } int read_current() { int i; float k=0; // for(i=0; read_ADC(1)<10 && i<100; i++) // continue; for (i=0; i<256; i++) { k+= read_ADC(1); } //return k/256; k/= 256; k*= .010; // LSB for 30A range return 220*k; // return WATT 220Vrms x Irms } //3.4A 0.411V 337 ADC // 1LSB 3.4A/337 = .010 // return calibrated temperature in celcius float read_temp1_filter(void) { return(0.0323*low_pass_filter1()-15.122); } void timer0int(void) interrupt 1 using 1 { TH0 = 0xd8; // reload value for 100Hz produced by 12MHz XTAL TL0 = 0xf0; // for 11.0592MHz, reload value = 0xDC00 cputick++; } void main() { EA=1; ET0=1; TMOD|=0x01; TR0=1; cputick =0; while(1) { while(!cputick) continue; cputick = 0; // below tasks will be executed every 10ms print_ADC(); blinkLED(); } }