AVR ASM - LÅNG fördröjning på bästa sätt?? (~3 månade

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
laban12
Inlägg: 1199
Blev medlem: 17 april 2008, 16:01:56
Ort: Stockholm

AVR ASM - LÅNG fördröjning på bästa sätt?? (~3 månade

Inlägg av laban12 »

Min UPS vill att man laddar ur batterierna helt var 3:e månad för bästa livslängd. Det är dumt! Anledningen till att jag har en UPS är ju att jag INTE vill att maskinerna bakom ska gå ner - så hur ska man göra då? Rycka kontakten, sitta och vänta tills den nääästan stänger av och sedan trycka i kontakten igen? Var 3:e månad?

Nope!

Jag tänkte mig två parallellkopplade batterier och sedan en krets som tar det ena batteriet offline, laddar ur det, kopplar det online, kopplar nästa batteri offline... ja ni förstår.

Busenkel krets att göra, jag tänkte göra det med en AVR för att hålla koll på dels hur snabbt batteriet laddar ur (för att få en ide om hur det mår) och sedan se till att den inte djupurladdar.

Det jag funderar över är hur jag bäst får till fördröjningen som väntar tre månader mellan varje cykel...

1) någon extern krets med en stor räknare som klockas långsamt?
2) någon intern räknare?
3) en RTC som man läser av och jämför?

... det ska vara så enkelt som möjligt och tiden är inte EXAKT viktig, 3 månader +- en vecka är ju helt okej.

Tankar?
Nerre
Inlägg: 27188
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Inlägg av Nerre »

Långsamma oscillatorer är svåra att trimma in.

Jag skulle nog lösa det med en kombination. Strömförbrukningen är väl inte kritisk?

Då använder man en intern räknare med interrupt för att få lagom snabba "tick", och sen räknar man helt enkelt de ticken i mjukvara.

Helst ska man kanske spara undan t.ex. antalet dagar i EEPROM så om det blir strömavbrott så kommer det diffa max en dag. Fast å andra sidan, om det blir strömavbrott så kommer väl UPSen att ha jobbat och då kanske man VILL börja om från början?
laban12
Inlägg: 1199
Blev medlem: 17 april 2008, 16:01:56
Ort: Stockholm

Inlägg av laban12 »

Intrimningen bör väl inte bli något problem när jag tillåter en sån stor felmarginal? eller... ? Det klart, det är rätt så lång tid så ett litet fel blir lätt stort.

Din andra tanke är intressant, VILL man att den ska börja om från noll vid ett strömavbrott? Troligtvis, om det har varit hyffsat långt och inte bara en spik. Det skulle alltså behöva detekteras. I version 2. :)
Version 1 får börja om från noll vid varje Power-On, enligt KISS-principen!
MiSTer
Inlägg: 725
Blev medlem: 26 juli 2007, 03:55:18
Ort: Skene
Kontakt:

Inlägg av MiSTer »

Ett 1-wire RTC chip, måste väl vara enklast?
Användarvisningsbild
psynoise
EF Sponsor
Inlägg: 7226
Blev medlem: 26 juni 2003, 19:23:36
Ort: Landvetter

Inlägg av psynoise »

Har inte riktigt koll på hur stabil en kristal är och vilka variabler som temperatur osv spelar roll. Men IQXO-350C har en stabillitet på +-100 ppm enligt ELFA. Dvs 3 månader ger en diff på +-3*30*24*60*0,0001 min ≈ +-13 min.

EDIT: Rättade till länken.
Nerre
Inlägg: 27188
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Inlägg av Nerre »

laban12 skrev:Intrimningen bör väl inte bli något problem när jag tillåter en sån stor felmarginal? eller... ? Det klart, det är rätt så lång tid så ett litet fel blir lätt stort.
Jag menade "svårare". Och då tänkte jag alltså periodtider på en minut eller mer.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Inlägg av jesse »

Det är absolut inga problem att få en AVR att räkna långa tider.... Man kan räkna årtusenden om man vill...

