/* * * esr.c ... firmware for an ESR-meter based on atmega MCU * * * * Copyright (C) 2010 Jiri Pittner * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * * * */ #include "backward.h" #include #include #include #include #include #include #include //this bridge configuration does not seem to be a proper circuit for capacity measurement //this is also not feasible due to anharmonic signal - everything works only for negligible Xc //phase shifts at the bridge are wrongly evaluated by this circuit which compares both bridge halves at a given time //it can be used ONLY when Xc is completely negligible with respect to R //-> user has to set manually appropriate measurement frequency according to the capacitance value //But VERY big capaciors, like 10000uF with very small ESR below about 0R2 will not be measured accurately too //Nevertheless, it is good enough to identify bad capacitors for repair work //ATmega8L at 7.3728 MHz //!!!! brownout off - fuse L =0xef //PB0 - switching of power //PB1=oc1a - signal generation //PD5 RS //PD6 RW //PD7 E //PC0-PC3=DB4-7 display //PD2=int0= right button //PC4 = voltage battery //PC5= measurement //reserved for future gain control: PD3,PD4,PB2 void printP (PGM_P string){ char c; c=pgm_read_byte(string); while (c) { loop_until_bit_is_set(UCSRA, UDRE); UDR = c; c=pgm_read_byte(++string); } return; } void print (char *string){ while (*string) { loop_until_bit_is_set(UCSRA, UDRE); UDR = *string++; } return; } void scan(char *string){ char c; do { do { loop_until_bit_is_set(UCSRA, RXC); c =UDR; } while bit_is_set(UCSRA, FE); *string++ = c; //echo the character loop_until_bit_is_set(UCSRA, UDRE); UDR = c; } while ( c != '\r' ); loop_until_bit_is_set(UCSRA, UDRE); UDR = '\n'; string[-1]=0; } #define UCR UCSRB #define UART_INIT(baud) { \ UBRRH=0; \ UBRRL= (XTAL/baud+15)/16-1; \ UCSRB=(1<>12; } uint32_t measure(uint16_t nrep) { uint16_t v; uint32_t vv=0; //enable A/D converter in single conversion mode ADMUX= 5; while(nrep-- > 0) { ADCSRA= (1<>4); lcd_w4bit(rs,x); } void lcd_clear(void) { lcd_wbyte(0,0x01); delay_xs(30000); } void lcd_init(void) { lcd_init4bit(); lcd_wbyte(0,0x28); lcd_wbyte(0,0x08); lcd_clear(); lcd_wbyte(0,0x06); lcd_wbyte(0,0x0c); } void lcd_print(char *t) { while(*t) if(*t=='\n') {++t; lcd_wbyte(0,0xc0);} else lcd_wbyte(1,*t++); } void lcd_printP(char *t) { char c=pgm_read_byte(t); while(c) if(c=='\n') {c=pgm_read_byte(++t); lcd_wbyte(0,0xc0);} else {lcd_wbyte(1,c); c=pgm_read_byte(++t);} } void lcd_print8(char *t) { uint8_t l=0; while(*t) {lcd_wbyte(1,*t++); ++l;} while(l<8) {lcd_wbyte(1,' '); ++l;} } void lcd_cursor(uint8_t r, uint8_t c) { lcd_wbyte(0,0x80+c+(r<<6)); } //start signal generation at x kilohertz void siggen(uint32_t x) { if(x==0) { cbi(DDRB,PB1); TCCR1B=0; TCCR1A=0; return; } sbi(DDRB,PB1); TCNT1=0; OCR1A= XTAL/(2*x); TCCR1A= (1<>= 4; if(r=2) cbi(GIMSK,INT0); } int main(void) { char c[20]; UART_INIT(115200); printP(PSTR("Start!\n")); cbi(DDRD,PD2); sbi(PORTD,PD2); //right button sbi(SREG,7); cbi(MCUCR,ISC01); sbi(MCUCR,ISC00); //fall edge interrupt sbi(GIMSK,INT0); siggen(freqs[freqindex]); lcd_init(); strcpy(c,"Battery \n"); printvoltage(voltage(),c+9); lcd_print(c); delay_ms(2000); lcd_clear(); delay_ms(100); printfreq(freqs[freqindex],c); lcd_cursor(1,0); lcd_print(c); uint16_t ii=0; while(1) { ++ii; //about twice a second uint8_t i; uint32_t v=measure(1<UNBALLANCE*(1L<=2) { freqindex = (freqindex+1)%N_freqs; if(freqindex==0) lcd_init(); siggen(freqs[freqindex]); delay_ms(300); buttonpressed=0; sbi(GIMSK,INT0); printfreq(freqs[freqindex],c); lcd_cursor(1,0); lcd_print(c); } if(ii>=120) break; //poweroff if unused for about a minute } poweroff(); };