Магнитометр-магнитограф
- Войдите на сайт для отправки комментариев
Вс, 06/03/2016 - 17:10
Представляю магнитометр-магнитограф созданный как пробный инструмент для дальнейшего развития при построении домашней метеостанции с возможностью индикации состояния магнитного поля земли, что очень важно для метео-зависимых людей к которым отношусь и я сам. Не совсем уверен в правильности выбранного пути, но по другому не получается и технических возможностей в общем-то не так уж и много. Устройство выполняет мониторинг и фиксацию поведения магнитной стрелки компаса за определенный период. Я отталкивался от факта, что магнитная стрелка чувствительна к колебаниям магнитного поля земли. Созданный прибор фиксирует на SD карте величины девиации стрелки за каждые 10 сек. За сутки количество измерений составляет 8645. Для отображения результатов на сегодняшний день используется программа на PYTHON, которая считывает из файла измерений данные и строит график. На мой взгляд подход оправдал себя и в дальнейшем после получения от китайских братьев графического дисплея отображение результата автор планирует реализовать в реальном масштабе времени непосредственно на дисплей. Сердцем устройства является электронный магнитный компас HMC 5883L. Компас жестко зафиксирован в пространстве с примерной ориентацией на север. При экспериментах я понял, что датчик в любом случае реагирует на поведение магнитного поля и следовательно, на мой взгляд, положение его в пространстве для данной задачи несущественно. При построении программы пока действует условие, что начальное положение стрелки находится в первом квадранте. Все устройство реализовано на основе Arduino Mega2560. На плате установлен самодельный шилд, на котором распаяны разъем клавиатуры, кнопки управления, разъем питания по min-USB, кнопка сброса и диод 13-го порта. Сама Ардуина закреплена на макетной плате, на которой установлен SD модуль, LCD монитор, разъем для шилда и магнитного компаса, а также выключатель питания LCD. Надо отметить, что дисплей применен не обычный китайский а типа американьский, фирмы Scott Edwardshs, и управляется он всего по одному проводу, просто другого под рукой небыло. Вещь, надо сказать интересная и управляется в принципе как обычный LCD I2C, библиотека для него по крайней мере стандартная SoftwareSerial.h. Часы-календарь реализованы программно, т.к. опять же под рукой нетбыло DS1320. Начальные данные (дата+время) вводятся при каждой перезагрузке или смене флешки при помощи клавиатуры PS/2. Часики у меня имеют технологическую неточность около 5 минут в сутки, но такая точчность меня вполне устраивает, т.к. файл результата выбирается ежедневно, а устройство как было сказано является испытательным инструментом. Результаты записываются в файл с именем ДДММГГ.txt (день, месяц, год) в виде строк (смотри на картинке) ДД ММ ГГ ЧЧ МН СК НН ТТ ДВ (день, месяц, год, час, минута, секунда, начальный угол стрелки, текущий угол, текущая девиация). Как уже отмечалось выше таких строк за сутки получается 8645. На сегодняшний день результаты отображаются не динамически, а по истечении периода измерения, но это уверен пока. По окончании периода измерения, т.е. суток, устройство останавливается нажатием кнопки START, флешка вынимается и файл переписывается на ПК, затем флешка снова вставляется и с клавитауры вводятся исходные значения день, месяц, год, час, минута и после нажатия <Enter> устройство запускается. Считанный файл обрабатывается программкой на Питоне. При этом из имеющихся 8645 записей формируется 720 координат путем вычисления среднего арифметического за каждые 12 минут. На основе получено массива строится график. Примеры привожу на фото. Должен сказать, что мои данные в принципе повторяют публикуемые данные с сайта http://v-kosmose.com/, но отстают на несколько часов. Скорее всего это связано с географическим положением регистратора. Видимо мне надо еще подумать над тем как правильно обрабатывать результаты и т.д., может кто посоветует дельную мысль, но уже сегодня я вижу, что возмущения магнитного поля мною фиксируются и такую функцию можно добавить в домашнюю метеостанцию, и она не будет лишней, так как показывает значение в моей домашней зоне. Для примера привожу полученные мною графики за 4 и 5 марта 2016г.. Картинка с заголовком "Геомагнитный индекс" это данные с сайта. Очень интересным считаю объединить результаты по компасу и атмосферному давлению, но это надеюсь в скором времени реализовать. Кнопка RESET просто инициализирует устройство с новой фиксацией начального положения стрелки, но без изменения даты, время и не прерывая запись в файл. Показываю эскиз схемы, думаю достаточно понятно, а также скетч для Ардуино и прогу на Питоне.








