RTV forum PL | NewsGroups PL

Niepokojące różnice czasowe między Atmegą a Raspberry Pi po synchronizacji NTP

Różny czas pomimo synchronizacji z NTP

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Niepokojące różnice czasowe między Atmegą a Raspberry Pi po synchronizacji NTP

Goto page Previous  1, 2, 3, 4

Marek
Guest

Thu Nov 13, 2014 9:26 am   



On Thu, 13 Nov 2014 08:55:58 +0100, Atlantis <marekw1986NOSPAM@wp.pl>
wrote:
Quote:
Z tego co pamiętam, to było 81. Przy czym mierzone ze stoperem jako
punktem odniesienia, wiec nie jestem w stanie zagwarantować
dokładności
na poziomie tej ostatniej sekundy. Wink

To może 83?
Tak kombinuję:
(249*(1/(12500000/1024))-0.02)*50*4200 = 83.5968 s

(250*(1/(12500000/1024))-0.02)*50*4200 = 100.8 s

Jak widac niewielka zmiana wartości OC (turaj 249 lub 250) powoduje
znaczne wachanie opóźnienia czasu.
Być może jednak ten timer nie został skonfigurowany tak jak zakładasz
i tyka inaczej.

--
Marek

Atlantis
Guest

Thu Nov 13, 2014 9:45 am   



Poeksperymentowałem trochę i udało mi się skalibrować ten timer.
Teraz w rejestr OCR0A wpisana jest wartość 238. Zegar spieszy o jakąś
sekundę na każde 10 minut. Nie jest może to idealną sytuacją, ale w
każdym razie jest to najlepsze rozwiązanie, jakie udało mi się znaleźć
do tej pory.
Dziwi mnie tylko ta rozbieżność w stosunku do obliczeń z kalkulatora...

Wychodzi jednak na to, że z synchronizacją NTP też coś jest nie tak. Tuż
po uruchomieniu układu mam czas różniący się o kilka sekund od
rzeczywistego. Uzyskanie dokładnego pokrycia wymaga przeprowadzenia
kilku-kilkunastu ręcznie wymuszonych synchronizacje, jedna po drugiej.
Po takiej operacji czas dryfuje już normalnie. Nie jestem jednak pewien,
czy kolejne (pojedyncze, automatyczne) synchronizacje znów go nie
zafałszują.

Jakiś pomysł co do możliwej przyczyny takiego stanu rzeczy? Czyżby
funkcje obsługi NTP w bibliotece tuxgraphics posiadały jakiś błąd?

Atlantis
Guest

Thu Nov 13, 2014 10:03 am   



Hmm... Coś jeszcze jest na rzeczy z tą synchronizacją.
Pojedyncza, automatyczna synchronizacja (wywołana po 10 minutach dla
skompensowania tego sekundowego błędu) wprowadziła 14 sekundowe opóźnienie.

Czy kod funkcji wysyłającej request wygląda w porządku?

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<4Cool{
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);
}

Zastanawia mnie zmienna ntpreqhdr. Jaką funkcję ona pełni?
Bo jej deklaracja wygląda następująco:

const char ntpreqhdr[] PROGMEM ={0xe3,0,4,0xfa,0,1,0,0,0,1};

Ktoś z Was wspominał, że request powinien zawierać informację o czasie.
Tutaj nigdzie nie jestem o nią proszony...

Atlantis
Guest

Thu Nov 13, 2014 10:07 am   



W dniu 2014-11-13 09:26, Marek pisze:

Quote:
Jak widac niewielka zmiana wartości OC (turaj 249 lub 250) powoduje
znaczne wachanie opóźnienia czasu.

Teraz wartość OC wynosi 238, a zegar spieszy się o jakąś sekundę na
każde dziesięć minut. Jest to najlepszy wynik, jaki udało mi się uzyskać
do tej pory. Różni się jednak wyraźnie od tego, co pokazywał kalkulator.

Nie mam pojęcia co jeszcze mógłbym pomieszać w ustawieniach timera. Tryb
CTC ustawiony, preskaler prawidłowy, zmiana OC jak widać ma wpływ na
pracę układu...

No i jak się okazuje - synchronizacja NTP także wprowadza jakiś błąd. Są
to dwie niezależne sprawy.

Andrzej W.
Guest

Thu Nov 13, 2014 11:45 am   



