Oregelbunden hastighet på klocka

Elektronikrelaterade (på komponentnivå) frågor och funderingar.
Frisk
Inlägg: 92
Blev medlem: 9 maj 2007, 21:31:10
Ort: Södertälje
Kontakt:

Oregelbunden hastighet på klocka

Inlägg av Frisk »

Har som säkert en del av er sett byggt en klocka (mer info här)
Har nu kört klockan under några dygn, trodde först det var mitt reload-värde till timern som var fel, men verkar mer som ett hårdvarufel.

Klockan började först med att dra sig 30-40 minuter första 2-3 dagarna, sen plötsligt hade den tagit in den tiden på bara någon dag.
Just nu går den 5-10min för fort/dygn, utan att ändrat något med programmeringen.

Klockkristallen sitter så nära pinnarna på picen jag lyckade placera den, och klockkondensatorerna är ytmonterade, sitter mer eller mindre direkt på lödöarna för krisallen.

Vad är troligast är fel? Har jag brännt kondensatorerna vid lödningen, eller har kristallen fått sig en smäll, eller blivit överhettad?
Kan det vara programmeringsfel? men tycker i så fall det borde bli lika mycket fel varje dygn.
Användarvisningsbild
Icecap
Inlägg: 26662
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Hur styr ditt program tiden?

Är det med timer-interrupt?
Johan.o
EF Sponsor
Inlägg: 2388
Blev medlem: 18 juni 2003, 01:08:50
Ort: Jönköping

Inlägg av Johan.o »

Känner igen det, det är livsfarligt (enligt mig) att försöka få till en långtids-stabil klocka
i en mikrodator som kör annat än själva klockan. Själv kodade jag i assembler, och använde
en interrupt rutin som hade prioritet för att sköta tids-räkningen.
Kunde "dra sig" några sekunder per timmen, rätt slumpmässigt.

Det bästa är att köpa eller bygga en liten separat RTC, med bra stabil kristall. Endast då kan man verkligen få det riktigt bra och pålitligt.
Frisk
Inlägg: 92
Blev medlem: 9 maj 2007, 21:31:10
Ort: Södertälje
Kontakt:

Inlägg av Frisk »

Programmet är skrivet i C,vilket jag antar är en dålig början. kör räkningen via timer-interruppt.
just nu gör jag inte mycket mer än sköter klockan med processorn,men tänkte även lägga in I2C,blir kanske ännu värre då.. Har även planer på lampdimmer,i annan processor,kanske bättre att bygga tiden nollgenomgångarna? eftersom allt kommer vara ihopkopplat via I2C kommer detta förhoppningsvis funka ganska smärtfritt.
Användarvisningsbild
Icecap
Inlägg: 26662
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Vad har C med problemet att göra?

HUR kör du timer-interrupten? Lägger du till ett offset på timervärdet? Kanske du ska testa att rensa ut lite i programmet och posta det, det räcker med timer -ISR + initialiseringen av timern.

Jag har programmerat klockor som går kristall-stabilt utan problem via en timer-interrupt så den biten är inget problem.
Frisk
Inlägg: 92
Blev medlem: 9 maj 2007, 21:31:10
Ort: Södertälje
Kontakt:

Inlägg av Frisk »

Tänkte mer att om man skrev i Assembler så vet man precis vad som händer.

Precis, lägger till ett preload-värde på timern, och räknar upp sekunderna med ett.
Är inte speciellt mycket kod så slänger med hela, hoppas den är hyffsat överskodlig.

Kod: Markera allt

#include <pic18.h>
static int sec = 0, min =0, h = 0;
void main(void){
	INTCON  = 0b11000000;
	INTCON2 = 0b11110000;
	INTCON3 = 0b00000000;
	PIE1    = 0b00000001;
	IPR1	= 0b00000001;
	T1CON	= 0b10001111;
	TRISA	= 0b11000000;
	TRISB	= 0b11000000;
	TRISC	= 0b00000011;	
	TRISD 	= 0b11000000;
	TRISE	= 0b00000000;
	PORTC = 0;//sätter "jord" på MUXen för katoderna, är där för att kunna reglera ljusstyrka med PWM.

	while(1){
		if (sec == 60){
			min++;
			sec=0;
		}
		
		if (min == 60){
			h++;
			min = 0;
		}
		
		if (h == 24){
			h = 0;
		}
		PORTA = sec;
		PORTB = (min %8) <<3;
		PORTE = (min/8);
		PORTD = ((h%12)*5)+(min/12); //räknar om för 5 lägen/timme
	}
}

