How to Build a USBtinyISP: Low-Cost DIY AVR Programmer
Atmel AVR chips power a lot of hobby and embedded projects, small, cheap, well-documented. To get code onto them you …
By Prabeesh Keezhathra
- 3 minutes read - 500 wordsThe time constant of an RC circuit equals R * C (in seconds). It is the time for the capacitor to charge through the resistor to 63.2% of the supply voltage, or to discharge to 36.8% of its starting level.
The ATmega8’s ADC samples the voltage across the capacitor continuously. A digital output pin (PB0) supplies the input voltage to the RC network. The moment PB0 goes high, Timer1 starts counting. When the ADC reading hits 63.2% of the rail (roughly 161 out of 255 for a 5 V supply), we capture the timer value.
Timer1 is a 16-bit counter, clocked at 8 MHz with a 1024 prescaler. To convert timer ticks to seconds, multiply by 1024 / 8000000. An LCD shows both the raw tick count and the ADC reading.
| R | C | Calculated RC | Timer ticks | Measured RC |
|---|---|---|---|---|
| 1 kOhm | 100 uF | 0.100 s | 846 | 0.108 s |
| 2 kOhm | 100 uF | 0.200 s | 1864 | 0.239 s |
Both within ~20% of the ideal value, which is typical for low-precision components.
1
2#include<avr/io.h>
3#define F_CPU 8000000UL
4#include <util/delay.h>
5
6#define RS 6 //PD6
7#define EN 7 //PD7
8#define databits PORTC //PC0 to PC3
9#define row1 cmd(0x80)
10#define row2 cmd(0xc0)
11
12void adc_init()
13{
14 //select AVCC reference voltage , left alignment of data and ADC4
15 ADMUX=((1<<REFS0)|(1<<ADLAR)|(1<<MUX2));
16
17 //enable ADC, set prescaler to divide the clock by 64 and auto triggering mode
18 ADCSRA=((1<<ADEN)|(1<<ADFR)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));
19
20}
21
22void conversion()
23{
24 //start conversion
25 ADCSRA|=(1<<ADSC);
26}
27
28void port_init()
29{
30 DDRC = 0xcf;
31 DDRD = (1 << RS)|(1 << EN);
32}
33
34void LCD_STROBE(void)
35{
36 PORTD |= (1 << EN);
37 _delay_us(1);
38 PORTD &= ~(1 << EN);
39}
40
41void data(unsigned char c)
42{
43 PORTD |= (1 << RS);
44 _delay_us(50);
45 databits = (c >> 4);
46 LCD_STROBE();
47 databits = (c);
48 LCD_STROBE();
49}
50
51void cmd(unsigned char c)
52{
53 PORTD &= ~(1 << RS);
54 _delay_us(50);
55 databits = (c >> 4);
56 LCD_STROBE();
57 databits = (c);
58 LCD_STROBE();
59}
60
61void clear(void)
62{
63 cmd(0x01);
64 _delay_ms(5);
65}
66
67void lcd_init()
68{
69 _delay_ms(15);
70 cmd(0x30);
71 _delay_ms(1);
72 cmd(0x30);
73 _delay_us(100);
74 cmd(0x30);
75 cmd(0x28); // Function set (4-bit interface, 2 lines, 5*7Pixels)
76 cmd(0x28); // Function set (4-bit interface, 2 lines, 5*7Pixels)
77 cmd(0x0c); // Make cursorinvisible
78 clear(); // Clear screen
79 cmd(0x6); // Set entry Mode(auto increment of cursor)
80}
81
82void print(char *p)
83{
84 while(*p) data(*p++);
85}
86
87void main()
88{
89 char a[5],b[5];
90 int c,d;
91 DDRB=0x01;
92 _delay_ms(50);
93 TCCR1B|=(1<<CS10)|(1<<CS12);//prescale 1024
94 port_init();
95 adc_init();
96 lcd_init();
97 PORTB=0x01;//applying vcc to RC circuit
98 TCNT1=0x00;//start the timer
99
100 while(1)
101 {
102 conversion();
103
104 while(!( ADIF));
105
106 if(ADCH==161)//63% of the input voltage
107 {
108 c=TCNT1;
109 d=ADCH;
110 itoa(c,a,10);//integer to ASCII
111 itoa(d,b,10);//integer to ASCII
112 row1;
113 print(a);//showing timer value
114 row2;
115 print(b);//showing adc value
116 }
117 }
118}