Очередной МЕТЕО. Но рабочий
- Войдите на сайт для отправки комментариев
Вс, 03/10/2021 - 17:49
Коллеги, рискну поделиться рабочим проектом самодельной простенькой метеостанции.
Работает на Arduino Mega
Измеряет:
- три температуры
- атмосферное давление
- влажность воздуха
Пишет всё это на SD.
Время корректирует по GPS (если ловит, что не всегда).
На дисплее 4х20 отображает:
- три температуры,
- давление
- влажность
- текущее время
- последнее время по GPS.
На запрос по СМС вида:
- *t отсылает строку метеоданных
- "money" - отсылает текущий баланс (запросив его у провайдера).
Система более-менее (не без погрешностей со временем) работает примерно года 3 в деревенском доме. Чаще всего в полностью автономном режиме.
Скетч далёк от идеала (особенно в части времени), но повторюсь - система работает, и меня в целом устраивает.
001
//***************************************************************
002
//получение СМС с балансом СИМ-карты модуля SIM900
003
// соединяем: MEGA SIM900
004
// 17 0 (TX)
005
// 16 1 (RX)
006
// G G
007
// 9 9
008
//
009
// на SIM900 перемычками J11 J12 выбираем D00 D01
010
// для получения баланса посылаем с планшета (+79853056321)
011
// на SIM900 (+7ХХХХХХХХХХ - номер используемой устройством СИМ-карты) СМС со словом << money >>
012
//
013
// монитором последовательного порта можно контролировать процесс
014
//
015
// 19 to GPS Module TX*
016
// 18 to GPS Module RX*
017
//
018
//
019
// и печать в файл на SD-карте
020
//
021
// UNO MEGA
022
// CS - pin 4 53
023
// MOSI - pin 5 51
024
// MISO - pin 6 50
025
// CLK - pin 7 52
026
//
027
//****************************************************************
028
029
#include <Arduino.h>
030
#include <SoftwareSerial.h>
031
#include <SFE_BMP180.h>
032
#include <TinyGPS.h>
033
#include <Wire.h>
034
#include <LiquidCrystal_I2C.h>
035
#include <avr/pgmspace.h>
036
#include "RTClib.h"
037
//#include "RTCInt.h"
038
#include <SPI.h>
039
#include <SD.h>
040
#include "dht.h"
041
#include <OneWire.h>
042
#include <DallasTemperature.h>
043
044
TinyGPS gps;
045
046
void
gpsdump(TinyGPS &gps);
047
048
#define DS1307_ADDRESS 0x68 // устанавливаем таймер
049
#define BMP180_ADDRESS 0x77 // устанавливаем датчик давления
050
051
#define GSMRXPIN 11
052
#define GSMTXPIN 10
053
054
//#define GPSRXPIN 19
055
//#define GPSTXPIN 18
056
057
#define DHTPIN 3 // вывод, к которому подключается датчик
058
#define DHTTYPE DHT22 // DHT 22 (AM2302)
059
060
// SoftwareSerial mySerialGSM(GSMTXPIN, GSMRXPIN); // TX, RX GSM MEGA
061
062
LiquidCrystal_I2C lcd(0x3F, 20, 4);
// Устанавливаем дисплей
063
064
OneWire ds(A1);
// подключен DS18B20 через I2S к A1 пину (резистор к питанию на 4.7к для одного датчика, и 3.3 кОм для двух - обязателен)
065
066
DHT dht(DHTPIN, DHTTYPE);
067
068
RTC_DS1307 RTC;
// Creation of the Real Time Clock Object
069
070
SFE_BMP180 pressure;
// You will need to create an SFE_BMP180 object, here called "pressure":
071
072
//const int chipSelect = 10; // for UNO
073
const
int
chipSelect = 53;
// for MEGA
074
075
076
byte
led = 13;
//**********************************
077
078
double
BMP180, T18B20, T1, T11, T2, P;
// переменные для датчиков давления и температуры
079
float
H, TDH22;
080
bool
J;
081
char
bufT[9], bufD[11],
string
[160], stringD[160];
082
byte
cfg, cfgA, cfgB;
083
char
status;
084
char
str_tempT1[7];
085
char
str_tempT11[7];
086
char
str_tempT2[7];
087
char
str_tempP[7];
088
char
str_tempH[7];
089
uint8_t hh, mm, ss;
// час, минута, секунда
090
uint8_t ddd, mmm;
// день месяца, месяц
091
uint16_t yyy;
// год
092
093
//***** пременные для датчиков DS18B20 ****//
094
byte
present = 0;
//
095
byte
data[12], dataA[12], dataB[12];
//
096
//******************************************//
097
098
DeviceAddress addr = {0x28, 0xFF, 0x13, 0xDA, 0x80, 0x16, 0x04, 0x25};
099
DeviceAddress addrB = {0x28, 0xFF, 0x89, 0xCE, 0x71, 0x16, 0x04, 0x3F};
100
//*****************************************//
101
102
// создаём недостающие символы
103
uint8_t bukva_G[8] = {B01100, B10010, B10010, B01100, B00000, B00000, B00000};
// градус
104
//uint8_t bukva_1[8] = {B00000, B00000, B00100, B01100, B00100, B00100, B01110}; // маленькая единичка
105
//uint8_t bukva_2[8] = {B00000, B00000, B01100, B10010, B00010, B01000, B11110}; // маленькая двойка
106
// //uint8_t bukva_3[8] = {B00100, B01110, B10101, B00100, B00100, B00100, B00100}; // стрелка вверх
107
// //uint8_t bukva_4[8] = {B00100, B00100, B00100, B00100, B10101, B01110, B00100}; // стрелка вниз
108
// //uint8_t bukva_5[8] = {B00100, B01110, B10101, B00100, B10101, B01110, B00100}; // стрелка вверх-вниз
109
110
111
112
void
setup
()
113
{
114
Serial
.begin(9600);
115
Serial1.begin(9600);
116
Serial2.begin(9600);
117
118
// RTC.adjust(DateTime(__DATE__, __TIME__)); // установка времени от коипа почему-то не работаеит
119
120
delay(100);
121
pinMode(led, OUTPUT);
122
digitalWrite(led, LOW);
123
124
// Serial.println("GSM NEOWAY promote site istarik.ru");
125
126
127
pinMode(9, OUTPUT);
128
digitalWrite(9,LOW);
129
delay(1000);
130
digitalWrite(9,HIGH);
131
delay(2000);
132
digitalWrite(9,LOW);
133
delay(5000);
134
135
Serial
.println();
136
Serial
.println(
"Turn on AOH:"
);
137
Serial2.println(
"AT+CLIP=1"
);
//включить АОН
138
delay(500);
139
Serial
.println(
"Text format sms:"
);
140
Serial2.println(
"AT+CMGF=1"
);
// текстовый формат SMS
141
delay(500);
142
Serial
.println(
"Mode GSM:"
);
143
Serial2.println(
"AT+CSCS=\"GSM\""
);
// кодировка текста - GSM
144
delay(500);
145
Serial
.println(
"SMS to terminal:"
);
146
Serial2.println(
"AT+CNMI=2,2,0,0,0"
);
// вывод смс в консоль
147
delay(500);
148
149
150
Wire.begin();
151
RTC.begin();
152
RTC.isrunning();
153
dht.begin();
154
155
lcd.init();
156
lcd.backlight();
// Включаем подсветку дисплея
157
// lcd.setCursor(0, 0);
158
159
// Initialize the sensor (it is important to get calibration values stored on the device).
160
pressure.begin();
161
162
lcd.createChar(0, bukva_G);
// создаем символ и записываем их в память LCD
163
// lcd.createChar(1, bukva_1); // создаем символ и записываем их в память LCD
164
// lcd.createChar(2, bukva_2); // создаем символ и записываем их в память LCD
165
//// lcd.createChar(3, bukva_3); // создаем символ и записываем их в память LCD
166
//// lcd.createChar(4, bukva_4); // создаем символ и записываем их в память LCD
167
//// lcd.createChar(5, bukva_5); // создаем символ и записываем их в память LCD
168
169
170
pinMode(53, OUTPUT);
171
SD.begin(53);
172
173
J =
true
;
174
175
// void powerUpOrDown() //***** включение модуля SIM900 (pin9 модуля соединён с pin9 Меги) *****************
176
//{
177
// pinMode(9, OUTPUT);
178
// digitalWrite(9,LOW);
179
// delay(1000);
180
// digitalWrite(9,HIGH);
181
// delay(2000);
182
// digitalWrite(9,LOW);
183
// delay(5000);
184
//}
185
186
}
187
188
void
loop
()
189
{
190
191
byte
i;
192
byte
present = 0;
193
byte
type_s;
194
// float celsius, fahrenheit;
195
196
//****************************** получаем время от DS1307 *******************************************
197
DateTime now = RTC.now();
198
199
// читаем время и записываем его в буфер
200
hh = now.hour();
201
mm = now.minute();
202
ss = now.second();
203
sprintf(bufT,
"%02d:%02d:%02d"
, hh, mm, ss );
204
205
// Serial.println(bufT);
206
207
// читаем дату и записываем его в буфер
208
ddd = now.day();
209
mmm = now.month();
210
yyy = now.year();
211
sprintf(bufD,
"%02d.%02d.%02d"
, ddd, mmm, yyy );
212
213
//**********************************************************************************************
214
215
//***********************получение GPS-данных*************************************************
216
217
218
bool
newdata =
false
;
219
unsigned
long
start = millis();
220
// Every 5 seconds we print an update
221
// while (millis() - start < 5000)
222
// Every 0.4 seconds we print an update
223
while
(millis() - start < 400)
224
225
{
226
if
(Serial1.available())
227
{
228
char
c = Serial1.read();
229
// Serial.print(c); // uncomment to see raw GPS data
230
if
(gps.encode(c))
231
{
232
newdata =
true
;
233
break
;
// uncomment to print new data immediately!
234
}
235
}
236
}
237
if
(newdata)
238
{
239
gpsdump(gps);
240
}
241
else
242
{
243
lcd.setCursor(0, 3);
244
lcd.print(
" last"
);
245
}
246
//*********************************************************************************************
247
248
//*********************** вывод времени и даты на дисплей 2004 **********************************
249
250
//*********** Выводим на экран дату **********************
251
//lcd.setCursor(0, 2);
252
//lcd.print(bufD);
253
254
//*********** Выводим на экран время *********************
255
lcd.setCursor(12, 2);
256
lcd.print(bufT);
257
//*********************************************************************************************
258
259
260
//********* получаем температуру с датчик DS18B20 **************************
261
262
//************A = 0x28, 0xFF, 0x13, 0xDA, 0x80, 0x16, 0x04, 0x25 *********************************
263
264
ds.reset();
265
ds.select(addr);
266
ds.write(0x44, 1);
// начало коммуникации
267
268
present = ds.reset();
269
ds.select(addr);
270
ds.write(0xBE);
// читаем значение
271
272
for
( i = 0; i < 9; i++)
273
{
274
// смотрим 9 байтов
275
data[i] = ds.read();
276
}
277
278
// Преобразуем получненный данные в температуру
279
// Используем int16_t тип, т.к. он равен 16 битам
280
// даже при компиляции под 32-х битный процессор
281
int16_t raw = (data[1] << 8) | data[0];
282
// byte cfg = (data[4] & 0x60);
283
cfg = (data[4] & 0x60);
284
285
raw = raw & ~3;
286
287
T1 = (
float
)raw / 16.0;
288
289
290
// Serial.println(T1);
291
292
//*************** B = 0x28, 0xFF, 0x89, 0xCE, 0x71, 0x16, 0x04, 0x3F ********************************
293
294
ds.reset();
295
ds.select(addrB);
296
ds.write(0x44, 1);
// начало коммуникации
297
298
present = ds.reset();
299
ds.select(addrB);
300
ds.write(0xBE);
// читаем значение
301
302
for
( i = 0; i < 9; i++)
303
{
304
// смотрим 9 байтов
305
dataB[i] = ds.read();
306
}
307
308
// Преобразуем получненный данные в температуру
309
// Используем int16_t тип, т.к. он равен 16 битам
310
// даже при компиляции под 32-х битный процессор
311
int16_t rawB = (dataB[1] << 8) | dataB[0];
312
// byte cfg = (data[4] & 0x60);
313
cfgB = (dataB[4] & 0x60);
314
315
rawB = rawB & ~3;
316
317
T11 = (
float
)rawB / 16.0;
318
319
//Serial.println(T11);
320
321
322
//************** получаем температуру и давление с датчика BMP180 *************************
323
status = pressure.startTemperature();
324
if
(status != 0)
325
{
// Wait for the measurement to complete:
326
delay(status);
327
status = pressure.getTemperature(BMP180);
328
if
(status != 0)
329
{
330
status = pressure.startPressure(3);
331
if
(status != 0)
332
{
// Wait for the measurement to complete:
333
delay(status);
334
status = pressure.getPressure(P, BMP180);
335
}
336
}
337
P = ((P * 0.0295333727) * 25.4);
// выражаем давление в мм ртутного столба
338
}
339
340
//*************** ВЫВОД ПОКАЗАНИЙ на дисплей 2004 ********************
341
342
//****************** выводим температуру в позицию 1 *************
343
344
//**************** выводим температуру с датчиа DS18B20 ********************
345
346
lcd.setCursor(5, 0);
347
lcd.print(
" "
);
348
lcd.setCursor(0, 0);
349
lcd.print(
"t1"
);
350
lcd.print(
"= "
);
351
352
if
(T11 > 0)
353
{
354
lcd.print(
"+"
);
355
}
356
357
lcd.print(T11, 1);
358
lcd.write(0);
359
lcd.print(
" "
);
360
361
//******************************************************************************
362
363
364
//************************ выводим температуру в позицию 2 *******************
365
366
//************************* выводим температуру с датчиа DS18B20 *************
367
368
lcd.setCursor(5, 1);
369
lcd.print(
" "
);
370
lcd.setCursor(0, 1);
371
lcd.print(
"t2"
);
372
lcd.print(
"= "
);
373
374
if
(T1 > 0)
375
{
376
lcd.print(
"+"
);
377
}
378
379
lcd.print(T1, 1);
380
lcd.write(0);
381
lcd.print(
" "
);
382
383
//*********************************************************
384
385
//******** получаем температуру и влажность с датчика DTH22 *****************
386
// считывание температуры или влажности занимает примерно 250 мс!
387
// считанные показания могут отличаться от актуальных примерно на 2 секунды (это очень медленный датчик)
388
H = dht.readHumidity();
389
TDH22 = dht.readTemperature();
// Считывание температуры в цельсиях
390
391
392
//********************** выводим температуру в позицию 3 ***************
393
394
//************************* выводим температуру с датчиа DHT22 ********
395
T2 = TDH22;
396
397
lcd.setCursor(0, 2);
398
// lcd.print("t");
399
// lcd.write(2);
400
lcd.print(
"t3"
);
401
lcd.print(
"= "
);
402
403
if
(T2 > 0)
404
{
405
lcd.print(
"+"
);
406
}
407
408
lcd.print(T2, 1);
409
lcd.write(0);
410
lcd.print(
" "
);
411
//********************************************************************
412
413
//********* выводим давление с датчиа BMP180 ****************************
414
lcd.setCursor(12, 0);
415
lcd.print(
"P= "
);
416
lcd.print(P, 1);
417
418
//********* выводим влажность с датчиа DHT22 ***********************
419
lcd.setCursor(12, 1);
420
lcd.print(
"H= "
);
421
lcd.print(H, 1);
422
lcd.print(
"%"
);
423
lcd.print(
" "
);
424
//*********************************************************************************************************************
425
426
427
//********************************* записываем данные на карту памяти *************************************************
428
//***** писать будем один раз в полчаса *********
429
430
//*********** готовим строку для вывода в файл ****************
431
//***** переводим данные из double и float в символы ******
432
// 4 is mininum width, 2 is precision; float value is copied onto str_temp
433
dtostrf(T1, 4, 2, str_tempT1);
434
dtostrf(T11, 4, 2, str_tempT11);
435
dtostrf(T2, 4, 2, str_tempT2);
436
dtostrf(P, 5, 2, str_tempP);
437
dtostrf(H, 4, 2, str_tempH);
438
439
//************************* формируем строку ******************************
440
sprintf(stringD,
"%02d.%02d.%02d %02d:%02d:%02d Tout=%s Ttube=%s Troom=%s P=%s Hroom=%s"
, ddd, mmm, yyy, hh, mm, ss, str_tempT11, str_tempT1, str_tempT2, str_tempP, str_tempH);
441
// Строка готова, можно её посмотреть:
442
// Serial.println(stringD);
443
// delay(100);
444
445
//********** формируем имя файла *******************************
446
File myFile;
447
char
NameOfFile[6] = {0,0,0,0,0,0};
448
// формируем имя файла
449
sprintf(NameOfFile,
"%02d_%02d_%02d.txt"
, (yyy - 2000), mmm, ddd);
450
//**************************************************************
451
452
//***** писать будем один раз в полчаса *********
453
if
((mm == 0 or mm == 30) and (ss < 10 ) and (J ==
true
))
//************ выбираем нулевую или тридцатую минуту получаса, **************
454
// и проверяем - писали ли уже в этом цикле - J==0 говорит, что уже писали
455
{
456
// ************ если условие выполняется, то пишем строку данных в файл *****************************************
457
458
//****************************** работа с картой памяти *****************************************
459
460
myFile = SD.open(NameOfFile, FILE_WRITE);
//********** открываем файл ***************************
461
462
463
//******* пишем строку данных в файл ***********************
464
myFile.println(stringD);
465
466
//********** закрываем файл ***************************
467
myFile.close();
468
469
//*************************************************** окончание записи в файл **************************************
470
J =
false
;
// отмечаем, что один раз уже писали, запрещаем в этом цикле писать вторично (J==false это запрет записи)
471
}
472
else
// если условие не выполняется (в этом цикле уже писали), то ничего не пишем,
473
{
// разрешаем запись на будущее (J==true это разрешение записи),
474
J =
true
;
// и ждём следующую нулевую или тридцатую минуту
475
}
476
477
//*********************************************************************************************
478
479
//****************************работаем с GSM-модулем**********************************
480
481
delay(500);
482
483
if
(Serial2.available())
//если модуль что-то послал
484
{
485
486
char
ch =
' '
;
487
String val =
""
;
488
489
while
(Serial2.available())
490
{
491
ch = Serial2.read();
492
val +=
char
(ch);
//собираем принятые символы в строку
493
delay(500);
494
}
495
496
Serial
.print(
"Neo send> "
);
497
Serial
.println();
498
Serial
.println(val);
499
500
if
(val.indexOf(
"+CMT"
) > -1)
// если есть входящее sms
501
{
502
503
if
(val.indexOf(
"*t"
) > -1)
// смотрим, что за команда
504
{
505
smsMeteo(String(stringD), String(
"+7XXXXXXXXXX"
));
// ВПИШИТЕ ВАШ НОМЕР
506
}
507
508
if
(val.indexOf(
"money"
) > -1)
// смотрим, что за команда
509
{
510
delay(500);
511
Serial2.println(
"ATD#100#;"
);
512
}
513
}
514
515
if
(val.indexOf(
"+CUSD"
) > -1)
// если есть входящее sms
516
{
517
if
(val.indexOf(
"Balance"
) > -1)
// смотрим, что за команда
518
{
519
delay(500);
520
521
val = val.substring(val.indexOf(
"Balance"
),val.indexOf(
"r"
));
522
sms(String(val), String(
"+7XXXXXXXXXX"
));
// ВПИШИТЕ ВАШ НОМЕР
523
}
524
}
525
}
526
//**************************************************************************************************
527
528
529
}
530
531
532
void
smsMeteo(String stringD, String phone)
// отправка СМС метеоданными
533
{
534
Serial
.println(
"Start SMS send"
);
535
Serial2.println(
"AT+CMGS=\""
+ phone +
"\""
);
536
delay(500);
537
Serial2.print(stringD);
538
delay(500);
539
Serial2.print((
char
)26);
540
delay(500);
541
Serial
.println(
"SMS send OK"
);
542
delay(500);
543
}
544
545
//void smsBalance(String text, String phone) // отправка СМС с балансом модема
546
void
sms(String text, String phone)
547
{
548
Serial
.println(
"Start SMS send"
);
549
Serial2.println(
"AT+CMGS=\""
+ phone +
"\""
);
550
delay(500);
551
Serial2.print(text);
552
delay(500);
553
Serial2.print((
char
)26);
554
delay(500);
555
Serial
.println(
"SMS send OK"
);
556
delay(500);
557
}
558
559
560
void
gpsdump(TinyGPS & gps)
561
562
{
563
unsigned
long
date, time;
564
int
year;
565
byte
month, day, hour, minute, second;
566
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
567
568
hour = hour + 3;
569
if
(hour > 23)
570
hour = (hour - 24);
571
572
// if((hh > 3) & (hh <24))
573
574
// if((hour > 3) & (hour <24))
575
// {
576
// RTC.adjust(DateTime(year, month, day, hour, minute, second)); // This line sets the RTC with an explicit date & time
577
// }
578
579
//***************************** вывод GPS-времени на дисплей *****************************
580
581
lcd.setCursor(0, 3);
582
lcd.print(
" GPS "
);
583
584
lcd.setCursor(6, 3);
585
586
lcd.print(day);
587
lcd.print(
"."
);
588
if
(month < 10)
589
lcd.print(
"0"
);
590
lcd.print(month);
591
592
lcd.setCursor(12, 3);
593
if
(hour < 10)
594
lcd.print(
"0"
);
595
lcd.print(hour);
596
lcd.print(
":"
);
597
598
if
(minute < 10)
599
lcd.print(
"0"
);
600
lcd.print(minute);
601
lcd.print(
":"
);
602
603
if
(second <10)
604
lcd.print(
"0"
);
605
lcd.print(second);
606
607
if
((hour > 3) & (hour <24))
608
{
609
RTC.adjust(DateTime(year, month, day, hour, minute, second));
// This line sets the RTC with an explicit date & time
610
}
611
612
}
как ты думаешь, нахрена людям в готовом коде закомментированные куски? Типа этого
175
// void powerUpOrDown() //***** включение модуля SIM900 (pin9 модуля соединён с pin9 Меги) *****************
176
//{
177
// pinMode(9, OUTPUT);
178
// digitalWrite(9,LOW);
179
// delay(1000);
180
// digitalWrite(9,HIGH);
181
// delay(2000);
182
// digitalWrite(9,LOW);
183
// delay(5000);
184
//}
Если ты код не поленишься почистить, текст станет меньше
loop() длиной в 340 строчек, я щитаю, просто шикарен, никто так не умеет. Для сравнения, я счас Радио делаю на Атмега8, вот мой loop(). Весь. Больше туда ничего вставляться не будет.
1
void
loop
()
2
{
3
TuningPot.Read();
// почитать потенциометр настройки
4
Timers.Run();
// тикнуть таймерами
5
Radio.ReadStatus();
// прочитать статус Радиомодуля
6
btnLight.Read();
// Прочитать кнопку включения подсветки
7
8
if
(MessageList) Dispatch(MessageList.GetMessage());
// если ктонить из них прислал сапщение - обработать его
9
}
Да, конечно. Можно почистить. И delay'ем я с тех пор научился не пользоваться...
Да, текст станет компактнее. Код красивее. Безусловно.
Но... я ведь не хвастаться сюда пришёл, и красоваться дыртаньяном... Я просто делюсь рабочим кодом. Древним, лохматым... Рабочим, пусть и не красивым. Мне, к примеру, очень много пользы приносят чужие именно "кривые" коды... Может, и мой кому сгодится. Выдернет что-то полезное, и сделает лучше.
А за совет - спасибо.
Нууу, какбэ это щитается хорошим тоном, ничего лишнего.
Нуу, какбэ да. Считается. У программистов. Оные готовы за лишнюю строку тухлыми тапками закидать насмерть. И я их даже где-то понимаю, да. Когда заказчику с тугим кошельком... или там прохфессору в курсовой... тем более - в дипломе. Или друг перед дружкой повыёживаться. Это так, достойно вполне.
Но тут, всё-таки, несколько иная ситуё... ситуа... ладно, проехали. Тут форум, где такое обилие тем (чаще пустых) про метео и охрану безумных домов, что мне показалось - будет полезно для кого-то посмотреть древний, кривой, лохматый (в смысле строк и комментов), но вот уже несколько лет работающий самописный код. Не, как в учебнике. Ну просто ради разнообразия. На фоне Гуров (с Большой Буквы) с одной стороны, и "поможите кто чем может"(с) с другой.
))
Ну это из серии, а давайте я вас говном накормлю, для разнообразия, невкусно, канеш, дак зато бесплатно, даже, мошт, и полезно кому будет.
А по существу мысли есть?
А то, боюсь, про рюшечки-плюшечки мало кому интересно. Конкретно - что в этом супе не так? Что мусор в листинге - это понятно, но "на скоростные качества влияния не оказывает"(с) - работать будет одинаково, что с мусором, что без. Вот со временем я где-то накосячил, работает кривовато. То есть пока GPS ловится нормально, то всё хорошо, а вот если нет, и если сигнал GPS поймался как-то не так - может совершенно фантастические циферки выдать.
Ну и календарь я поленился писать, в итоге дата в интервале от 00:00 до 03:00 не правильная. А как обойтись без самописного календаря - знаний не хватает.
Не то, чтобы я просил себе какой-то помощи в этом вопросе (меня-то несколько лет всё в этой штуке более-менее устраивает), но вообще было бы полезно. Во всяком случае, гораздо полезнее вылизывания листинга ради фэншуя.
Что же до дерьма, так ведь никто силой не кормит - "не нравится, не ешь"(с)
За критику спасибо.