void interrupt NewSec(void){
	TMR1IF = 0;          	
	sec++;
	TMR1L  = 0b00000001;	
	TMR1H  = 0b01111010;
}
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Klockkristallen sitter så nära pinnarna på picen jag lyckade placera den,

Är det frågan om en Timer1-osc kristall ?

Hur har du räknat ut de nya TIMERL/TIMERH värderna ?
Normalt gör man ADD till TIMER'n för att slippa räkna på
overhead.

Bäst är att låta timern vara freerunning hela tiden (00-FF eller 0000-FFFF)
så slipper man effekterna vid omladdning av timern. Det kan bli tätare
interrupt, men det är bara att räkna til det blir en sekund (eller vilken
tidbas man nu vill ha). Utan omladdning så blir det mycket enklare att få
timern att gå p åett förväntat sätt.
Frisk
Inlägg: 92
Blev medlem: 9 maj 2007, 21:31:10
Ort: Södertälje
Kontakt:

Inlägg av Frisk »

Det stämmer bra, Timer1-osc.
Jag räknade först på värderna, och har därefter justerat. Enligt beräkningarna skulle preload vara 8000 hex.
Kör jag timern som 16-bitars och freerunning kommer jag få 2s interruppt, men kanske kan vara idé att istället köra den som 8-bitars...
Blir ju en del extrainterrupt, men då inte klockprocessorn har mycket mer i uppgift än att sköta just klockan spelar det ingen större roll.
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Om preload är 8000h borde du kunna OR:a TMR1H med 80h vid interruptet bara. Eller så använder du Comparemodulen med 32768 som period.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Som sagt, normalmetoden är att *lägga till* värdet, då tas det automatiskt
hänsyn till att timern ha hunnit köra en liten bit sedan interruptet.
Men som sagt, enklast är att låta den bara snurra runt med ett lämpligt
intervall och bara räkna antalet varv.
Användarvisningsbild
Icecap
Inlägg: 26662
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Jupp, felet är hittat:
TMR1L = 0b00000001;
TMR1H = 0b01111010;

Big no no!!!

Håller i övrigt med de förra talare.
Frisk
Inlägg: 92
Blev medlem: 9 maj 2007, 21:31:10
Ort: Södertälje
Kontakt:

Inlägg av Frisk »

Icecap, vad är felet? att jag sätter fasta värden, som övriga påpekat? Ska istället addera lämpligt tal?
Får testa addera ett värde då, se om den går tillräckligt exakt då, fungerar inte får jag testa sodjans förslag med att bara låta timern rulla.

Tack för hjälp och förklaringar om mina fel!
Användarvisningsbild
Icecap
Inlägg: 26662
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Det är generellt fel att lägga in fasta tal eller addera, det rätta är att hårdvaran ställs en gång och sedan använder man interrupten till att räkna på. Därför finns det kristaller med "knasiga" värden, för att timrar och deras delningar ska passa med 1/10/100Hz.

Det framgår inte vilken PIC du använder annat än att det troligt blir en PIC18.

Jag har just avslutat ett projekt som helt var timerberoende, jag använde Timer2 på en PIC16F628A och kunde ställa in den till att ge en 100Hz (100,16...) och det räckte för mitt behov, den kan man ställa prescaler, postscaler och delningsgrad på och få nära nog vilken frekvens man vill ha på interrupten.

Om du tar t.ex. ett 3,6864MHz kan du lätt få ut ett "binärt" värde på 100,000Hz, och då är det bara att räkna till 0-99 och vid 100 slå över räknaren till noll och addera 1 till sekunderna.
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Skriv bara:

Kod: Markera allt

void interrupt NewSec(void){
	TMR1IF = 0;          	
	sec++;
	TMR1H  |= 0x80;
}
istället. Är väl den elegantaste lösningen.
Frisk
Inlägg: 92
Blev medlem: 9 maj 2007, 21:31:10
Ort: Södertälje
Kontakt:

Inlägg av Frisk »

Jag använder en klockkristall, 32,758kHz, tyvärr skapar ju denna bara interrupt varannan sekund, därav preloadvärdet.
Kan ju klart underlätta om jag säger vad det är för saker jag kör på ja... är en PIC18F4550.
Får testa bearings förslag, hoppas på att det funkar.
Skriv svar