fc797a6b4b43b53b93d01b738a8c567488448727
[Arduino-Nano-VA-meter] / main.c
1 #define F_CPU 16000000L
2
3 #include <avr/io.h>
4 #include <util/delay.h>
5
6 #define USART_BAUDRATE 9600
7 #define UBRR_VALUE (((F_CPU/(USART_BAUDRATE*16UL)))-1)
8
9 // this will output only changes on serial
10 #define SERIAL_CHANGES 1
11
12 void serial_init(){
13         // initialize USART (must call this before using it)
14         UBRR0=UBRR_VALUE; // set baud rate
15         UCSR0B|=(1<<TXEN0); //enable transmission only
16         UCSR0C|=(1<<UCSZ01)|(1<<UCSZ01); // no parity, 1 stop bit, 8-bit data
17 }
18
19 void serial_send(unsigned char data){
20         // send a single character via USART
21         while(!(UCSR0A&(1<<UDRE0))){}; //wait while previous byte is completed
22         UDR0 = data; // Transmit data
23 }
24
25 void serial_string(const char* s){
26     while(*s){
27                 serial_send(*s++);
28         }
29 }
30
31 void serial_break(){
32         serial_send(10); // new line 
33         serial_send(13); // carriage return
34 }
35 void serial_comma(){
36         serial_send(','); // comma
37         serial_send(' '); // space
38 }
39
40 void serial_number(uint32_t val){ // send a number as ASCII text
41         uint32_t divby=1000000000; // change by dataType
42         while (divby){
43                 serial_send('0'+val/divby);
44                 val-=(val/divby)*divby;
45                 divby/=10;
46         }
47 }
48
49 void serial_binary(int val){ // send a number as ASCII text
50         char bitPos;
51         for(bitPos=8;bitPos;bitPos--){
52                 if ((val>>(bitPos-1))&1){serial_send('1');}
53                 else {serial_send('0');}
54         }
55 }
56         
57 void serial_test(){
58         char i;
59         serial_break();
60         for(i=65;i<65+26;i++){
61                 serial_send(i);
62         }
63         serial_break();
64 }
65
66
67
68
69 ////////////////////////////////////////////////////////////////////////
70 ////////////////////////////////////////////////////////////////////////
71 ////////////////////////////////////////////////////////////////////////
72 ////////////////////////////////////////////////////////////////////////
73 ////////////////////////////////////////////////////////////////////////
74 ////////////////////////////////////////////////////////////////////////
75 ////////////////////////////////////////////////////////////////////////
76 ////////////////////////////////////////////////////////////////////////
77 ////////////////////////////////////////////////////////////////////////
78 ////////////////////////////////////////////////////////////////////////
79 ////////////////////////////////////////////////////////////////////////
80 ////////////////////////////////////////////////////////////////////////
81 ////////////////////////////////////////////////////////////////////////
82
83 // these variables will hold an instant capture of all input pins
84 volatile uint8_t regB;
85 volatile uint8_t regC;
86 volatile uint8_t regD;
87
88 // these values will hold the current/voltage value
89 volatile char current[4];
90 volatile char voltage[4];
91
92 volatile int display_sum = 0;
93 volatile int last_display_sum = 0;
94
95
96 void read_capture(){
97     // load the volatile capture variables with tue current pin state
98     regB=PINB;
99     regC=PINC;
100     regD=PIND;
101 }
102
103 char saved_letter(){
104     // returns the letter (1-8) of the segments stored in read_capture
105     // returned value will be in ASCII
106     // returns ? if no letter is selected, or if it's confusing
107     
108     // start by creating a "letter" variable which defines pin states
109     uint8_t letter=0;    
110     if(regC&(1<<PC0)){letter|=(1<<7);} // letter 1 (voltage MSB)
111     if(regC&(1<<PC3)){letter|=(1<<6);} // letter 2
112     if(regC&(1<<PC4)){letter|=(1<<5);} // letter 3
113     if(regD&(1<<PD2)){letter|=(1<<4);} // letter 4
114     if(regB&(1<<PB3)){letter|=(1<<3);} // letter 5 (current MSB)
115     if(regD&(1<<PD4)){letter|=(1<<2);} // letter 6
116     if(regD&(1<<PD3)){letter|=(1<<1);} // letter 7
117     if(regD&(1<<PD5)){letter|=(1<<0);} // letter 8
118
119     // try to match expected pin states
120     if (letter==0b10000000) {return '1';}
121     if (letter==0b01000000) {return '2';}
122     if (letter==0b00100000) {return '3';}
123     if (letter==0b00010000) {return '4';}
124     if (letter==0b00001000) {return '5';}
125     if (letter==0b00000100) {return '6';}
126     if (letter==0b00000010) {return '7';}
127     if (letter==0b00000001) {return '8';}
128     return '?';    
129 }
130
131 volatile uint8_t saved_period;
132 char saved_number(){
133     // returns the numerical value (0-9) stored in read_capture
134     // returned value will be in ASCII
135     // returns 0 if no letter is selected, or if it's confusing
136     int segments=0;
137     if(regC&(1<<PC1)){segments|=(1<<7);} // A (MSB)
138     if(regC&(1<<PC5)){segments|=(1<<6);} // B
139     if(regD&(1<<PD7)){segments|=(1<<5);} // C
140     if(regB&(1<<PB1)){segments|=(1<<4);} // D
141     if(regB&(1<<PB2)){segments|=(1<<3);} // E
142     if(regC&(1<<PC2)){segments|=(1<<2);} // F
143     if(regD&(1<<PD6)){segments|=(1<<1);} // G (LSB)
144     //if(regB&(1<<PB0)){}//H
145     
146     if(segments==0b00001000) {return '9';}
147     if(segments==0b00000000) {return '8';}
148     if(segments==0b00011110) {return '7';}
149     if(segments==0b01000000) {return '6';}
150     if(segments==0b01001000) {return '5';}
151     if(segments==0b10011000) {return '4';}
152     if(segments==0b00001100) {return '3';}
153     if(segments==0b00100100) {return '2';}
154     if(segments==0b10011110) {return '1';}
155     if(segments==0b00000010) {return '0';}
156     return '?';
157 }
158
159 uint8_t capture_letter(char letter){
160     // loops until the current letter has been captured
161     uint16_t tries=1000; // trial and error reveals this works
162     while (tries){
163         tries--;
164         read_capture(); // take a new read
165         if (saved_letter()==letter) {
166             if (saved_number()!='?'){
167                 if (letter=='1'){voltage[0]=saved_number();}
168                 if (letter=='2'){voltage[1]=saved_number();}
169                 if (letter=='3'){voltage[2]=saved_number();}
170                 if (letter=='4'){voltage[3]=saved_number();}
171                 if (letter=='5'){current[0]=saved_number();}
172                 if (letter=='6'){current[1]=saved_number();}
173                 if (letter=='7'){current[2]=saved_number();}
174                 if (letter=='8'){current[3]=saved_number();}
175                 return 1;
176             }
177         }
178     }
179     return 0;
180 }
181
182 void capture_full(){
183     // capture even value of every letter
184     char i;
185     char j;
186     for(i=0;i<4;i++) {voltage[i]=' ';}
187     for(i=0;i<4;i++) {current[i]=' ';}
188     
189     for(i=0;i<8;i++){ // for each of the 8 letters
190         for (j=0;j<10;j++){ // try to capture each letter 10 times
191             if (capture_letter('1'+i)) {break;}
192         }
193     }
194
195 #if SERIAL_CHANGES
196     // don't send same values over serial
197     for(i=0;i<4;i++) {
198             display_sum = voltage[i] + current[i];
199     }
200     if ( display_sum == last_display_sum ) {
201             return;
202     } else {
203             last_display_sum = display_sum;
204     }
205 #endif
206
207     for(i=0;i<4;i++) {
208         serial_send(voltage[i]);
209         if (i==1){serial_send('.');}
210     }
211     serial_send(',');
212     for(i=0;i<4;i++) {
213         serial_send(current[i]);
214         if (i==2){serial_send('.');}
215     }
216     serial_break();
217 }
218
219 volatile uint16_t checksum;
220 int main(void){
221     serial_init();
222         for(;;){
223         //serial_send(getDigitForLetter('1'));
224         capture_full();
225         //capture_letter('4');
226         //serial_break();
227         }
228 }