001 | Скетч для Ардуино |
002 |
003 | /* |
004 | Мониторинг магнитной стрелки |
005 | v 1.0 |
006 | 24.02.2016 |
007 | Arduino 1.0.5-r2 |
008 | Предполагается, что начальное положение стрелки в первом квадранте. |
009 | LCD - Scott Edwardshs |
010 | <a href="http://www.seetron.com/products.html" title="http://www.seetron.com/products.html" rel="nofollow">http://www.seetron.com/products.html</a> |
011 | <a href="http://elabz.com/serial-oled-display-and-arduino/" title="http://elabz.com/serial-oled-display-and-arduino/" rel="nofollow">http://elabz.com/serial-oled-display-and-arduino/</a> |
012 | */ |
013 |
014 | //** SD card attached to SPI bus as follows: |
015 | //** MOSI - pin 51 |
016 | //** MISO - pin 50 |
017 | //** CLK - pin 52 |
018 | //** CS - pin 53 - отключена, с ней не инициализируется SD - не разбирался |
019 | // pinMode(53, OUTPUT); |
020 | // |
021 |
022 |
023 | #include <SD.h> |
024 | #include <PS2Keyboard.h> |
025 | #include "Wire.h" |
026 | #include "HMC5883L.h" |
027 | #include <SoftwareSerial.h> |
028 | #define rxPin A7 |
029 | #define txPin A7 |
030 |
031 | PS2Keyboard keyboard; |
032 | const int DATA_PIN = 2; |
033 | const int IRQ_PIN = 3; |
034 | File myFile; |
035 |
036 | SoftwareSerial MySerial = SoftwareSerial(rxPin,txPin); |
037 | HMC5883L compass; |
038 |
039 | volatile long mks100; |
040 | volatile long ms10; |
041 | volatile int cntr; |
042 | long tmillis,tms10=0; |
043 | char flip; |
044 | int id=0; |
045 | char fil[11]; |
046 | char cd0= '1' ; |
047 | char cd1= '2' ; |
048 | char cd2= '1' ; |
049 | char cd3= '2' ; |
050 | char cd4= '1' ; |
051 | char cd5= '2' ; |
052 | char cd6= '.' ; |
053 | char cd7= 't' ; |
054 | char cd8= 'x' ; |
055 | char cd9= 't' ; |
056 | float raz=0; |
057 | float Mraz=raz; |
058 | int i_start=0; |
059 | float old_heading=0; |
060 | int head = 0; |
061 | int basic_h=0; |
062 | int basic_a=0; |
063 | int start_h=0; |
064 | int dev=0; |
065 |
066 | // set pin numbers -start - reset: |
067 | const int buttonPin_start = 28; // START COMPASS |
068 | const int buttonPin_reset = 36; // SET DATE-TIME |
069 |
070 | int pause=1; |
071 |
072 | // переменные для начального задания времени |
073 | int hour=17; |
074 | int min=0; |
075 | int sec=0; |
076 |
077 | // переменные для начального задания даты |
078 |
079 | int day = 12; |
080 | int mon = 12; |
081 | int yar = 12; |
082 |
083 | String st1= "0" ; |
084 |
085 | void setup () { |
086 | keyboard.begin(DATA_PIN,IRQ_PIN); |
087 | Serial .begin(9600); |
088 | Wire.begin(); |
089 | delay(1000); |
090 | digitalWrite(txPin,HIGH); |
091 | delay(1000); |
092 | pinMode(txPin,OUTPUT); |
093 | MySerial.begin(9600); |
094 | compass = HMC5883L(); // создаем экземпляр HMC5883L библиотеки |
095 | setupHMC5883L(); // инициализация HMC5883L |
096 | |
097 | mks100 = 0; // счетчик сотен микросекунд, переполнение счетчика примерно через 5 суток |
098 | ms10 = 0; // счетчик десятков миллисекунд, переполнение счетчика примерно через 16 месяцев |
099 | cntr = 0; |
100 | flip = 0; |
101 |
102 |
103 | // Включаем нужный нам режим таймера/счетчика - нормальный |
104 | TCCR2A = 0; //нормальный режим (по умолчанию 1 - ШИМ с коррекцией фазы?) |
105 | // Предделитель таймера/счетчика настраиваем на 16 - |
106 | // это позволит "тикать" таймером каждую микросекунду |
107 | // (при условии, что микроконтроллер работает с |
108 | // частотой 16.000.000 тактов в секунду) |
109 | TCCR2B = 2; // 010 - fclk/8 (по умолчанию 100 - fclk/64) |
110 | //TCCR2B = 7; // 111 - fclk/1024 (по умолчанию 100 - fclk/64) |
111 | TCNT2=59; //55; |
112 | TIMSK2 |= (1 << TOIE2); // разрешаем прерывание таймера/счетчика 2 по переполнению |
113 | fil[0]=cd0; |
114 | fil[1]=cd1; |
115 | fil[2]=cd2; |
116 | fil[3]=cd3; |
117 | fil[4]=cd4; |
118 | fil[5]=cd5; |
119 | fil[6]=cd6; |
120 | fil[7]=cd7; |
121 | fil[8]=cd8; |
122 | fil[9]=cd9; |
123 | |
124 |
125 | ini_SD(); |
126 | open_SD(); |
127 | LCD_clear(); |
128 | MySerial.print( "One moment" ); |
129 | } |
130 |
131 | ISR(TIMER2_OVF_vect) { |
132 | // прежде всего взводим счетчик |
133 | TCNT2=59; //55; |
134 | // прошли очередные 100 мксек - увеличиваем счетчик сотен микросекунд |
135 | mks100++; |
136 | // if(mks100%100==0) ms10++; |
137 | cntr++; |
138 | // прошли очередные 10 мсек? - увеличиваем счетчик десятков миллисекунд |
139 | if (cntr>99) { |
140 | ms10++; |
141 | cntr = 0; |
142 | } |
143 | } |
144 | |
145 | //---------------------------------------------------------------------------- |
146 | void loop () { |
147 |
148 | // RESET |
149 |
150 |
151 |
152 | if (digitalRead(buttonPin_reset) == HIGH) { // Установка времени, даты |
153 | delay(1000); |
154 | start_h=0; |
155 | id=0; |
156 | myFile.close(); |
157 | reset(); |
158 | } |
159 |
160 | if (digitalRead(buttonPin_start) == HIGH) { // Сброс компаса |
161 | start_h=0; |
162 | raz=0; |
163 | Mraz=raz; |
164 | i_start=0; |
165 | old_heading=0; |
166 | head = 0; |
167 | MySerial.write(0xFE); |
168 | MySerial.write(0x01); |
169 | MySerial.write(0x80); |
170 | MySerial.print( "One moment" ); |
171 | MySerial.write(0xFE); |
172 | MySerial.write(0xC0); |
173 | MySerial.print( "Reset compass" ); |
174 | delay(1000); |
175 | |
176 | } |
177 | |
178 | // часы запущены |
179 | if (ms10>tms10) { |
180 | tmillis = millis(); |
181 | tms10 = ms10; |
182 | |
183 | if (tms10%100==0) { |
184 | flip = !flip; |
185 | } |
186 | if (tms10%1000==0) { // выполнение каждые 10 сек |
187 |
188 | if (sec<50){ |
189 | sec=sec+10; |
190 | Time_Ind(); |
191 | } |
192 | else { |
193 | sec=0; |
194 | min=min+1; |
195 | if (min<60){ |
196 | Time_Ind(); |
197 | } |
198 | else { |
199 | sec=0; |
200 | min=0; |
201 | hour=hour+1; |
202 | if (hour<24){ |
203 | Time_Ind(); |
204 | } |
205 | else { // смените дату !!!!! |
206 | day = day+1; |
207 | hour=0; |
208 | Time_Ind(); |
209 | } |
210 | } |
211 | } |
212 | } |
213 | } |
214 | } |
215 |
216 |
217 |
218 |
219 | //================================================ |
220 | void Time_Ind() |
221 | { |
222 | |
223 | if (digitalRead(buttonPin_start) == HIGH) { // Сброс компаса |
224 | start_h=0; |
225 | raz=0; |
226 | Mraz=raz; |
227 | i_start=0; |
228 | old_heading=0; |
229 | // head = 0; |
230 | MySerial.write(0xFE); |
231 | MySerial.write(0x01); |
232 | MySerial.write(0x80); |
233 | MySerial.print( "One moment" ); |
234 | MySerial.write(0xFE); |
235 | MySerial.write(0xC0); |
236 | MySerial.print( "Reset compass" ); |
237 | delay(1000); |
238 | } |
239 | //if (sec==0) { // вывод результата каждую минуту |
240 | |
241 |
242 | MySerial.write(0xFE); |
243 | MySerial.write(0x01); |
244 | MySerial.write(0x80); |
245 | // время |
246 | if (hour>9 and min<10){ |
247 | // час > 10, мин < 10 |
248 | float heading = getHeading(); |
249 | MySerial.print(basic_h); // начальное - стартовое положение стрелки |
250 | MySerial.print( " " ); |
251 | MySerial.print(head); // текущее полжение стрелки |
252 | MySerial.print( " " ); |
253 | MySerial.print(dev); // текущая девиация |
254 |
255 |
256 |
257 | MySerial.write(0xFE); |
258 | MySerial.write(0xC0); |
259 | write_SD(); |
260 |
261 |
262 | MySerial.print(hour,DEC); |
263 | MySerial.print( ":" ); |
264 | MySerial.print( "0" ); |
265 | MySerial.print(min,DEC); |
266 | } |
267 | if (hour<10 and min>9){ |
268 | // час < 10, мин > 10 |
269 | float heading = getHeading(); |
270 | MySerial.print(basic_h); // начальное - стартовое положение стрелки |
271 | MySerial.print( " " ); |
272 | MySerial.print(head); // текущее полжение стрелки |
273 | MySerial.print( " " ); |
274 | MySerial.print(dev); // текущая девиация |
275 |
276 |
277 | MySerial.write(0xFE); |
278 | MySerial.write(0xC0); |
279 | write_SD(); |
280 | MySerial.print( "0" ); |
281 | MySerial.print(hour,DEC); |
282 | MySerial.print( ":" ); |
283 | MySerial.print(min,DEC); |
284 | } |
285 | if (hour>9 and min>9){ |
286 | // час > 10, мин > 10 |
287 | float heading = getHeading(); |
288 | MySerial.print(basic_h); // начальное - стартовое положение стрелки |
289 | MySerial.print( " " ); |
290 | MySerial.print(head); // текущее полжение стрелки |
291 | MySerial.print( " " ); |
292 | MySerial.print(dev); // текущая девиация |
293 |
294 | |
295 |
296 | MySerial.write(0xFE); |
297 | MySerial.write(0xC0); |
298 | write_SD(); |
299 | MySerial.print(hour,DEC); |
300 | MySerial.print( ":" ); |
301 | MySerial.print(min,DEC); |
302 | } |
303 | if (hour < 10 and min<10){ |
304 | // час < 10, мин < 10 |
305 | float heading = getHeading(); |
306 |
307 | MySerial.print(basic_h); // начальное - стартовое положение стрелки |
308 | MySerial.print( " " ); |
309 | MySerial.print(head); // текущее полжение стрелки |
310 | MySerial.print( " " ); |
311 | MySerial.print(dev); // текущая девиация |
312 | |
313 | MySerial.write(0xFE); |
314 | MySerial.write(0xC0); |
315 | write_SD(); |
316 | MySerial.print( "0" ); |
317 | MySerial.print(hour,DEC); |
318 | MySerial.print( ":" ); |
319 | MySerial.print( "0" ); |
320 | MySerial.print(min,DEC); |
321 | } |
322 | // дата |
323 | if (day < 10 and mon<10){ |
324 | MySerial.print( " " ); |
325 | MySerial.print( "0" ); |
326 | MySerial.print(day,DEC); |
327 | MySerial.print( "." ); |
328 | MySerial.print( "0" ); |
329 | MySerial.print(mon,DEC); |
330 | MySerial.print( "." ); |
331 | MySerial.println(yar,DEC); |
332 | } |
333 | if (day < 10 and mon>9){ |
334 | MySerial.print( " " ); |
335 | MySerial.print( "0" ); |
336 | MySerial.print(day,DEC); |
337 | MySerial.print( "." ); |
338 | MySerial.print(mon,DEC); |
339 | MySerial.print( "." ); |
340 | MySerial.println(yar,DEC); |
341 | } |
342 |
343 | if (day > 9 and mon>9){ |
344 | MySerial.print( " " ); |
345 | MySerial.print(day,DEC); |
346 | MySerial.print( "." ); |
347 | MySerial.print(mon,DEC); |
348 | MySerial.print( "." ); |
349 | MySerial.println(yar,DEC); |
350 | } |
351 | if (day > 9 and mon<10){ |
352 | MySerial.print( " " ); |
353 | MySerial.print(day,DEC); |
354 | MySerial.print( "." ); |
355 | MySerial.print( "0" ); |
356 | MySerial.print(mon,DEC); |
357 | MySerial.print( "." ); |
358 | MySerial.println(yar,DEC); |
359 | } |
360 | } |
361 | //} |
362 |
363 |
364 | void setupHMC5883L(){ |
365 | // инициализация HMC5883L, и проверка наличия ошибок |
366 | int error; |
367 | error = compass.SetScale(0.88); // чувствительность датчика из диапазона: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1 |
368 | if (error != 0) |
369 | LCD_clear(); |
370 | MySerial.println(compass.GetErrorText(error)); // если ошибка, то выводим ее |
371 | |
372 | error = compass.SetMeasurementMode(Measurement_Continuous); // установка режима измерений как Continuous (продолжительный) |
373 | if (error != 0) |
374 | LCD_clear(); |
375 | MySerial.println(compass.GetErrorText(error)); // если ошибка, то выводим ее |
376 | } |
377 | |
378 | float getHeading(){ |
379 | // считываем данные с HMC5883L и рассчитываем направление |
380 | MagnetometerScaled scaled = compass.ReadScaledAxis(); // получаем масштабированные элементы с датчика |
381 | float heading = atan2(scaled.YAxis, scaled.XAxis); // высчитываем направление |
382 | |
383 | // return heading; |
384 | // корректируем значения с учетом знаков |
385 | if (heading < 0) heading += 2*PI; |
386 | if (heading > 2*PI) heading -= 2*PI; |
387 | head=heading * RAD_TO_DEG; |
388 | |
389 | // вычисление отклонения стрелки |
390 | if (start_h==0){ |
391 | basic_h=head; // начальное положение стрелки |
392 | basic_a=basic_h+180; //при условии 180 >=basic_h>=0 |
393 | start_h=1; |
394 | } |
395 | |
396 | if ((basic_h<=180)&&(basic_h>=0)){ // начальное положение стрелки в секторе 180>=basic_h>=0 |
397 | if ((basic_h>head)&&(head>=0)){ // текущее положение стрелки в секторе basic_h>head>=0 |
398 | dev=(basic_h-head)*(-1); |
399 | } |
400 | if ((basic_a>=head)&&(head>=basic_h)){ // текущее положение стрелки в секторе basic_a>=head>=basic_h |
401 | dev=head-basic_h; |
402 | } |
403 | if ((basic_a<head)&&(head<=360)){ // текущее положение стрелки в секторе basic_a<head<=360 |
404 | dev=(basic_h+(360-head))*(-1); |
405 | } |
406 | |
407 | } |
408 | return heading * RAD_TO_DEG; // переводим радианы в градусы |
409 | } |
410 | //=================================================== |
411 | void reset(){ |
412 | |
413 | reset: |
414 | |
415 | // Serial.println("reset"); |
416 | day: |
417 | st1= "0" ; |
418 | pause = 1; |
419 | myFile.close(); |
420 | LCD_clear(); |
421 | MySerial.print( "DD <Enter>" ); |
422 |
423 | while (pause){ |
424 | if (keyboard.available()) { |
425 | char c = (keyboard.read()); // читаем состояние клавиатуры |
426 | // Serial.print("id="); |
427 | // Serial.println(id); |
428 | fil[id]=c; |
429 | // Serial.print(fil[id]); |
430 | id=id+1; |
431 |
432 | if (c==PS2_ENTER){ |
433 | id=id-1; |
434 | goto mon; |
435 | } |
436 | String c1 = String (c); |
437 | String st = String(st1+c1); |
438 | st1=c1; |
439 | day=st.toInt(); |
440 | // Serial.print("day "); |
441 | // Serial.println(day); |
442 | |
443 | MySerial.write(0xFE); |
444 | MySerial.write(0xC0); |
445 | MySerial.print(day); |
446 |
447 | } |
448 | } |
449 |
450 |
451 |
452 | mon: |
453 | st1= "0" ; |
454 | pause = 1; |
455 | LCD_clear(); |
456 | MySerial.print( "MM <Enter>" ); |
457 |
458 | while (pause){ |
459 | if (keyboard.available()) { |
460 | char c = (keyboard.read()); // читаем состояние клавиатуры |
461 | // Serial.print("id="); |
462 | // Serial.println(id); |
463 | fil[id]=c; |
464 | // Serial.print(fil[id]); |
465 | id=id+1; |
466 | |
467 | if (c==PS2_ENTER){ |
468 | id=id-1; |
469 | goto yar; |
470 | } |
471 | String c1 = String (c); |
472 | String st = String(st1+c1); |
473 | st1=c1; |
474 | mon=st.toInt(); |
475 | MySerial.write(0xFE); |
476 | MySerial.write(0xC0); |
477 | MySerial.print(mon); |
478 |
479 | } |
480 | } |
481 |
482 |
483 | yar: |
484 | st1= "0" ; |
485 | pause = 1; |
486 | LCD_clear(); |
487 | MySerial.print( "YY <Enter>" ); |
488 |
489 | while (pause){ |
490 | if (keyboard.available()) { |
491 | char c = (keyboard.read()); // читаем состояние клавиатуры |
492 | fil[id]=c; |
493 | id=id+1; |
494 | |
495 | if (c==PS2_ENTER){ |
496 | fil[6]=cd6; |
497 | fil[7]=cd7; |
498 | fil[8]=cd8; |
499 | fil[9]=cd9; |
500 | goto hour; |
501 | } |
502 | String c1 = String (c); |
503 | String st = String(st1+c1); |
504 | st1=c1; |
505 | yar=st.toInt(); |
506 | |
507 | MySerial.write(0xFE); |
508 | MySerial.write(0xC0); |
509 | MySerial.print(yar); |
510 |
511 | } |
512 | } |
513 |
514 | hour: |
515 | st1= "0" ; |
516 | pause = 1; |
517 | LCD_clear(); |
518 | MySerial.print( "HH <Enter>" ); |
519 |
520 | while (pause){ |
521 | if (keyboard.available()) { |
522 | char c = (keyboard.read()); // читаем состояние клавиатуры |
523 | if (c==PS2_ENTER){ |
524 | goto min; |
525 | } |
526 | String c1 = String (c); |
527 | String st = String(st1+c1); |
528 | st1=c1; |
529 | hour=st.toInt(); |
530 | |
531 | MySerial.write(0xFE); |
532 | MySerial.write(0xC0); |
533 | MySerial.print(hour); |
534 |
535 | } |
536 | } |
537 |
538 | min: |
539 | st1= "0" ; |
540 | pause = 1; |
541 | LCD_clear(); |
542 | MySerial.print( "MM <Enter>" ); |
543 |
544 | while (pause){ |
545 | if (keyboard.available()) { |
546 | char c = (keyboard.read()); // читаем состояние клавиатуры |
547 | if (c==PS2_ENTER){ |
548 | raz=0; |
549 | Mraz=raz; |
550 | i_start=0; |
551 | old_heading=0; |
552 | head = 0; |
553 | id=0; |
554 | ini_SD(); |
555 | open_SD(); |
556 | LCD_clear(); |
557 | MySerial.print( "One moment" ); |
558 | return ; |
559 | } |
560 | String c1 = String (c); |
561 | String st = String(st1+c1); |
562 | st1=c1; |
563 | min=st.toInt(); |
564 | MySerial.write(0xFE); |
565 | MySerial.write(0xC0); |
566 | MySerial.print(min); |
567 |
568 | } |
569 | } |
570 | } |
571 |
572 |
573 | void LCD_clear(){ |
574 | MySerial.write(0xFE); |
575 | MySerial.write(0x01); |
576 | MySerial.write(0x80); |
577 | MySerial.write(0xFE); |
578 | MySerial.write(0xC0); |
579 | } |
580 | void ini_SD(){ |
581 | if (!SD.begin(4)) { |
582 | LCD_clear(); |
583 | MySerial.print( "initialization failed!" ); |
584 | return ; |
585 | } |
586 | else |
587 | LCD_clear(); |
588 | MySerial.print( "initialization done" ); |
589 | return ; |
590 | } |
591 | void open_SD(){ |
592 | |
593 | // Открываем файл, если есть, то удаляем старый |
594 | |
595 | if (SD.exists(fil)) { |
596 | LCD_clear(); |
597 | MySerial.print( "Removing ..." ); |
598 | SD.remove(fil); |
599 |
600 | } |
601 | else { |
602 | LCD_clear(); |
603 | MySerial.print( "doesn't exist." ); |
604 | delay(1000); |
605 | } |
606 |
607 |
608 | //======================================================================== |
609 | // Создаем новый файл |
610 | // |
611 | LCD_clear(); |
612 | MySerial.print( "Creating ..." ); |
613 | myFile = SD.open(fil, FILE_WRITE); |
614 | myFile.close(); |
615 |
616 |
617 | //======================================================================== |
618 | // Проверяем открывается или нет |
619 | // |
620 | if (SD.exists(fil)){ |
621 | LCD_clear(); |
622 | MySerial.print( " exists." ); |
623 |
624 | } |
625 | else { |
626 | LCD_clear(); |
627 | MySerial.print( " doesn't exist." ); |
628 | return ; |
629 | } |
630 |
631 | myFile = SD.open(fil, FILE_WRITE); |
632 | return ; |
633 | } |
634 |
635 | void write_SD(){ |
636 | |
637 | if (SD.exists(fil)){ |
638 | } |
639 | else { |
640 | LCD_clear(); |
641 | MySerial.print( " doesn't exist." ); |
642 | return ; |
643 | } |
644 |
645 | myFile = SD.open(fil, FILE_WRITE); |
646 | |
647 | if (myFile) { |
648 | myFile.print(day); |
649 | myFile.print( " " ); |
650 | myFile.print(mon); |
651 | myFile.print( " " ); |
652 | myFile.print(yar); |
653 | //myFile.print(" "); |
654 | myFile.print( " " ); |
655 | myFile.print(hour); |
656 | myFile.print( " " ); |
657 | myFile.print(min); |
658 | myFile.print( " " ); |
659 | myFile.print(sec); |
660 | //myFile.print(" "); |
661 | myFile.print( " " ); |
662 |
663 | myFile.print(basic_h); // начальное - стартовое положение стрелки |
664 | //myFile.print(" "); |
665 | myFile.print( " " ); |
666 | myFile.print(head); // текущее полжение стрелки |
667 | //myFile.print(" "); |
668 | myFile.print( " " ); |
669 | myFile.println(dev); // текущая девиация |
670 | myFile.close(); |
671 | } |
672 | else { |
673 | delay(1000); |
674 | } |
675 | } |
676 |
677 | void read_SD(){ |
678 | // re-open the file for reading: |
679 |
680 | // |
681 | myFile = SD.open(fil); |
682 | if (myFile) { |
683 | // read from the file until there's nothing else in it: |
684 | while (myFile.available()) { |
685 | } |
686 | delay(1000); |
687 | myFile.close(); |
688 | return ; |
689 | } else { |
690 | // if the file didn't open, print an error: |
691 | LCD_clear(); |
692 | MySerial.print( "error opening SD." ); |
693 | delay(1000); |
694 | } |
695 |
696 | return ; |
697 | } |
Программа на Питоне
001 | # Обработка измерений отклонения магнитной стрелки за период |
002 |
003 |
004 | from math import * |
005 | from tkinter import * |
006 |
007 | f= open( 'C:/Python_proekt/flash/050316.TXT' ) # файл с исходными измерениями |
008 | pp=8 # граница для считывания значения отклонения из исходного файла |
009 | i=0 # индекс текущей строки string |
010 | ip=0 # счетчик пробелов при разборе string |
011 | dev=[ ' ' , ' ' , ' ' , ' ' ] # массив преобразования значения девиации |
012 | di=0 # индекс dev |
013 | s_izm=8640 # общее количество измерений |
014 | i_izm=0 # счетчик обработанных измерений |
015 | s_X=720 # количество отображаемых измерений |
016 | k_X=[] # массив отображаемых измерений по X |
017 | k_Y_p=[] # массив отображаемых измерений (+) по Y |
018 | k_Y_m=[] # массив отображаемых измерений (-) по Y |
019 | X=0 # индекс k_X |
020 | Y=0 # индекс k_Y_p, k_y_m |
021 | Ydev=0 # девиация по Y берется из файла измерений |
022 | k_M=11 # масштабный коэффициент измерений |
023 | # в сутках получается около 8645 измерений в сутки, 1440 минут, отображаем каждую 2-ю минуту = 720 |
024 | i_M=0 # счетчик суммы девиации за период k_M |
025 | sum_dev_p =0 # сумма девиации за период k_M (+) |
026 | sum_dev_m =0 # сумма девиации за период k_M (-) |
027 |
028 | while True: |
029 | if i_izm==s_izm: |
030 | print( 'Break' ) |
031 | break |
032 | else : |
033 | if i_izm==0: |
034 | string=f.readline() |
035 | string_n=string |
036 | else : |
037 | string=f.readline() |
038 |
039 |
040 | while True: |
041 | if string[i]== '\n' : |
042 | break |
043 | else : |
044 | if string[i]== ' ' : |
045 | ip=ip+1 |
046 | else : |
047 | if ip==pp: |
048 | dev[di]=string[i] |
049 | di=di+1 |
050 | if ip==(ip+1): |
051 | break |
052 | i=i+1 |
053 |
054 |
055 | i_izm=i_izm+1 |
056 | i_M=i_M+1 |
057 | Ydev= int (dev[0]+dev[1]+dev[2]+dev[3]) |
058 | |
059 | if i_M<=k_M: |
060 | if Ydev>=0: |
061 | sum_dev_p=sum_dev_p+Ydev |
062 | else : |
063 | sum_dev_m=sum_dev_m+Ydev |
064 | else : |
065 | k_X.append([1]) |
066 | k_X[X]=X |
067 | X=X+1 |
068 | k_Y_p.append([1]) |
069 | k_Y_m.append([1]) |
070 | k_Y_p[Y]= int (sum_dev_p/k_M) |
071 | k_Y_m[Y]= int ((sum_dev_m/k_M)*(-1)) |
072 | Y=Y+1 |
073 | sum_dev_p =0 # сумма девиации за период k_M (+) |
074 | sum_dev_m =0 # сумма девиации за период k_M (-) |
075 | i_M=0 |
076 |
077 | i=0 |
078 | ip=0 |
079 | dev=[ ' ' , ' ' , ' ' , ' ' ] |
080 | di=0 |
081 |
082 |
083 |
084 | # В Ы В О Д Г Р А Ф И К А |
085 |
086 | X_s=10 # отступ слева по оси Х - координата нуля |
087 | Y_s=200 # координата нуля по Y |
088 | D_X=0.01 # масштабный коэффициент по Х |
089 | D_Y=10 # масштабный коэффициент по Y |
090 | Y_P_p=17 # граница по Y выхода в красный |
091 | Y_0=0 # левый верхний Y |
092 | sm_X=100 # смещение по X от последнего измерения до конца оси X |
093 | kd_Y=2 # коэффициент деления оси Y |
094 | line_canv=2 # толщина линии оси координат |
095 | line_izm=2 # толщина линии отображения измерения |
096 |
097 |
098 | root = Tk() |
099 |
100 | canv = Canvas(root, width = (s_X+sm_X), height = 400, bg = "white" ) # окно |
101 | canv.create_line(X_s,Y_s*kd_Y,X_s,Y_0,width=line_canv,arrow=LAST) # координата Y |
102 | canv.create_line(X_s,Y_s,(s_X+sm_X),Y_s,width=line_canv,arrow=LAST) # координата X |
103 | canv.create_text((s_X+sm_X-45), Y_s+20, text = 'Время-минуты ' , fill= "purple" , font=( "Courier New CYR" , "10" )) |
104 | canv.create_text((X_s+80), Y_0+10, text = 'Отклонение - градусы ' , fill= "purple" , font=( "Courier New CYR" , "10" )) |
105 | canv.create_text((X_s+400), Y_0+10, text = 'Отклонение магнитной стрелки за период 1440 минут ' , fill= "black" , font=( "Courier New CYR" , "10" )) |
106 | canv.create_line((X_s-3),(Y_s-170),(X_s+3),(Y_s-170),width=line_canv) |
107 | canv.create_line((X_s-3),(Y_s+170),(X_s+3),(Y_s+170),width=line_canv) |
108 | canv.create_text((X_s+17), (Y_s-170), text = '+17 ' , fill= "purple" , font=( "Courier New CYR" , "10" )) |
109 | canv.create_text((X_s+17), (Y_s+170), text = '-17 ' , fill= "purple" , font=( "Courier New CYR" , "10" )) |
110 | canv.create_line((s_X+X_s),Y_s-3,(s_X+X_s),Y_s+3,width=line_canv) |
111 | canv.create_text((s_X+X_s+35),Y_s-10,text= '1440 min' ,fill= "purple" , font=( "Courier New CYR" , "10" )) |
112 | canv.create_text((X_s+400), Y_s+185, text =string_n, fill= "black" , font=( "Courier New CYR" , "10" )) |
113 | canv.create_text((X_s+400), Y_s+199, text =string, fill= "black" , font=( "Courier New CYR" , "10" )) |
114 |
115 |
116 | J=0 # индекс выводимых результатов |
117 |
118 | for J in range(X): |
119 | |
120 | if k_Y_p[J]<=Y_P_p: # проверка на положительное красное |
121 | canv.create_line([[X_s+k_X[J]+D_X*J],Y_s],[[X_s+k_X[J]+D_X*J],[Y_s-k_Y_p[J]*D_Y]],fill= "blue" ,width=line_izm) |
122 | else : |
123 | canv.create_line([[X_s+k_X[J]+D_X*J],Y_s],[[X_s+k_X[J]+D_X*J],[Y_P_p]],fill= "red" ,width=line_izm) |
124 |
125 |
126 | if k_Y_m[J]<=Y_P_p: # проверка на отрицательное красное |
127 | canv.create_line([[X_s+k_X[J]+D_X*J],Y_s],[[X_s+k_X[J]+D_X*J],[Y_s+k_Y_m[J]*D_Y]],fill= "green" ,width=line_izm) |
128 | else : |
129 | canv.create_line([[X_s+k_X[J]+D_X*J],Y_s],[[X_s+k_X[J]+D_X*J],[Y_s+Y_P_p*D_Y]],fill= "red" ,width=line_izm) |
130 | |
131 |
132 | canv.pack() |
133 | root.mainloop() |
134 | f.close() |
штука интересная можно ей искать не однородности земли к примеру и грунтовые воды в том числе... будет время попробую повторить ну может у автора есть какие то наработки
Честно говоря я забросил этот проект. Не оправдались ожидания от результата.
Вот
https://github.com/IvanKor/geomagnetic-magnetometer
гораздо круче, чувствительность не хуже чем у протонного магнитометра
Если нарастить магнитную антенну и сделать дифсистему то можно и грунтовые воды в том числе... искать ...
Честно говоря я забросил этот проект. Не оправдались ожидания от результата.
А можно подробнее что не понравилось?
Идея то интересная. Я бы себе на устройство к графикам радиации и давления за сутки такой график добавил бы.
Просто не хватило терпения и усидчивости. Надо было глубже погрузиться в предметную область, а хотелось быстрого результата, но видимо не в этом случае. Уверен, что этот магнитометр имеет большой запас возможностей, но надо серьезнее подойти к решению задачи. По сути я соорудил болванку, а вот до правильной методики измерений не смог довести. Тема сложная и требует определенных знаний, которыми я, к сожалению, не владею.
Добрый день.
Позвольте спросить о какой антенне идет речь?
IvanKor, пожалуйста, расскажите об антенне вашего устройства. какие ферриты вы использовали, размеры, есть ли обмотки ...
ферриты М400 от антенн старых радиоприемников, длиной 200 мм и диаметром 10 мм
стержни необходимо тщательно размагнитить
обмоток нет, весь эффект достигается как там показано, за счет фокусировки МП на крошечный датчик который внутри чипа.
ферриты М400 от антенн старых радиоприемников, длиной 200 мм и диаметром 10 мм
стержни необходимо тщательно размагнитить
Ты каданить видел намагниченный М400 живьём?
Ты каданить видел намагниченный М400 живьём?
Ежели с китаю, то могет. У них и медь магнитится.
Ты каданить видел намагниченный М400 живьём?
Ежели с китаю, то могет. У них и медь магнитится.
У него написано "от антенн старых радиоприемников". Не думаю, что китайских, ибо размер самый что ни на есть советский. 200х10
Ты каданить видел намагниченный М400 живьём?
ты видать никогда их не видал как и мой
geomagnetic-magnetometer
https://github.com/IvanKor/geomagnetic-magnetometer
где есть фотка, там два круглых стержня по 200 мм с обмотками.
обмотки я хотел использовать для компенсации земного поля но это оказалоссь весьма непростой задачей при измерениях меньше единицы нано теслы. Очень высокие требования к стабильности тока ... меньше пико ампера.
так вот, запомни, в старых приемниках такие антенны расположены недалеко от магнитов динамиков и ВСЕГДА НАМАГНИЧЕНЫ !
выяснить при помощи компаса намагничены или нет стержни может каждый
если стержень размагниченный и его расположить по вектору МП (наклонный) Земли то ...дальше сами,
ибо мине с хамами грить ниочем :D
Ха черточка ха черточка ха
IvanKor, спасибо за быстрый ответ!
Добрый день.
Позвольте спросить о какой антенне идет речь?
https://github.com/IvanKor/geomagnetic-magnetometer
это модуль Bluetooth для передачи на основной комп результата измерений
обмоток нет, весь эффект достигается как там показано, за счет фокусировки МП на крошечный датчик который внутри чипа.
Думаю. если стержни не "размагничивать" - графики не изменятся, там же относительные величины. а не абсолютные.
интересно, а если стержни вовсе выкинуть - хоть что-нибудь изменится?
Думаю. если стержни не "размагничивать" - графики не изменятся, там же относительные величины. а не абсолютные.
Измеряется абсолютная величина горизонтальной составляющей МП Земли при размещении антенны восток-запад. Путем юстировки (незначительных поворотов) антенны в горизонтальной плоскости добиваемся показаний близких к нулю. Если это не сделать прибор уйдет в зашкал.
интересно, а если стержни вовсе выкинуть - хоть что-нибудь изменится?
Получите чувствительность обыкновенного электронного компаса вместо ~ 1 nT и как следствие не сможете наблюдать вариации МП Земли типа как здесь http://geodata.izmiran.ru/ Собственно при геомагнитных бурях я сверялся с показаниями этого сайта.
Оба проекта http://arduino.ru/forum/proekty/magnitometr-magnitograf#comment-form и этот https://github.com/IvanKor/geomagn-magnetometer очень хороши в идее. Я не видел ничего подобного в интернете. Я рад, что их авторы отвечают на сообщения. Проекты были опубликованы давно. Магнитометр HMC 5983 больше не производится. Неясно, может ли его аналог HMC 5883L быть использован в проекте. Возможно, есть различия в их характеристиках и в том, как они связаны. Буду очень признателен авторам проекта за разъяснение этого важного вопроса. Я решил воссоздать оба проекта. Тот, что с Arduino UNO, не очень ясно, как защищены шесть ферритов. Может ли какая-нибудь картина быть просто о том, как феррит прикреплен к чипу магнитометра? Еще одна вещь, которая не была объяснена, состоит в том, почему, поскольку в ее коде для Arduino UNO есть bluetotch, его использование не включено? Также нет строкового кода. Для проекта, реализованного с помощью Arduino MEGA, нет антенной схемы. Авторы могут дать один? Заранее спасибо
Буду рад помочь. Уверен, если дополнить мой проект антенной из https://github.com/IvanKor/geomagnetic-magnetometer то получится интересное продолжение. Правда давно это все было реализовано, но материалы где то остались.
Я хотел бы спросить автора проекта на основе Arduino MEGA, что именно использовал модуль SD-карты. Не ясно, для большой или маленькой карты памяти. И какая антенна использовалась в этом проекте? Даже простая схема антенны отсутствует. Я спрашиваю автора, не мешает ли ему поставить одну картинку и диаграмму. Я буду ему очень благодарен. Я решил воспроизвести этот проект.
Модуль для большой SD, не для MicroSD. Антенны никакой нет, поэтому и бросил т.к. никто тогда мне не подсказал про антенну, а сам просто забросил проект, хотя долго - несколько месяцев собирал статистику. Появились другие проекты.
Вы собираете данные на карту памяти, но не ясно, какой программой вы обрабатываете собранную информацию впоследствии. Это важно для того, чтобы получить необходимые графики из этих данных. У вас есть такая программа? Что касается антенны, я спроектирую и опубликую здесь. Вопрос о моделях магнитометров и их взаимозаменяемости является важным. Можно ли заменить HMC 5983 на HMC 5883L???х Первый больше не производится. И еще одна вещь. Добавления в проекте часов реального времени RTC может оптимизировать проект, и я мог бы развивать его дальше, поскольку я инженер и программист. Я считаю ети два проекта http://arduino.ru/forum/proekty/magnitometr-magnitograf#comment-form и https://github.com/IvanKor/geomagn-magnetometer очень важными, так как большинство применений микросхем магнитометра предназначены для измерения земное поле но куда важнее скорость, с которой меняется это поле. Я заинтересован в поиске зоны аномалий в области земной территории. Я буду рад разработать оба проекта http://arduino.ru/forum/proekty/magnitometr-magnitograf#comment-form и https://github.com/IvanKor/geomagn-magnetometer, для которых мне нужны ответы на мои вопросы спросены выше. Спасибо за быстрые ответы.
я мог бы развивать его дальше, поскольку я инженер и программист.
судя по вашим вопросам, в этом есть большие сомнения....
странно слышать такой вопрос от "инженера и программиста". У вас есть файл с точками, программ для построения графиков - просто море. Начните с Экселя
ну так добавляйте... Или вы хотите, чтобы это сделали для вас авторы? - они выложили проекты, дальше кто угодно может их развивать по собственному вкусу...
PS - не сочтите за наезд, но уж больно забавный контраст между заявлениями "я-инженер" "хочу развивать проекты" и наивными вопросами на уровне школьника
Это правда, что я не прочитал все написанное авторами с достаточной тщательностью (поэтому позже я делал это несколько раз). Тогда я просто увидел, что там есть файл Python. Вы правы И еще одна вещь. Я не ленивый и не жду другой работы. Конечно, я инженер и программист. Вопросы их вопросы. Они не бьют вопрос. Наивный или не проявляющий особого живого интереса. Одно можно сказать наверняка, эти типы проектов чрезвычайно интересны. Даже для не инженеров и не программистов.
Denev - вы свои сообщения через Гугль переводчик пишете?
Данные собираются на карту и обрабатываются на Питоне. Все это указано выше. В проекте применен HMC 5883L. Часы можно добавить, не вижу проблем. Касательно антенны я уже писал.
Я прошу прощения, но русский не мой родной язык. Переводчик Google предназначен для использования. Я прошу прощения за использование этого. У меня есть обязанности, ответственность и приверженность только моему родному языку. Как бы вы написали вопрос на португальском форуме?
Какие трудности вы испытываете при повторении этого проекта?
Как бы вы написали вопрос на португальском форуме?
hablo espanol un poco, claro que potugues no es espanol :)))
HMC 5883L более старый чип и естественнно хуже HMC 5983, чем именно хуже всегда можно прочесть в описании на эти чипы.
Для поиска аномалий необходимо проделать весьма большую работу, намного большую чем просто этот магнитометр. Чувствительность всегда можно увеличить еще как минимум на два порядка, т.е. до ~ 0.01 nT что более чем достаточно для поиска аномалий.
Даже при нынешних ~ 1 nT магнитометр фиксирует проезжающие легковые авто за ~60 метров от антенны
Полностью согласен с вами коллега. Для развития такого проекта требуются значительные усилия, которые в итоге могут и не привести к ожидаемому результату.
Для развития такого проекта требуются значительные усилия, которые в итоге могут и не привести к ожидаемому результату.
Если физику в школе прогуливать, то, таки, да.
тут не одна физика тут и материаловедение и химия в том числе