Rev Author Line No. Line
417 kakl 1 //******** Mrakomer ******************************************
2 #define VERSION "2.1"
419 kakl 3 #define ID "$Id: irmrak.c 419 2006-12-29 19:37:38Z kakl $"
417 kakl 4 //************************************************************
5  
6 #include "irmrak.h"
7 #include <string.h>
8  
9 #use rs232(baud=9600,parity=N,xmit=PIN_A6,rcv=PIN_A7,bits=8)
10  
11 char VER[4]=VERSION;
12 char REV[50]=ID;
13  
14 #define TRESHOLD 8 // nebo 9
15 // nad_diodou=H je + teplota
16 // pod_diodou=L je - teplota
17  
18 #define MINUS !C1OUT // je kladny impuls z IR teplomeru
19 #define PLUS C2OUT // je zaporny impuls z IR teplomeru
20 #define HALL PIN_A4 // Hallova sonda pro zjisteni natoceni dolu
21 // topeni je na RB3 (vystup PWM)
22  
23 #define MAX_TEMP 10000
24  
25 int port; // stav brany B pro krokove motory
26 int j; // pro synchronisaci fazi
27 unsigned int8 uhel; // pocitadlo prodlevy mezi merenimi
28 unsigned int8 i; // pro cyklus for
29 unsigned int16 nn; // pocitadlo mereni
30 unsigned int32 timer; // casovac pro topeni
31 unsigned int8 topit; // na jaky vykon se ma topit?
32  
33 unsigned int16 teplota; // prectena teplota
34 int1 sign; // nad nulou / pod nulou
35  
36 // --- Jeden krok krokoveho motoru ---
37 void krok(int n)
38 {
39 while((n--)>0)
40 {
41 if (1==(j&1)) {port^=0b11000000;} else {port^=0b00110000;};
42 output_B(port);
43 delay_ms(50);
44 j++;
45 }
46 }
47  
48 // --- Dojet dolu magnetem na cidlo ---
49 void dolu()
50 {
51 unsigned int8 err; // pocitadlo pro zjisteni zaseknuti otaceni
52  
53 err=0;
54 while(!input(HALL)) // otoceni trubky dolu az na hall
55 {
56 krok(1);
57 err++;
58 if(40==err) // do 40-ti kroku by se melo podarit otocit dolu
59 {
60 output_B(0); // vypnuti motoru
61 printf("Error movement.\n\r");
62 err=0;
63 }
64 };
65 delay_ms(700); // cas na ustaleni trubky
66 output_B(0); // vypnuti motoru
67 }
68  
69 // --- Najeti na vychozi polohu dole ---
70 void nula()
71 {
72 int n;
73  
74 for (n=0; n<7; n++)
75 {
76 if (!input(HALL)) return;
77 krok(1);
78 }
79 }
80  
81 // --- Precti teplotu z IR teplomeru ---
82 void prevod()
83 {
84 unsigned int16 t; // cas
85 unsigned int16 tt;
86  
87 t=0;
88 while(!PLUS && !MINUS)
89 {
90 t++;
91 if(t>65000)
92 {
93 printf("Error thermometer.\n\r");
94 teplota=0;
95 sign=true;
96 return;
97 }
98 }; // ceka se na 0
99  
100 teplota=0;
101 sign=false;
102 for(t=0;t<=MAX_TEMP;t++)
103 {
104 if(PLUS || MINUS) // ceka se na + nebo -
105 {
106 if(MINUS) sign=true;
107 for(tt=1;tt<=MAX_TEMP;tt++)
108 {
109 if(!PLUS && !MINUS) {teplota=tt; break;}; // ceka se na 0
110 }
111 break;
112 }
113 }
114 teplota=teplota*19/100; // 1 stupen celsia je asi 10us
115 }
116  
117 // --- Prevod a vystup jedne hodnoty ---
118 void vystup()
119 {
120 delay_ms(200); // pockej na ustaleni napeti po krokovani
121 printf(" ");
122 prevod(); // precti teplotu z teplomeru
123 if(sign)
124 printf("-%Lu", teplota);
125 else
126 printf("%Lu", teplota);
127 }
128  
129 //------------------------------------------------
130 void main()
131 {
132 setup_oscillator(OSC_4MHZ|OSC_INTRC); // 4 MHz interni RC oscilator
133  
134 setup_adc_ports(NO_ANALOGS|VSS_VDD);
135 setup_adc(ADC_OFF);
136 setup_spi(FALSE);
137 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); // Casovac pro PWM
138 setup_timer_1(T1_DISABLED);
139 setup_ccp1(CCP_OFF);
140 setup_comparator(A0_VR_A1_VR); // inicializace komparatoru
141 setup_vref(VREF_HIGH|TRESHOLD); // 32 kroku od 0.25 do 0.75 Vdd
142  
143 // nastav PWM pro topeni
144 set_pwm1_duty(0); // Spust PWM, ale zatim s trvalou 0 na vystupu
145 setup_ccp1(CCP_PWM);
146 setup_timer_2(T2_DIV_BY_16,100,1); // perioda
147  
148 output_B(0); // vypnuti motoru
149 set_tris_B(0b00000111); // faze a topeni jako vystup
150  
151 delay_ms(1000);
152 printf("Mrakomer V%s (C) 2006 KAKL\n\r", VER);
153 printf("%s\n\r", REV);
154  
155 topit=0; // na zacatku netopime
156  
157 while(true)
158 {
159 port=0b01010000; // vychozi nastaveni fazi pro rizeni motoru
160 j=0; // smer dolu
161 dolu(); // otoc trubku do vychozi pozice dolu
162  
163 while(!kbhit())
164 {
165 timer--;
166 if (0==timer) // casovac, aby se marakomer neupek
167 {
168 topit=0;
169 set_pwm1_duty(0); // zastav topeni
170 printf("H %u\n\r", topit);
171 };
172  
173 if (!input(HALL)) // znovuotoceni trubky dolu, kdyby ji vitr otocil
174 {
175 set_pwm1_duty(0); // zastav topeni, aby byl odber do 1A
176 dolu();
177 set_pwm1_duty(topit); // spust topeni
178 }
179 }; // pokracuj dal, kdyz prisel po RS232 znak
180  
181  
182 uhel=getc(); // prijmi znak
183 if ((uhel>='a') && (uhel<='k')) // nastaveni topeni [a..k]=(0..100%)
184 {
185 topit=uhel-'a';
186 topit*=10;
187 timer=500000; // cca 11s
188  
189 // ochrana proti upeceni
190 prevod();
191 if(sign)
192 {
193 if ((teplota <= 5) && (topit > 60)) topit=0; // do -5°C se da topit maximalne na 60%
194 printf("H %u;G -%Lu\n\r", topit, teplota); // zobraz hodnotu topeni (<H>eating)
195 }
196 else
197 {
198 if (teplota > 10) topit=0; // kdyz je vic jak +10°C, tak netopit
199 if (topit > 40) topit=0; // pokud nemrzne, tak se neda topit vic jak na 40%
200 printf("H %u;G %Lu\n\r", topit, teplota); // zobraz hodnotu topeni (<H>eating)
201 }
202 set_pwm1_duty(topit); // spust topeni
203 continue;
204 };
205  
206  
207 if ('m'==uhel) // standardni mereni ve trech polohach
208 {
209 prevod(); //jeden prevod na prazdno pro synchnonisaci
210  
211 j++; // reverz, nahoru
212 nula();
213  
214 printf("G"); // mereni teploty Zeme (<G>round)
215 vystup();
216  
217 krok(15);
218 printf(";S45"); // mereni teploty 45° nad obzorem
219 vystup();
220 krok(7);
221 printf(";S90"); // mereni teploty v zenitu
222 vystup();
223 krok(7);
224 printf(";S135"); // mereni teploty 45° nad obzorem na druhou stranu
225 vystup();
226 printf("\n\r");
227  
228 j++; // reverz
229 dolu();
230  
231 continue;
232 }
233  
234  
235 if ((uhel>='0') && (uhel<='@')) // mereni v pozadovanem uhlu [0..;]=(0..11)
236 {
237 uhel-='0';
238 };
239  
240 if(uhel>11) continue; // ochrana, abysme neukroutili draty
241  
242 printf("A %u;", uhel); // zobraz pozadovany uhel (<A>ngle)
243  
244 prevod(); // jeden prevod na prazdno pro synchnonisaci
245  
246 j++; // reverz, nahoru
247 nula();
248  
249 printf("G"); // mereni teploty Zeme (<G>round)
250 vystup();
251  
252 printf(";S"); // mereni teploty pozadovanym smerem do vesmiru (<S>pace)
253 krok(12); // odkrokuj do roviny
254 for(i=0; i<uhel; i++) // dale odkrokuj podle pozadovaneho uhlu
255 {
256 krok(2);
257 };
258 vystup();
259 printf("\n\r");
260  
261 j++; // reverz
262 dolu();
263 }
264 }
265