W dniu 2014-11-13 o 10:03, Atlantis pisze:
Quote:
Bo jej deklaracja wygląda następująco:

const char ntpreqhdr[] PROGMEM ={0xe3,0,4,0xfa,0,1,0,0,0,1};

Naprawdę tak trudno zerknąć do RFC4330?
Informacja o czasie nadania pakietu jest potrzebna do korekcji czasu
przelotu pakietów UDP. Jeśli serwer NTP masz blisko a czas liczysz w
sekundach to nie jest potrzebna taka korekta (w Twoim kodzie jej nie
liczysz).

0xE3 - LI=3, VN=4, Mode=3
LI jest polem serwera, klient go nie ustawia, ale to nie ma wpływu.
VN - ok
Mode - ok
0 - Stratum = 0
4 - Poll = 4 - to ustawia tylko serwer
0xFA - Precision = 0xFA - to ustawia tylko serwer

Jakieś to dla mnie dziwne.
U mnie pakiet z zapytaniem wygląda tak (wartość, długość):

/* Client
-- 0
LI = 0, 2b
VN = 4, 3b
MODE = 3,3b
-- 1
Stratum = 0, 8b
-- 2
Poll = 0, 8b
-- 3
Precision = 0, 8b
-- 4-7
Root Delay = 0, 32b
-- 8-11
Root Dispersion = 0, 32b
-- 12-15
Reference Identifier = 0, 32b
-- 16-23
Reference Timestamp = 0, 64b
-- 24-31
Originate Timestamp = 0, 64b
-- 32-39
Receive Timestamp = 0, 64b
-- 40-43
Transmit Timestamp = Seconds, 32b
-- 44-47
Transmit Timestamp = Seconds Fraction, 32b
*/

W odpowiedzi od serwera w polu "Originate Timestamp" powinieneś mieć to
co wysłałeś w "Transmit Timestamp".
Można by też lekceważyć wszystkie odpowiedzi z LI=3.
A jak chcesz być poprawny to powinieneś też sprawdzać czy pole Stratum
nie jest równe zero i podejmować odpowiednią akcję.


--
AWa.

Atlantis
Guest

Thu Nov 13, 2014 1:35 pm   



W dniu 2014-11-13 11:45, Andrzej W. pisze:

Quote:
W odpowiedzi od serwera w polu "Originate Timestamp" powinieneś mieć to
co wysłałeś w "Transmit Timestamp".
Można by też lekceważyć wszystkie odpowiedzi z LI=3.
A jak chcesz być poprawny to powinieneś też sprawdzać czy pole Stratum
nie jest równe zero i podejmować odpowiednią akcję.

Hmm... Czy w takim razie ta mocno uproszczona funkcja wysyłÍająca
request może być odpowiedzialna za zachowanie mojego programu? A może
jednak coś jest nie tak z funkcją odbiorczą? Może autor popełnił błąd i
zaprogramował odczytywanie pól z niewłaściwym timestampem?
Jaka pomyłka mogłaby skutkować czasem opóźnionym o kilka-kilkanaście
sekund po aktualizacji, no chyba, że serwer "zaleje się" requestami?

J.F.
Guest

Thu Nov 13, 2014 1:55 pm   



Użytkownik "Andrzej W." napisał w wiadomości
W dniu 2014-11-12 o 23:14, J.F. pisze:
Quote:
A propos NTP - czy ktos analizowal jak to dziala i rozumie ?
Bo nie rozumiem jak on sobie radzi z laczami niesymetrycznymi, gdy
np
pakiet w jedna strone idzie 0.1s, a w druga 2.1s ..
Z tego co jest w RFC4330:
Timestamp Name ID When Generated
------------------------------------------------------------
Originate Timestamp T1 time request sent by client
Receive Timestamp T2 time request received by server
Transmit Timestamp T3 time reply sent by server
Destination Timestamp T4 time reply received by client

The roundtrip delay d and system clock offset t are defined as:
d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2.
Jak dla mnie wzór na t tak pięknie się skraca, że nie ma znaczenia
czy opóźnienie jest symetryczne czy nie.

No to policzmy. Zalozmy ze
10 T1
112 T2
114 T3
16 T4

d=4, t=100 OK.

a teraz zalozmy ze pakiet w jedna strone leci 3s, a wraca 1s. Bedzie
wiec

10 T1
113 T2
115 T3
16 T4