1) sätt igång en timer som ger ett interrupt när den räknat till 256 (eller 0). Dividera ner timerns klocka så att den slår om t.ex 100 ggr/sekund.

2) vid interrupt så räknar du upp ett register (antingen har du ett register bara för detta eller så lagrar du det i SRAM). När du kommit till 100 (om det nu är 100 interrupt per sekund) så nollställer du det registret och går vidare till register två och tre som t.ex räknar upp sekunderna som går. Antingen delar du upp det i 60 och 60 (så ena registret representerar sekunder och nästa minuter) När du är uppe i 60 så nollställer du precis som du gjorde med det första registret, eller så räknar du direkt till 3600 (så får du en timme).

När du då kommit upp i 60 minuter så sätter du igång timregistret 0-23. Vid 24 nollställer du och ökar dygnsregistret med ett. När du kommit upp i 90 så har 90 dagar gått och du kan nollställa det och allt börjar om på nytt.

Om du vill slippa programmera en massa kan du låta första registret räkna till 200 istället och alltså slå om varannan sekund. då får du ett dygn = 86400 sekunder eller 43200 "tvåsekunder". eftersom 43200 är mindre än 65536 så kan du använda två bytes. Sen ett separat byte för dygn. (eller två bytes om du vill räkna fler än 256 dygn)


3) ska du hålla reda på flera separata (osynlkade) tider kan du göra på olika sätt. parallellt med att di räknar sekunder , minuter osv.. på "tremånaderstimern" så kan du samtidigt (i samma interruptrutin) börja räkna på "en-veckas-timern" och "30minuterstimern" osv...

vill du inte hantera allt detta i en interruptrutin kan du istället låta interruptrutinen sätta en flagga vid varje hel sekund. Då kan du i huvudprogrammet läsa av flaggan (oftare än en gång i sekunden då) och när du får en etta så går du till en procedur där du börjar räkna upp dina timers. Har du massa tider att hålla reda på kan det vara en bra idé att automatsera det hela, så du slipper att koda varje timer separat. då skickar du bara med ett index till en adress i EPROM eller Flash-adress som innehåller lite parametrer för timern, t.ex. längd (tid) , adress i SRAM där din timer räknar upp, adress till den rutin som ska utföras när timern slår om etc...

Hittade en gammal kodsnutt ... här tar jag bara med interruptdelen...

Kod: Markera allt

; ---- TIMER0 overflow interrupt handler----
TIM0_OVF:   ; Timer0 Overflow
	interrupt                     ; (spara SREG och tmp)
	lds tmp, timerl             ; läs in värde från SRAM adress timerl
	subi tmp,1                   ; minska med ett
	sts timerl,tmp               ; spara i SRAM
	brcc owf0end             ; har timerl nått maxvärde? nej = avsluta.
	lds tmp, timerh            ; läs in värde från SRAM adress timerh
	subi tmp,1                   ; minska med ett
	sts timerh,tmp               ; spara i SRAM
	brcc owf0end              ; har timerl nått maxvärde? nej = avsluta.
               ; TIMERN HAR UPPNÅTT TIDEN
	       ;timer nollad > sätt flagga   
	sbr flagga,1<<timer
OWF0END: interrupt_end ; (poppa SREG och tmp samt gör reti)
sedan kollar du "flagga" (=namnet på ett register som bara används som flagga) i huvudprogrammet...

nåt i stil med (obs! inget bra exempel men det jag råkade hitta)... Laddar timerl och timerh med ett värde som sedan räknar ner till noll innan man når "ret":

Kod: Markera allt

wait: cli
	cbr flagga, 1<<timer
	sts timerl,tmp 
    sts timerh,tmp2
	sei
waitloop: sleep          ;sleep kan användas om man inte vill göra något i väntan på interrupt
	SBRS flagga,timer ; skip if bit in register is set
	rjmp waitloop
	ret
