-
11. Data: 2014-11-12 12:43:21
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Atlantis <m...@w...pl>
W dniu 2014-11-12 12:17, J.F. pisze:
> Rozumiem ze czas tam jest mierzony przerwaniem programowym na podstawie
> czestotliwosci zegarowej uP.
Tak. Przerwanie TIMER0_COMPA_vect jest wywoływane co 10ms. W procedurze
jego obsługi inkrementowana jest zmienna. Jeśli jej wartość przekroczy
100, wykonywana jest instrukcja warunkowa wewnątrz której zwiększana
jest wartość zegara (a także obsługiwane jest kilka dodatkowych
programowych timerów).
> Czestotliwosc zegarowa - jesli kwarcem, to powinna byc w miare dokladna.
> Tak powiedzmy do 100ppm, jesli dales byle jakie elementy.
> Czyli sekunda na trzy godziny.
MCU jest taktowany sygnałem 12,5MHz, pochodzącym z układu ENC28J60 który
z kolei jest taktowany kwarcem 25 MHz. Niedokładność wedle mkAVR
Calculatora wynosi 0,06%.
Zresztą zachowanie układu wcale nie wygląda na dryf spowodowany
niedokładnością wzorca. Opóźnienie wynoszące od kilku do kilkudziesięciu
sekund często mam tuż po synchronizacji.
> Porownujesz z jakims innym urzadzeniem ... ale jakim ?
Porównałem z webowymi wzorcami (np. currenttimestamp.com). Pokazują
dokładnie to samo, co Raspberry Pi. Czas na Atmedze prawie zawsze różni
się o pewną liczbę sekund...
> Moze tam jest numer ze np odczytujesz koncowke 59 sekund, a minuty juz
> po zmianie ...
Nie dokonuję konwersji na "human readable time". Zależy mi tylko na
timestampie, najlepiej w formacie Unix epoch.
-
12. Data: 2014-11-12 12:49:31
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Atlantis <m...@w...pl>
W dniu 2014-11-12 12:36, Andrzej W. pisze:
> Ten kod to interpretuje każdy pakiet UDP co ma 56 bajtów, tak?
Sprawdza też jeszcze, czy zgadza się port.
> Ja u siebie czytam czas z pozycji [40:43], widzę, że Ty czytasz [82:85].
> Ten bufor to "czyste" dane z pakietu UDP, czy jest tam też jakiś
> nagłówek? Bo czytasz znacznie dalej niż długość pakietu UDP.
Z tego co pamiętam, to w buforze znajduje się kompletna ramka
Ethernet/MAC, pobrana bufora ENC28J60. Tuxgraphics to mocno uproszczony
stos, który operuje właśnie na pojedynczych ramkach i nie jest w stanie
obsługiwać dłuższych komunikatów.
W każdym razie nie sądzę, żeby tutaj leżała przyczyna. Gdyby do układu
"zabłąkał się" przypadkowy pakiet UDP o oczekiwanej długośc, wysłany na
oczekiwany port, to otrzymywałbym po prostu bezsensowne dane. Ja
tymczasem otrzymuję wartość zbliżoną do obecnego czasu, różniącą się o
tych kilka do kilkudziesięciu sekund.
-
13. Data: 2014-11-12 12:59:04
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Marek <f...@f...com>
On Wed, 12 Nov 2014 12:49:31 +0100, Atlantis <m...@w...pl>
wrote:
> Ja tymczasem otrzymuję wartość zbliżoną do obecnego czasu, różniącą
się o
> tych kilka do kilkudziesięciu sekund.
Jesteś pewien, że prawidłowo interpretujesz otrzymane dane? Czy czas
z serwera ntp już jest przesunięty czy przesunięcie następuje podczas
lokalnego odczytu tuż po odbiorze (ta funkcja licząca *time)?
--
Marek
-
14. Data: 2014-11-12 13:49:05
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Atlantis <m...@w...pl>
W dniu 2014-11-12 12:59, Marek pisze:
> Jesteś pewien, że prawidłowo interpretujesz otrzymane dane? Czy czas z
> serwera ntp już jest przesunięty czy przesunięcie następuje podczas
> lokalnego odczytu tuż po odbiorze (ta funkcja licząca *time)?
Tego właśnie nie wiem. W każdym razie patrzę na kod i nie widzę co
mogłoby być nie tak. Zastosowałem trochę inny, jaśniejszy sposób
przeliczania danych z bufora na timestamp:
uint32_t sec_since_1900 = 0;
(...)
sec_since_1900 = (uint32_t)buf[0x52] << 24;
sec_since_1900 |= (uint32_t)buf[0x53] << 16;
sec_since_1900 |= (uint32_t)buf[0x54] << 8;
sec_since_1900 |= (uint32_t)buf[0x55];
cli();
*time = (sec_since_1900 - 2208988800UL);
sei();
Efekt jest dokładnie taki sam.
Gdybym czytał dane z nieprawidłowych komórek bufora, to w efekcie
otrzymywałbym kompletnie bezsensowną wartość, a nie wynik różniący się
od obecnego czasu o kilka-kilkadziesiąt sekund.
Raspberry Pi jest synchronizowane z tego samego serwera czasu.
-
15. Data: 2014-11-12 14:01:12
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: "Andrzej W." <a...@w...pl>
W dniu 2014-11-12 o 13:49, Atlantis pisze:
> Gdybym czytał dane z nieprawidłowych komórek bufora, to w efekcie
> otrzymywałbym kompletnie bezsensowną wartość, a nie wynik różniący się
> od obecnego czasu o kilka-kilkadziesiąt sekund.
W pakiecie SNTP masz chyba cztery różne znaczniki czasu, jakaś szansa na
to by odczytać coś sensownego z innej lokalizacji istnieje, jednak nie
spodziewał bym się tam różnicy 60 sekund a raczej jednej dwóch.
Chyba, że robisz wielokrotne uaktualnienie czasu i za każdym razem
wczytujesz czas nadania swojego zapytania (Originate Timestamp).
--
AWa.
-
16. Data: 2014-11-12 14:06:57
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Atlantis <m...@w...pl>
Zauważyłem jeszcze jedną ciekawą rzecz. Jeśli przeprowadzę dłuższą serię
ręcznych synchronizacji czasu, to różnica się niweluje i wynosi 0-1 sek.
Ta jedna sekunda może już po prostu wynikać z różnicy w czasie, jaki
jest potrzebny do wykonania skryptu.
Teraz wyłączyłem automatyczną synchronizację i zobaczę jak się będzie
zachowywał czas.
Procedura wysyłająca request wygląda następujaco:
void client_ntp_request(uint8_t *buf,uint8_t *ntpip,uint8_t
srcport,uint8_t *dstmac)
{
uint8_t i=0;
uint16_t ck;
if (!enc28j60linkup())return;
//
while(i<6){
buf[ETH_DST_MAC +i]=dstmac[i]; // gw mac in local lan or
host mac
buf[ETH_SRC_MAC +i]=macaddr[i];
i++;
}
buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
fill_buf_p(&buf[IP_P],9,iphdr);
buf[IP_ID_L_P]=ipid; ipid++;
buf[IP_TOTLEN_L_P]=0x4c;
buf[IP_PROTO_P]=IP_PROTO_UDP_V;
i=0;
while(i<4){
buf[IP_DST_P+i]=ntpip[i];
buf[IP_SRC_P+i]=ipaddr[i];
i++;
}
fill_ip_hdr_checksum(buf);
buf[UDP_DST_PORT_H_P]=0;
buf[UDP_DST_PORT_L_P]=0x7b; // ntp=123
buf[UDP_SRC_PORT_H_P]=10;
buf[UDP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
buf[UDP_LEN_H_P]=0;
buf[UDP_LEN_L_P]=56; // fixed len
// zero the checksum
buf[UDP_CHECKSUM_H_P]=0;
buf[UDP_CHECKSUM_L_P]=0;
// copy the data:
i=0;
// most fields are zero, here we zero everything and fill later
while(i<48){
buf[UDP_DATA_P+i]=0;
i++;
}
fill_buf_p(&buf[UDP_DATA_P],10,ntpreqhdr);
//
ck=checksum(&buf[IP_SRC_P], 16 + 48,1);
buf[UDP_CHECKSUM_H_P]=ck>>8;
buf[UDP_CHECKSUM_L_P]=ck& 0xff;
enc28j60PacketSend(90,buf);
}
-
17. Data: 2014-11-12 14:19:26
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Atlantis <m...@w...pl>
Hmm... Sprawa jeszcze dziwniejsza - pomimo wyłączonej synchronizacji
różnica czasu zdaje się narastać w tempie dużo szybszym, niż mogłoby to
wynikać z zastosowanego wzorca - sekunda na kilka minut...
Jednak po pojedynczej synchronizacji praktycznie nigdy nie mam różnicy
wynoszącej 0-1 sek. Muszę wykonać długi ciąg ręcznych synchronizacji,
żeby sytuacja tak wyglądała.
-
18. Data: 2014-11-12 15:02:16
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Marek <f...@f...com>
On Wed, 12 Nov 2014 14:19:26 +0100, Atlantis <m...@w...pl>
wrote:
> Hmm... Sprawa jeszcze dziwniejsza - pomimo wyłączonej synchronizacji
> różnica czasu zdaje się narastać w tempie dużo szybszym, niż
mogłoby to
> wynikać z zastosowanego wzorca - sekunda na kilka minut...
Bez synch. późni się czy spieszy? Pisałeś, że ten *time liczysz w
przerwaniu timera 1ms, który odlicza czas lokalny, uwzględniłeś czas
tych obliczeń *time (maltretujesz 8bit mcu obliczeniami na int32,
timer powinien być aktywny podczas ich trwania)?
--
Marek
-
19. Data: 2014-11-12 15:45:05
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Atlantis <m...@w...pl>
W dniu 2014-11-12 15:02, Marek pisze:
> Bez synch. późni się czy spieszy?
Spóźnia się. Z każdą chwilą coraz bardziej.
> Pisałeś, że ten *time liczysz w przerwaniu timera 1ms, który odlicza
> czas lokalny, uwzględniłeś czas tych obliczeń *time (maltretujesz
> 8bit mcu obliczeniami na int32, timer powinien być aktywny podczas
> ich trwania)?
W tej chwili używam przerwania 10ms.
Hmm... Uważasz, że operacje na zmiennych mogą zajmować więcej czasu,
przez co różnica odkłada się z każdą sekundą?
Czy to (wraz z czasem potrzebnym na obliczenie nowego czasu z pakietu
NTP) tłumaczyłoby także początkowe, kilkusekundowe opóźnienie,
pojawiające się zwykle po synchronizacji?
Funkcja obsługująca przerwanie wygląda następująco:
ISR(TIMER0_COMPA_vect) {
ten_millis++;
if (ten_millis > 100) {
geiger_pulses[seconds] = TCNT1;
TCNT1 = 0;
seconds = (seconds + 1) % 60;
one_second_tick = 1;
uptime++;
if (rtc) rtc++;
if (ntp_update_timer) ntp_update_timer--;
if (bmp085_update_timer) bmp085_update_timer--;
if (dht_update_timer) dht_update_timer--;
if (graphite_upload_timer) graphite_upload_timer--;
ten_millis = 0;
}
}
Pierwszy blok poleceń w instrukcji warunkowej to obsługa licznika
Geigera (właściwe główny czujnik zamontowany w tym urządzeniu) - co
sekundę ilość impulsów zliczonych przez licznik sprzętowy jest
zapisywana do tablicy, sam licznik jest czyszczony i liczony jest numer
kolejnego pola do zapisania.
Zmienna "one_second_tick" to uint8_t - jej jedyną funkcją jest
przekazywanie do pętli głównej informacji o przekręceniu się licznika
sekund.
Zmiennymi 32bitowymi są jedynie uptime i rtc.
Zmienne bmp085_update_timer i dht_update_timer mają rozmiar ośmiu bitów
- odliczają czas pomiędzy kolejnymi odczytami czujników BMP085 oraz DHT11.
Podobne jest przeznaczenie szesnastobitowych zmiennych ntp_update_timer
oraz graphite_upload_timer, które odliczają czas do kolejnego wysłania
requesta do serwera NTP oraz uploadu wyników pomiarów do Graphite'a.
Jeśli to tu leży przyczyna, to w jaki sposób powinienem wprowadzić
poprawkę? Jak ustalić czas potrzebny do wykonania tych operacji?
-
20. Data: 2014-11-12 17:21:05
Temat: Re: Różny czas pomimo synchronizacji z NTP
Od: Jakub Rakus <s...@o...pl>
On 12.11.2014 15:45, Atlantis wrote:
> W tej chwili używam przerwania 10ms.
> Hmm... Uważasz, że operacje na zmiennych mogą zajmować więcej czasu,
> przez co różnica odkłada się z każdą sekundą?
Prawdę powie Ci kod w assemblerze, zajrzyj tam i policz ile to
instrukcji wymaga. Takie liczenie bywa upierdliwe, szczególnie gdy
fragment kodu zawiera jakieś pętle i odwołania do funkcji, ale wynik
bywa zaskakujący i dobrze uświadamia gdzie spędzamy za dużo czasu.
> Jeśli to tu leży przyczyna, to w jaki sposób powinienem wprowadzić
> poprawkę? Jak ustalić czas potrzebny do wykonania tych operacji?
Jak wyżej plus warto sobie przypomnieć prehistorię czyli dobieranie
wartości wpisywanych do 16 bitowych liczników na 51', żeby się ładnie
"zerowały":
http://edsim51.com/8051Notes/8051/timers.html
--
Pozdrawiam
Jakub Rakus