GPS disiplined counter algorithme gezocht

Geachte Forum leden,

Ik gebruik een GPS NEO 6 met 1 PPS uitgang naar
een PIC 16F690. Alles draait goed, maar mijn oplossing kan
zonder uitmiddelen maar een resolutie aan van 4Hz op de 20MHz.
Ik ben gestart met uitmiddelen, maar wil minimaal 0,1 Hz halen
Is er een "slim" algorithme ?
Kun je een oplossing zodanig opschrijven dat ik er met BASIC
mee overweg kan.

STUK VERKLARING EN HUIDIGE CODE HIERONDER

pic basic code:


'; Wacht op extern interrupt van de GPS  1 x per seconde
'; start Timer1
'; Laat TIMER 1 vrijlopen
'; Na 76 keer TIMER 1 doorlopen te hebben
'; Staat er een getal in CCP1 gelijk aan TIMER 1
'; Wacht tot interrupt.
'; lees CCP1 uit , moet ongeveer 19264 zijn
'; BIJREGELING
'; Gebruik de timer 1 als PWM om de temperatuur te regelen.
'; Vergelijk Temp met timer1, als gelijk of groter is
'; dan PORTA.2 wordt hoog en daarmee het crystal 
'; verwarmt.
'; Als  CCP1 vroeger valt dan 19264 dan incr Temp
'; Gelijk dan geen verandering
'; Later dan decr Temp



CCPOLD = 19264
DelayMS 1000
Print At 1,1, "GPS Accurate"
PIR1    = %00000000
;Cls
'; start counting
Clear
While  PIR1.2 = 0               ; wacht op eerste rising edge van CCP
Wend 
TIMER1  = 0                     ; Zet Timer1 op 0
PIR1.2 = 0                      ; reset flag 
PIR1.0 = 0
CCPNEW = 0 
WACHT:                          ; Wacht loop
While  PIR1.2 = 0               ; wacht op rising edge van CCP
Wend                            ; CCPNEW bevat TIMER 1 waarde

Xerror  = (CCPNEW - CCPOLD - 19264) ;    krijg error vergeleken met "perfect" xtal
PIR1.2 = 0;
CCPOLD = CCPNEW;                   ; neem nieuwe waarde over
                                   ; Xerror  bevat  afwijking t.o.v ideaal met een resolutie van 200nS
                                   ;  Ideaal is 20.00000MHz
  Inc Index                        ; Uitmiddelen van 8 seconden  geeft resolutie van 0.5 Hz op 20 MHz
  If Index = 9 Then Index = 1
  Rot[Index] = Xerror
  Rys = Rot[1] + Rot[2] 
  Rys = Rys + Rot[3] + Rot[4]  
  Rys = Rys + Rot[5] + Rot[6]
  Rys = Rys + Rot[7] + Rot[8]      ; Rys = 4x zo groot om van 5 Mhz naar 20Mhz te gaan


Print  At 1,1 ,Dec Xerror,  " HZ ", Dec Rys, " ", Dec Index 
Print  At 2,1  , Dec 20000000+ Rys/2 ," Hz", " v66      "

[Bericht gewijzigd door GJ_ op donderdag 20 februari 2020 16:57:35 (1%)

Guus@Sint-Michielsgestel
Arco

Special Member

Je kunt toch een IOC interrupt gebruiken om de timer te stoppen? (als die counters bijhoudt mag het zelfs uren of dagen duren... ;) )
Of een wat nieuwere pic overwegen. De 16F1769 bijv. heeft een timer met pre/postscaler van 16x/128x...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Hoi Arco, de truc zit hem nou juist in het laten doorlopen van TIMER 1.
Ik meet nu 20.000.503 Hz, mijn ongecalibreerde counter geeft 20.000.499 Hz
aan, dus daar heb ik wel vertrouwen in.
Ik zoek juist naar een algorithme om 40 seconden te integreren,
zodat ik .1Hz resolutie krijg.
Mijn huidige algorithme kan ik wel uitbreiden van 8 sec naar 40 sec, maar is erg lomp. Ik zou zeggen dat er toch veel slimmere oplossingen zijn.

Guus@Sint-Michielsgestel
Arco

Special Member