Senast redigerad av jesse 23 december 2008, 17:57:37, redigerad totalt 1 gång.
Användarvisningsbild
JonasJ
Inlägg: 653
Blev medlem: 11 september 2007, 16:02:26
Ort: Kinna
Kontakt:

Inlägg av JonasJ »

Varför inte en RTC med en inbyggd larmfunktion? Då kan du låta processorn sova tills den får ett interrupt på en pinne. Borde vara det enklast men kanske inte det billigaste.

Edit: Fixade sär skrivning
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Inlägg av jesse »

en kodsnutt som räknar ner några register är väl ändå enklare än någon yttre komponent som i sin tur ska trimmas och joxas med för att få att fungera. Nej. Kör software!

3 månader = 90 dagar = 7776000 sekunder. log(7776000)/log(256) = 2.86 dvs du får plats att räkna sekunderna med endast tre bytes (eller mer exakt 23 bitar). Kan inte bil enkare!

Om du kör på 4 Mhz, interruptar 100 ggr/sek och interruptavsnittet ligger på genomsnitt 20 klockcykler och du sätter processorn på sleep så sover den 99.95% av tiden.

EDIT: ändrade ett räknefel :roll:
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Mitt förslag:

En 32,768 kHz klockkristall för 3,52 kr på ELFA som genererar interrupt var 8:e sekund. Räkna antalet interrupt tills det är dags...
Användarvisningsbild
JonasJ
Inlägg: 653
Blev medlem: 11 september 2007, 16:02:26
Ort: Kinna
Kontakt:

Inlägg av JonasJ »

jesse skrev:en kodsnutt som räknar ner några register är väl ändå enklare än någon yttre komponent som i sin tur ska trimmas och joxas med för att få att fungera. Nej. Kör software!

[snip]

EDIT: ändrade ett räknefel :roll:
Vad som är enklast är upp till den som implementerar. Mitt var bara ett förslag. Tanken med en yttre komponent var att du slipper riskera att räkna fel på interrupter och klockfrekvenser :) Det kanske inte är så kul att upptäcka efter 3 månader när UPS:en stängs av. Hade jag implementerad detta själv hade jag förstås valt något liknande ditt sätt alt. thepirateboy för att minimera antal komponenter och hålla nere kostnader.
limpan4all
Inlägg: 8444
Blev medlem: 15 april 2006, 18:57:29
Ort: Typ Nyköping

Inlägg av limpan4all »

En väldigt exakt tidsreferens som kan användas som backup eller normal till en RTC är faktiskt elnätet. Jag har för mig att det är exakt 50Hz sett över något dygn.
Användarvisningsbild
psynoise
EF Sponsor
Inlägg: 7226
Blev medlem: 26 juni 2003, 19:23:36
Ort: Landvetter

Inlägg av psynoise »

Har hört att nätfrekvensen sjunker med ökad belastning, t.ex vid kalla vinterdagar. Hur stor andel det har att göra med vet jag dock inte, borde dock inte vara allt för svårt att hitta statistik om tror jag.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Inlägg av blueint »

Skulle absolut inte använda nätfrekvensen som referens.
Med 100 ppm nogrannhet är nogrannheten på 3 månader 13 minuter, och med 2% är nogrannheten 1.8 dagar. Och eftersom det gäller urladdning av kemiska batterier torde det inte spela så stor roll ..?

Så en lösning där SPDT-relä för varje batteripack växlar mellan inkoppling till UPS eller resistans kanske vore något?

Ett problem kan vara när man ska växla mellan batterierna, om UPSen inte klarar sig utan batteri i några millisekunder.
Användarvisningsbild
mrfrenzy
Co Admin
Inlägg: 15459
Blev medlem: 16 april 2006, 17:04:10

Inlägg av mrfrenzy »

Har du NiCd-batterier i din ups? Har aldrig hört talas om några blybatterier som mår bättre av urladdning, snarare försämras dom varje gång dom laddas ur. Jag skulle rekommendera att du tar reda på modellbeteckningen på batterierna och läser tillverkarens datablad.
Skriv svar