Oregelbunden hastighet på klocka
Oregelbunden hastighet på klocka
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.
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.
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.
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.
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.
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.
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.
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.
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.
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;
}
> 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.
Ä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.
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.
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.
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.
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.
Skriv bara:
istället. Är väl den elegantaste lösningen.
Kod: Markera allt
void interrupt NewSec(void){
TMR1IF = 0;
sec++;
TMR1H |= 0x80;
}