't Is me niet duidelijk wat je wilt bereiken. Wil je daar je kristal mee calibreren?

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Hoi Arco,
Hiermee meet ik de frequentie van het crystal, mijn tweede insteek is om een crystal oven te bouwen en de temperatuur zo te regelen dat er exact 20MHz uitkomt.

Guus@Sint-Michielsgestel

Nooit met PIC basic gewerkt, maar als ik het goed begrijp gebruik je de GPS als gate (tijd=1s) en runt timer1 met als input het 20MHz kristal met een prescaler van 4?

Dan heb je (in 1s) 20M/4 = 5M pulsen = 76 * 2**16 + 19264 (timer1 is 16 bit)

Vandaar ook de resolutie van 4Hz.

Ja, gatetijd langer maken (bv 10 GPS pulsen tellen terwijl timer 1 blijft lopen) of evt een ander PIC/timer die geen prescaler nodig heeft?

exofx.

Ja dat is mijn vraag, ik wil 40 sec meten en zo een resolutie van .1Hz
krijgen, mijn originele vraag is dus om een algorithme dat een soort lopende gemiddelde afgeeft. Ik denk dat ik meer in de DSP hoek moet zijn met deze vragen.

Guus@Sint-Michielsgestel

Doe een meting per seconde.
Opslaan in een array met 40 entries: Oudste weggooien en nieuwe toevoegen.
Dan gemiddelde berekenen van de array.

Dan krijg je elke seconde een nieuw lopend gemiddelde.

Als je in mijn code kijkt, dan zie je dat ik dat al voor 8 sec deed.
Met Proton Basic kan ik maar 3 variabelen optellen, dus het wordt erg omslachtig. Het is nogal "brute force " om dit naar 40 sec uit te breiden, maar wat als je naar 400 seconden wilt ? Vandaar mijn vraag naar een " algorithme "

Guus@Sint-Michielsgestel

Je kan ook een "FIR" filter gebruiken om lopende gemiddeldes te berekenen : Bij elke nieuwe meetwaarde bereken je :
Gemiddelde = 0.01*Meetwaarde + 0.99*Gemiddelde
Op deze manier heb je maar één variabele nodig om een "lopend" gemiddelde van de (ca) laatste 100 metingen te berekenen. Opgelet, dit is dan niet exact hetzelfde als een "echt" lopend gemiddelde ! De "oudste" metingen hebben dan relatief minder gewicht. In excell kan je dit mooi vergelijken.

Als je enerzijds die array bijhoudt, maar ook het totaal. Bij iedere meting gooi je de oudste weg door die van het totaal af te trekken en voeg je de nieuwste toe.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Ik heb geen verstand van pic basic, maar dat kan toch met een for loopje?

Iets als:

code:


  NrElements = 40  ; of 400 als je genoeg geheugen hebt..

  ... 

  Inc Index   
  If Index > NrElements Then Index = 1
  Rot[Index] = Xerror

  Total = 0
  For i = 1 to NrElements
    Total = Total + Rot[i]
  Next

  Average = Total / NrElements
    

Maar de suggestie van rew is ook wel erg leuk:

code:



[code]
  NrElements = 40  ; of 400 als je genoeg geheugen hebt..

  ... 

  Inc Index   
  If Index > NrElements Then Index = 1

  Total = Total - Rot[Index]
  Total = Total + Xerror  
  Rot[Index] = Xerror


  Average = Total / NrElements
    

Maar ik heb geen verstand van basic. Dus het kan best dat je de array Rot nog moet declareren of zo.

Bedankt deKees,

hier kan ik verder mee.

Guus@Sint-Michielsgestel

Misschien vind je hier wat inspiratie. (Lars DIY GPSDO with Arduino and 1ns resolution TIC)

Mijn thuis is waar mijn Weller staat

@ Waters
Kijk eens op de site van Bertrand Zauhar, VE2ZAZ. Hij heeft enige jaren geleden een GPSDSO gebouwd met een PIC, en e.e.a. ook goed gedocumenteerd. Ik heb zijn PIC assembly code ooit omgeschreven naar Bascom voor ATMEGA met de bedoeling beter te begrijpen hoe het in elkaar stak.