d=4, t=101
Offset inny niz za pierwszym razem.

Ale ... zaczynam podejrzewac ze to sam Einstein mi gwarantuje
niemoznosc poprawnego wyniku.
W koncu moge synchronizowac czas miedzy dwiema rakietami lecącymi w te
samą strone z tymi samymi predkosciami.
Róznica czasów przelotu zalezy od predkosci, a predkosc od
obserwatora. Zas niezaleznie od predkosci obserwatora wynik musi wyjsc
ten sam :-)

J.

Andrzej W.
Guest

Thu Nov 13, 2014 2:00 pm   



W dniu 2014-11-13 o 13:35, Atlantis pisze:
Quote:
W dniu 2014-11-13 11:45, Andrzej W. pisze:

W odpowiedzi od serwera w polu "Originate Timestamp" powinieneś mieć to
co wysłałeś w "Transmit Timestamp".
Można by też lekceważyć wszystkie odpowiedzi z LI=3.
A jak chcesz być poprawny to powinieneś też sprawdzać czy pole Stratum
nie jest równe zero i podejmować odpowiednią akcję.

Hmm... Czy w takim razie ta mocno uproszczona funkcja wysyłÍająca
request może być odpowiedzialna za zachowanie mojego programu? A może
jednak coś jest nie tak z funkcją odbiorczą? Może autor popełnił błąd i
zaprogramował odczytywanie pól z niewłaściwym timestampem?
Jaka pomyłka mogłaby skutkować czasem opóźnionym o kilka-kilkanaście
sekund po aktualizacji, no chyba, że serwer "zaleje się" requestami?



Masz możliwość debugowania?
A może choć jesteś w stanie wysłać coś na port szeregowy?
Zobacz co przychodzi w odpowiedzi z serwera i tyle. Bez żadnej obróbki,
wyślij po prostu te cztery bajty i zobacz co tam jest.

--
AWa.

Atlantis
Guest

Thu Nov 13, 2014 6:17 pm   



W dniu 2014-11-13 14:00, Andrzej W. pisze:

Quote:
Masz możliwość debugowania?
A może choć jesteś w stanie wysłać coś na port szeregowy?

Niestety w tej chwili nie mam takiej możliwości. W projekcie nie
wyprowadziłem UART-a na goldpiny, ponieważ podstawową część programu
miałem już przetestowaną na płytce uruchomieniowej. Wtedy nie myślałem
nawet o dodawaniu do tego projektu dodatkowych funkcji, jak RTC i klient
NTP.

W każdym razie przyjrzałem się bliżej stosowi. Wygląda na to, że
początek pakietu danych odpowiada elementowi 0x2A bufora. Wychodzi więc
na to, że odczytywane w kodzie komórki 0x52..0x55 faktycznie odpowiadają
bajtom 40..43 pakietu UDP. Więc faktycznie jest to część sekundowa
transmit timestamp. Operacja składania ich w jedną zmienną uint32_t
także nie wzbudza moich zastrzeżeń. Tak więc opóźnienie z którym teraz
się zmagam raczej nie pochodzi z tej części programu...

Pewnie nieco rozbuduję procedurę odbiorczą. Przede wszystkim warto
byłoby sprawdzać, czy pakiet faktycznie został przysłany przez nasz
serwer NTP. Poza tym chyba wprowadzę obsługę originate timestamp.

Tylko czy któraś z tych kwestii może powodować takie opóźnienie przy
synchronizacji? Jakoś też nie mogę tutaj doszukać się możliwego
mechanizmu...

Atlantis
Guest

Thu Nov 13, 2014 10:16 pm   



Znalazłem przyczynę. Okazało się, że w pętli głównej zabrakło jednej z
kilku instrukcji warunkowych, które sprawdzają efekt działania funkcji
czytającej dane z ENC28J60 oraz parsujących nagłówki. Skutek tego był
taki, że w pewnych okolicznościach program wykonywał część programu,
której wykonać nie powinien - z bufora były czytane stare dane i po raz
kolejny uruchamiała się funkcja analizująca pakiet NTP. Timestamp sprzed
kilku-kilkunastu sekund powracał jak echo...

Goto page Previous  1, 2, 3, 4

elektroda NewsGroups Forum Index - Elektronika Polska - Niepokojące różnice czasowe między Atmegą a Raspberry Pi po synchronizacji NTP

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map