Rev 193 Rev 195
1 // Firmware pro pripravek pro testovani slunecnich clanku CT01A 1 // Firmware pro pripravek pro testovani slunecnich clanku CT01A
2 // (c) miho 2005 2 // (c) miho 2005
3 // 3 //
4 // 1.00 Zakladni verze 4 // 1.00 Zakladni verze
5   5  
6 #include <16F88.h> 6 #include <16F88.h>
7 #fuses INTRC_IO, NOWDT, NOPUT, NOPROTECT, NOBROWNOUT, MCLR, NOLVP, NOCPD, NODEBUG, CCPB3 7 #fuses INTRC_IO, NOWDT, NOPUT, NOPROTECT, NOBROWNOUT, MCLR, NOLVP, NOCPD, NODEBUG, CCPB3
8   8  
9 #use delay(clock=8000000) // interni RC oscilator 9 #use delay(clock=8000000) // interni RC oscilator
10   10  
11 #use RS232 (baud=9600, xmit=PIN_B5, rcv=PIN_B2) 11 #use RS232 (baud=9600, xmit=PIN_B5, rcv=PIN_B2)
12   12  
13 #include <eeprom.c> // Podpora zapisu promennych do EEPROM 13 #include <eeprom.c> // Podpora zapisu promennych do EEPROM
14   14  
15 #define LCD_E PIN_A2 15 #define LCD_E PIN_A2
16 #define LCD_RS PIN_A7 16 #define LCD_RS PIN_A7
17 #define LCD_D0 PIN_A3 17 #define LCD_D0 PIN_A3
18 #define LCD_D1 PIN_A4 18 #define LCD_D1 PIN_A4
19 #define LCD_D2 PIN_B7 19 #define LCD_D2 PIN_B7
20 #define LCD_D3 PIN_B6 20 #define LCD_D3 PIN_B6
21   21  
22 #include <LCD.C> // podpora LCD displeje 22 #include <LCD.C> // podpora LCD displeje
23   23  
24   24  
25 // Globalni nastaveni a globalni promenne 25 // Globalni nastaveni a globalni promenne
26 // 26 //
27 #define Ofset 5 // ofset PWM pro nulovy proud 27 #define Ofset 5 // ofset PWM pro nulovy proud
28 float Vref; // konstanta voltmetru (napeti 1 LSB prevodniku) 28 float Vref; // konstanta voltmetru (napeti 1 LSB prevodniku)
29 int1 Xrs; // 1 znamena vystup na RS232 29 int1 Xrs; // 1 znamena vystup na RS232
30 int1 Xlcd; // 1 znamena vystup na LCD displej 30 int1 Xlcd; // 1 znamena vystup na LCD displej
31   31  
32   32  
33 signed int16 Convert(int8 Chanel) 33 signed int16 Convert(int8 Chanel)
34 // Prevod AD prevodnikem ze zadaneho kanalu 34 // Prevod AD prevodnikem ze zadaneho kanalu
35 // Vysledek je na 10 bitu, doba prevodu 1.8ms 35 // Vysledek je na 10 bitu, doba prevodu 1.8ms
36 { 36 {
37 unsigned int16 Data; 37 unsigned int16 Data;
38 int i; 38 int i;
39   39  
40 // AD prevod s prumerovanim 32x 40 // AD prevod s prumerovanim 32x
41 Data=0; 41 Data=0;
42 *ADCON0 = 0x41 | Chanel << 3; // frekvence f/16, zapnout, cislo kanalu 42 *ADCON0 = 0x41 | Chanel << 3; // frekvence f/16, zapnout, cislo kanalu
43 *ADCON1 = 0xC0; // right justify, Vdd a Vss jako reference 43 *ADCON1 = 0xC0; // right justify, Vdd a Vss jako reference
44 delay_us(100); // ustaleni vstupu 44 delay_us(100); // ustaleni vstupu
45 for(i=32;i!=0;i--) 45 for(i=32;i!=0;i--)
46 { 46 {
47 *ADCON0 |= 4; // start prevodu 47 *ADCON0 |= 4; // start prevodu
48 delay_us(50); // prevod 48 delay_us(50); // prevod
49 Data += (int16)*ADRESH<<8|*ADRESL; // vysledek se nascita 49 Data += (int16)*ADRESH<<8|*ADRESL; // vysledek se nascita
50 } 50 }
51 Data=Data>>5; // odcin prumerovani 51 Data=Data>>5; // odcin prumerovani
52   52  
53 // Vysledek 53 // Vysledek
54 return Data; // vysledek 0 az 1023 54 return Data; // vysledek 0 az 1023
55 } 55 }
56   56  
57   57  
58 float GetVoltage() 58 float GetVoltage()
59 // Provede nacteni dat z AD prevodniku a prevod na float napeti 59 // Provede nacteni dat z AD prevodniku a prevod na float napeti
60 { 60 {
61 float Data; 61 float Data;
62 Data=(Convert(0)-Convert(1))*Vref; 62 Data=(Convert(0)-Convert(1))*Vref;
63 return Data; 63 return Data;
64 } 64 }
65   65  
66   66  
67 void SetPWM(int8 Data) 67 void SetPWM(int8 Data)
68 // Nastaveni dat do PWM vystupu 68 // Nastaveni dat do PWM vystupu
69 // Celych 8 bitu, doba behu 10ms 69 // Celych 8 bitu, doba behu 10ms
70 { 70 {
71 *CCPR1L = Data>>2; // hornich 6 bitu 71 *CCPR1L = Data>>2; // hornich 6 bitu
72 *CCP1CON = *CCP1CON & 0x0F | (Data & 3)<<4; // spodni 2 bity 72 *CCP1CON = *CCP1CON & 0x0F | (Data & 3)<<4; // spodni 2 bity
73 delay_ms(50); // doba na ustaleni 73 delay_ms(50); // doba na ustaleni
74 } 74 }
75   75  
76   76  
77 void GetString(char *s, int max) 77 void GetString(char *s, int max)
78 // Nacte ze seriovky retezec, 78 // Nacte ze seriovky retezec,
79 // dela echo a hlida delku retezce 79 // dela echo a hlida delku retezce
80 { 80 {
81 int len; // aktualni delka 81 int len; // aktualni delka
82 char c; // nacteny znak 82 char c; // nacteny znak
83   83  
84 max--; 84 max--;
85 len=0; 85 len=0;
86 do { 86 do {
87 c=getc(); 87 c=getc();
88 if(c==8) { // Backspace 88 if(c==8) { // Backspace
89 if(len>0) { 89 if(len>0) {
90 len--; 90 len--;
91 putc(c); 91 putc(c);
92 putc(' '); 92 putc(' ');
93 putc(c); 93 putc(c);
94 } 94 }
95 } else if ((c>=' ')&&(c<='~')) 95 } else if ((c>=' ')&&(c<='~'))
96 if(len<max) { 96 if(len<max) {
97 s[len++]=c; 97 s[len++]=c;
98 putc(c); 98 putc(c);
99 } 99 }
100 } while(c!=13); 100 } while(c!=13);
101 s[len]=0; 101 s[len]=0;
102 } 102 }
103   103  
104   104  
105 float atof(char *s) 105 float atof(char *s)
106 // Prevod retezce na float 106 // Prevod retezce na float
107 { 107 {
108 float pow10 = 1.0; 108 float pow10 = 1.0;
109 float result = 0.0; 109 float result = 0.0;
110 int sign = 0; 110 int sign = 0;
111 char c; 111 char c;
112 int ptr = 0; 112 int ptr = 0;
113   113  
114 c = s[ptr++]; 114 c = s[ptr++];
115   115  
116 if ((c>='0' && c<='9') || c=='+' || c=='-' || c=='.') { 116 if ((c>='0' && c<='9') || c=='+' || c=='-' || c=='.') {
117 if(c == '-') { 117 if(c == '-') {
118 sign = 1; 118 sign = 1;
119 c = s[ptr++]; 119 c = s[ptr++];
120 } 120 }
121 if(c == '+') 121 if(c == '+')
122 c = s[ptr++]; 122 c = s[ptr++];
123   123  
124 while((c >= '0' && c <= '9')) { 124 while((c >= '0' && c <= '9')) {
125 result = 10*result + c - '0'; 125 result = 10*result + c - '0';
126 c = s[ptr++]; 126 c = s[ptr++];
127 } 127 }
128   128  
129 if (c == '.') { 129 if (c == '.') {
130 c = s[ptr++]; 130 c = s[ptr++];
131 while((c >= '0' && c <= '9')) { 131 while((c >= '0' && c <= '9')) {
132 pow10 = pow10*10; 132 pow10 = pow10*10;
133 result += (c - '0')/pow10; 133 result += (c - '0')/pow10;
134 c = s[ptr++]; 134 c = s[ptr++];
135 } 135 }
136 } 136 }
137   137  
138 } 138 }
139   139  
140 if (sign == 1) 140 if (sign == 1)
141 result = -result; 141 result = -result;
142 return(result); 142 return(result);
143 } 143 }
144   144  
145   145  
146 signed int atoi(char *s) 146 signed int atoi(char *s)
147 // Preved retezec na int (jen dekadicka cisla) 147 // Preved retezec na int (jen dekadicka cisla)
148 { 148 {
149 signed int result; 149 signed int result;
150 int sign, index; 150 int sign, index;
151 char c; 151 char c;
152   152  
153 index = 0; 153 index = 0;
154 sign = 0; 154 sign = 0;
155 result = 0; 155 result = 0;
156   156  
157 // Omit all preceeding alpha characters 157 // Omit all preceeding alpha characters
158 if(s) 158 if(s)
159 c = s[index++]; 159 c = s[index++];
160   160  
161 // increase index if either positive or negative sign is detected 161 // increase index if either positive or negative sign is detected
162 if (c == '-') 162 if (c == '-')
163 { 163 {
164 sign = 1; // Set the sign to negative 164 sign = 1; // Set the sign to negative
165 c = s[index++]; 165 c = s[index++];
166 } 166 }
167 else if (c == '+') 167 else if (c == '+')
168 { 168 {
169 c = s[index++]; 169 c = s[index++];
170 } 170 }
171   171  
172 while (c >= '0' && c <= '9') 172 while (c >= '0' && c <= '9')
173 { 173 {
174 result = 10*result + (c - '0'); 174 result = 10*result + (c - '0');
175 c = s[index++]; 175 c = s[index++];
176 } 176 }
177   177  
178 if (sign == 1) 178 if (sign == 1)
179 result = -result; 179 result = -result;
180   180  
181 return(result); 181 return(result);
182 } 182 }
183   183  
184   184  
185 void Xputc(char c) 185 void Xputc(char c)
186 // Spolecna procedura pro vystup znaku na LCD a RS232 186 // Spolecna procedura pro vystup znaku na LCD a RS232
187 // dle stavu promennych Xrs a Xlcd 187 // dle stavu promennych Xrs a Xlcd
188 { 188 {
189 if (Xrs) 189 if (Xrs)
190 if(c!='\n') putc(c); // vystup na RS232 (neposilej LF) 190 if(c!='\n') putc(c); // vystup na RS232 (neposilej LF)
191 if (Xlcd) lcd_putc(c); // vystup na LCD displej 191 if (Xlcd) lcd_putc(c); // vystup na LCD displej
192 } 192 }
193   193  
194   194  
195 void Calibrate() 195 void Calibrate()
196 // Procedura pro kalibraci 196 // Procedura pro kalibraci
197 { 197 {
198 #define LINE_LEN 40 // delka retezce 198 #define LINE_LEN 40 // delka retezce
199 char Line[LINE_LEN]; // retezec 199 char Line[LINE_LEN]; // retezec
200 int8 Data; // nacteny proud 0 az 250 200 int8 Data; // nacteny proud 0 az 250
201 float FData; // nactene rozdilove napeti 201 float FData; // nactene rozdilove napeti
202   202  
203 lcd_clr(); 203 lcd_clr();
204 printf(Xputc,"\n\rCalibration\r\n"); 204 printf(Xputc,"\n\rCalibration\r\n");
205 for(;1;) 205 for(;1;)
206 { 206 {
207 Xrs=1; 207 Xrs=1;
208 Xlcd=1; 208 Xlcd=1;
209 GetString(Line,LINE_LEN); 209 GetString(Line,LINE_LEN);
210 if (*Line=='q') 210 if (*Line=='q')
211 { 211 {
212 // Ukonceni procesu kalibrace 212 // Ukonceni procesu kalibrace
213 SetPWM(0); // vypni proud 213 SetPWM(0); // vypni proud
214 printf("\n\r"); // odradkuj na terminalu 214 printf("\n\r"); // odradkuj na terminalu
215 EE_WR(0,Vref); // uloz kalibraci do EEPROM 215 EE_WR(0,Vref); // uloz kalibraci do EEPROM
216 return; // navrat 216 return; // navrat
217 } 217 }
218 else if (*Line=='v') 218 else if (*Line=='v')
219 { 219 {
220 // Zadani nove hodnoty Vref 220 // Zadani nove hodnoty Vref
221 Vref=atof(Line+1)/1023; // referencni napeti na 1 LSB 221 Vref=atof(Line+1)/1023; // referencni napeti na 1 LSB
222 printf("\r\n"); 222 printf("\r\n");
223 } 223 }
224 else if(*Line) 224 else if(*Line)
225 { 225 {
226 // Zadan novy proud 226 // Zadan novy proud
227 Data=atoi(Line); // preved retezec na cislo 227 Data=atoi(Line); // preved retezec na cislo
228 printf(Xputc," Set %3umA\r\n",Data); 228 printf(Xputc," Set %3umA\r\n",Data);
229 SetPWM(Data+Ofset); // nastav proud 229 SetPWM(Data+Ofset); // nastav proud
230 delay_ms(100); // cas na ustaleni 230 delay_ms(100); // cas na ustaleni
231 } 231 }
232 // Jeden cyklus mereni 232 // Jeden cyklus mereni
233 FData=GetVoltage(); 233 FData=GetVoltage();
234 printf(Xputc,"%1.2fV \r\n",FData); 234 printf(Xputc,"%1.2fV \r\n",FData);
235 } 235 }
236 lcd_clr(); // smaz displej 236 lcd_clr(); // smaz displej
237 } 237 }
238   238  
239   239  
240 void AutoRun() 240 void AutoRun()
241 // AutoRun - automaticke mereni cele zatezovaci krivky 241 // AutoRun - automaticke mereni cele zatezovaci krivky
242 { 242 {
243 float FData; // zmerene napeti 243 float FData; // zmerene napeti
244 int8 i; // promenna cyklu - proud v mA 244 int8 i; // promenna cyklu - proud v mA
245   245  
246 Xrs=0; // vystup neni na RS232 246 Xrs=0; // vystup neni na RS232
247 Xlcd=1; // vystup je na LCD 247 Xlcd=1; // vystup je na LCD
248 printf(Xputc,"\fAutoRun"); // napis na LCD 248 printf(Xputc,"\fAutoRun"); // napis na LCD
249 Xrs=1; // hlavika jen na RS232 249 Xrs=1; // hlavika jen na RS232
250 Xlcd=0; 250 Xlcd=0;
251 printf(Xputc,"\r\nI[mA] U[V] P[mW]"); 251 printf(Xputc,"\r\nI[mA] U[V] P[mW]");
252 Xlcd=1; 252 Xlcd=1;
253   253  
254 SetPWM(0); // vypni proud 254 SetPWM(0); // vypni proud
255 delay_ms(100); // klidova podminka 255 delay_ms(100); // klidova podminka
256 for(i=0;i<=250;i++) // cyklus pres proud 0 az 250mA 256 for(i=0;i<=250;i++) // cyklus pres proud 0 az 250mA
257 { 257 {
258 SetPWM(i+Ofset); // nastav proud 258 SetPWM(i+Ofset); // nastav proud
259 FData=GetVoltage(); // zmer napeti 259 FData=GetVoltage(); // zmer napeti
260 if (FData>0) printf(Xputc,"\r\n%03u %1.2f %3.1f",i,FData,FData*i); 260 if (FData>0) printf(Xputc,"\r\n%03u %1.2f %3.1f",i,FData,FData*i);
261 else i=250; // predcasne ukonceni 261 else i=250; // predcasne ukonceni
262 } 262 }
263 printf(Xputc,"\r\n"); // na konci odradkuj 263 printf(Xputc,"\r\n"); // na konci odradkuj
264 SetPWM(0); // vypni proud 264 SetPWM(0); // vypni proud
265 lcd_clr(); // smaz displej 265 lcd_clr(); // smaz displej
266 } 266 }
267   267  
268   268  
269 void main() 269 void main()
270 { 270 {
271 // Hodiny 271 // Hodiny
272 *0x8F = 0x72; // 8 MHz interni RC oscilator 272 *0x8F = 0x72; // 8 MHz interni RC oscilator
273   273  
274 // Digitalni vystupy 274 // Digitalni vystupy
275 output_low(PIN_B0); // nepouzity 275 output_low(PIN_B0); // nepouzity
276 output_low(PIN_B1); // nepouzity 276 output_low(PIN_B1); // nepouzity
277 output_low(PIN_B3); // PWM vystup 277 output_low(PIN_B3); // PWM vystup
278 output_high(PIN_B5); // TX data 278 output_high(PIN_B5); // TX data
279 port_b_pullups(TRUE); // vstupy s pull up odporem 279 port_b_pullups(TRUE); // vstupy s pull up odporem
280   280  
281 // Analogove vstupy 281 // Analogove vstupy
282 *ANSEL = 0x03; // AN0 a AN1 282 *ANSEL = 0x03; // AN0 a AN1
283   283  
284 // Inicializace LCD 284 // Inicializace LCD
285 lcd_init(); 285 lcd_init();
286 Xrs=1; 286 Xrs=1;
287 Xlcd=1; 287 Xlcd=1;
288 printf(Xputc,"\fSolar Cell\r\nTester 1.00\r"); 288 printf(Xputc,"\fSolar Cell\r\nTester 1.00\r");
289   289  
290 // Inicializace PWM 8 bitu 290 // Inicializace PWM 8 bitu
291 *PR2 = 0x3F; // perioda PWM casovace 291 *PR2 = 0x3F; // perioda PWM casovace
292 *T2CON = 0x04; // povoleni casovace T2 bez preddelicu a postdelicu 292 *T2CON = 0x04; // povoleni casovace T2 bez preddelicu a postdelicu
293 *CCP1CON = 0x0C; // PWM mode, lsb bity nulove 293 *CCP1CON = 0x0C; // PWM mode, lsb bity nulove
294 *CCPR1L = 0; // na zacatku nulova data 294 *CCPR1L = 0; // na zacatku nulova data
295 output_low (PIN_B3); // PWM vystup 295 output_low (PIN_B3); // PWM vystup
296   296  
297 // Kalibrace pri drzenem tlacitku 297 // Kalibrace pri drzenem tlacitku
298 EE_RD(0,Vref); // vytahni kalibracni konstantu z EEPROM 298 EE_RD(0,Vref); // vytahni kalibracni konstantu z EEPROM
299 if (input(PIN_B4)==0) // otestuj tlacitko 299 if (input(PIN_B4)==0) // otestuj tlacitko
300 { 300 {
301 delay_ms(200); 301 delay_ms(200);
302 Calibrate(); // pokud je stalceno spust kalibraci 302 Calibrate(); // pokud je stalceno spust kalibraci
303 } 303 }
304 else 304 else
305 { 305 {
306 delay_ms(1000); // jinak jen 1s spozdeni 306 delay_ms(1000); // jinak jen 1s spozdeni
307 } 307 }
308 lcd_clr(); // smaz displej 308 lcd_clr(); // smaz displej
309   309  
310 // Hlavni smycka 310 // Hlavni smycka
311 { 311 {
312 int8 il,ih,im; // spodni a horni mez a maximum proudu 312 int8 il,ih,im; // spodni a horni mez a maximum proudu
313 int8 i; // promenna cyklu 313 int8 i; // promenna cyklu
314 float Voltage,Power; // zmerene rozdilova napeti a vypocteny vykon 314 float Voltage,Power; // zmerene rozdilova napeti a vypocteny vykon
315 float MaxVoltage,MaxPower; // maximalni hodnoty 315 float MaxVoltage,MaxPower; // maximalni hodnoty
316   316  
317 // Cihej na stisk tlacitka 317 // Cihej na stisk tlacitka
318 0==PORTB; // jen precti port B 318 0==PORTB; // jen precti port B
319 RBIF=0; // nuluj priznak preruseni od zmeny 319 RBIF=0; // nuluj priznak preruseni od zmeny
320   320  
321 // Pocatecni meze 321 // Pocatecni meze
322 il=0; 322 il=0;
323 ih=10; 323 ih=10;
324   324  
325 // Trvale prohledavani 325 // Trvale prohledavani
326 for(;1;) 326 for(;1;)
327 { 327 {
328   328  
329 if (RBIF) // kdyz je tlacitko 329 if (RBIF) // kdyz je tlacitko
330 { 330 {
331 AutoRun(); 331 AutoRun();
332 while (~input(PIN_B4)); // cti port B a cekej na uvolneni 332 while (~input(PIN_B4)); // cti port B a cekej na uvolneni
333 RBIF=0; 333 RBIF=0;
334 } 334 }
335   335  
336 Xrs=0; 336 Xrs=0;
337 Xlcd=1; 337 Xlcd=1;
338 printf(Xputc,"\rOpt. [mA V mW]"); // napis na LCD 338 printf(Xputc,"\rOpt. [mA V mW]"); // napis na LCD
339   339  
340 MaxVoltage=0; // inicializace maxim 340 MaxVoltage=0; // inicializace maxim
341 MaxPower=0; 341 MaxPower=0;
342 im=0; 342 im=0;
343   343  
344 for(i=il;i<=ih;i++) // dilci cyklus hledani 344 for(i=il;i<=ih;i++) // dilci cyklus hledani
345 { 345 {
346 SetPWM(i+Ofset); // nastav proud 346 SetPWM(i+Ofset); // nastav proud
347 Voltage=GetVoltage(); // precti rozdilove napeti 347 Voltage=GetVoltage(); // precti rozdilove napeti
348 Power=Voltage*i; // vypocti vykon 348 Power=Voltage*i; // vypocti vykon
349 if (Power>MaxPower) // zkontroluj maximu 349 if (Power>MaxPower) // zkontroluj maximu
350 { 350 {
351 MaxVoltage=Voltage; // zapamatuj si maximum 351 MaxVoltage=Voltage; // zapamatuj si maximum
352 MaxPower=Power; 352 MaxPower=Power;
353 im=i; 353 im=i;
354 } 354 }
355 } 355 }
356   356  
357 // Zobrazeni vysledku 357 // Zobrazeni vysledku
358 Xrs=0; 358 Xrs=0;
359 Xlcd=1; 359 Xlcd=1;
360 printf(Xputc,"\r\n%3u %1.2f %3.1f ", im, MaxVoltage, MaxPower); 360 printf(Xputc,"\r\n%3u %1.2f %3.1f ", im, MaxVoltage, MaxPower);
361   361  
362 // Natav nove meze 362 // Natav nove meze
363 if (im>5) il=im-5; else il=0; 363 if (im>5) il=im-5; else il=0;
364 if (il>240) il=240; 364 if (il>240) il=240;
365 ih=il+10; 365 ih=il+10;
366 } 366 }
367 } 367 }
368 } 368 }