Wat in ieder geval speelt is de korte termijn variatie in je 1PPS uit de gps. Die is niet bijster nauwkeurig en zwabbert (typical +/- 1 µs?). Je zult dus moeten middelen, maar de vraag is hoe lang? Denk aan een uur of zo, uitgaande van een stabiele oven-oscillator. Ook moet je in de gaten hebben als je een seconde-pulsje gemist hebt. Je moet dan free-wheelen en niet corrigeren. Als je telling van het aantal pulsen van je oscillator teveel afwijkt van wat je verwacht moet je je ook afvragen waar de fout zit. VE2ZAZ heeft dat allemaal netjes opgelost.

Opvoeren van resolutie? ZAZ laat de timer oscillator-periden tellen gedurende 16 PPS seconden, waarbij het aantal bits van de timer, die eigenlijk als counter bezig is, niet zo belangrijk is. De counter zal een aantal keer vollopen en weer op nul beginnen en de laatste keer blijft er een rest over (zoals de 19264 in de post van exofx). Je weet wat de rest had moeten zijn, dus die waarde trek je af van de gemeten rest, en je houdt het verschil over, een maat voor de fout dus. Als alles OK is is dat verschil nul. Zoniet, dan moet je voorzichtig en met overleg gaan bijregelen...
Na 16 seconden meten van een 20 MHz signaal had je 320 miljoen pulsen moeten zien voorbijkomen. Je hebt er misschien 123 teveel geteld.. dan is je oscillator te snel geweest, en moet je langzamer worden. Je verschil is op 1 puls nauwkeurig, dus je meet-resolutie (onzekerheid) is 1/320,000,000 (~ 3 ppb).
Met een /4 prescaler wordt het dan 1/80 ppm. Anders gezegd, op 20 Mhz een fout van 1/80 ppm = 20/80 Hz is 1/4 Hz (bij 16 sec. meettijd). Blijkbaar meet jij maar 1 seconde en kom je op 4 Hz.

Let wel dat je gps PPS zwabbert, dus bij een klein verschil moet je misschien wel even niks veranderen. Optellen van de verschillen (integreren dus) biedt uitkomst: pas als de som van de verschillen een bepaalde waarde over- of onderschrijdt is er pas echt iets aan de hand en moet je bij gaan regelen (in kleine stapjes). Als een enkel tel-verschil veel groter is dan verwacht moet je die meting misschien maar niet geloven. Je gaat er immers van uit dat je een fatsoenlijke oscillator gebruikt die niet zomaar 'zwabbert' tussen een paar metingen, maar continue iets te snel of te langzaam is. 'Eindeloos' blijven optellen van de (als 'echt' geaccepteerde) verschillen is dus hetzelfde al wat jij bedoeld met het integreren over een langere periode. Zolang je totaal ergens rond de nul zit ben je OK. Loopt het op, dan pas bijsturen, eventueel ietsepietsie proportioneel. Let wel op de thermische traagheid van de oven.

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.

Verwijderd, bericht had ik al gepost.

[Bericht gewijzigd door soldeersmurf op vrijdag 28 februari 2020 02:54:26 (98%)

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.

Hoi Soldeersmurf,

Ik ben al een tijdje bezig met BASCOM voor atmega,
zou ik jouw bascom code kunnen krijgen, het zou me meer inzicht
geven in de voetklemmen en valstrikken die er nog op mijn weg
liggen, zoals je die al beschrijft.
Bij voorbaat dank.

P.S. Ik meet nu met een lopende gemiddelde over 40 Seconden

Guus@Sint-Michielsgestel

Even mijn Nederlands verbeteren,

Het moet zijn: voetangels en klemmen
voor onze Vlaamse lezers : wolfijzers en schietgeweren

Guus@Sint-Michielsgestel

@ waters

Ik zal vanavond even de software voor je opsnorren (tenminste als ik er aan denk).

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.

@waters,

Ik denk niet dat g@st.m in je profielpagina gaat werken als e-mailadres (of misschien toch wel?).
Ik heb wat software gevonden. Misschien niet de laatste versie, maar goed genoeg om een beeld va de werking te krijgen. Ik kan nog wel verder zoeken bij interesse. Stuur me een PM, dan drop ik wel een bascommetje in je mailbox.

Niet alles wat op internet staat is waar... Dat geldt ook voor CO.