PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Softwareseitige UHR ?



EDatabaseError
29.06.2006, 10:07
Ist es möglich bspw. Über Timerinterrupt eine (auch ziemlich ungenaue) Uhr (mit Datum) in Bascom zu programmieren???
(Quarz 16 MHz)

Ich spiele jeden 2. Tag die Uhrzeit neu via RS in das Modul ein.

Mfg
Tobi

Kaiser-F
29.06.2006, 10:20
Hallo!

Jup, Das ist möglich... Nur wird das mit nem 16MHz Quarz schwierig.
Ich verwende zB ein 14,7456 MHz-Quarz.
das ist im binärsystem eine gerade Zal´l..
14745600 / 1024 = 14400.

Dann muss der Timer bis 143 Zählen und dann den Interrupt auslösen.
In diesem lasse ich dann diese Funktion ausführen:



// -=> Timer Uhr <=-
void TIMER_clock( void ){

TIMER_percent++;

if( TIMER_percent >= 100 ){
TIMER_percent = 0;
TIMER_second++;
}

if( TIMER_second >= 60 ){
TIMER_second = 0;
TIMER_minute++;
}

if( TIMER_minute >= 60 ){
TIMER_minute = 0;
TIMER_hour++;
}

if( TIMER_hour >= 24 ){
TIMER_hour = 0;
}
}

Ich programmiere zwar nicht in Basic, aber ich denke dieser kurze
C-Code ist durchaus zu verstehen. Wenn nicht, sag bescheid...

EDatabaseError
29.06.2006, 10:36
Also
16000000 / 1024 = 15625

leider kenn ich mich mit dem Basic nur so gut aus:
Variablen deklarieren, Pórts deklariern, if, for, while...

(Das Buch kommt erst noch :lol:)


Mfg
Tobi

Kaiser-F
29.06.2006, 10:45
nagut.. wenn du den 16bit Timer nimmst, dann kannst du ihn jetzt bis 15624 laufen lassen (immmer 1 weniger, weil er ja bei 0 beginnt).
kommt aber dann im sekundentakt.

Achja, und wenn du wirklich eine genaue zeit brauchst, dann würd ich am eingang für das zweite quarz ein Uhrenquarz einbauen.

Quarze, mit solch komischen werten wie 7,372800MHz sind im binärsystem eine gerade zahl. deshalb kommt auch bei mir 14400 raus. und mir stehen hundertstelsekunden zur verfügung.

Aber uhrenquarze sind wesentlich besser geeignet....
die haben auch 32768 Hz.

PS: Wenn du schon anfängst zu programmieren, würd ich gleich mit C anfangen...

EDatabaseError
29.06.2006, 10:55
Also mir reicht eine relativ ungenaue Urzeit +-5 Minuten würde ich sogar noch aushalten. Mein Chip ist ein ATmega128 auf einer fertigen Platine.

Zu PS: Mit Basic kenn ich mich halt schon ein bissel aus und C kann dann ja immer noch kommen. Ich mach ja das Atmel zeugs nicht Tag-täglich sondern nur bei speziellen Projekten. (Bin eigentlich für die PC Software Win 32 via Delphi zuständig ;-) )


Mfg
Tobi

EDatabaseError
29.06.2006, 16:38
Wenn ich mal kurz pushen darf ;-)

Ich benötige nur den Source der den Timer so initialisiert das er jede Sekunde einen Interrupt auslöst. Das was in dem Interrup passiert schreib ich selber.

Mfg
Tobi

uwegw
29.06.2006, 16:44
Im Wiki steht schon der passende Code dafür:
https://www.roboternetz.de/wissen/index.php/Bascom_und_Timer

EDatabaseError
29.06.2006, 16:50
Im Wiki steht schon der passende Code dafür:
https://www.roboternetz.de/wissen/index.php/Bascom_und_Timer

also ich hab jetzt mal folgendes


Config Timer1 = Timer, Prescale= 15624 ‘die 15624 müssen doch in den Prescaler oder?!?
Enable Timer1
On Timer1 AddSecond
Enable Interrupts

Do

Loop
End

AddSecond:
second = second + 1
Return

uwegw
29.06.2006, 16:58
Nee, der Prescaler kann nur ganze Vielfache von 2 annehmen. Er bestimmt, wie weit der Quarztakt runtergeteilt wird, bevor er den Timer hochzählt. Deine 15000nochwas müssen entweder in ein Compare-Register [dann könntest du aber z.B. niicht mehr alle PWM-Ports nutzen], oder du lädst damit bei jedem Überlauf das Zählregister neu. Datenblatt lesen empfohlen!

EDatabaseError
29.06.2006, 17:00
Ich greif noch mal auf diesen beitrag zurück den ich versteh nur Bahnhof:

nagut.. wenn du den 16bit Timer nimmst, dann kannst du ihn jetzt bis 15624 laufen lassen (immmer 1 weniger, weil er ja bei 0 beginnt).
kommt aber dann im sekundentakt.

Achja, und wenn du wirklich eine genaue zeit brauchst, dann würd ich am eingang für das zweite quarz ein Uhrenquarz einbauen.

Quarze, mit solch komischen werten wie 7,372800MHz sind im binärsystem eine gerade zahl. deshalb kommt auch bei mir 14400 raus. und mir stehen hundertstelsekunden zur verfügung.

Aber uhrenquarze sind wesentlich besser geeignet....
die haben auch 32768 Hz.

PS: Wenn du schon anfängst zu programmieren, würd ich gleich mit C anfangen...

franzl
29.06.2006, 17:06
hallo,
der prescale geht max. bis 1024 er teilt den quarztakt durch diese zahl und verwendet ihn dann für den timer.
du musst den timer auf voreinstellen.


on timer1 ontimer1 'interrupt-rputine für timer 1
config timer 1 = timer , prescale = 256 'Takt ist Quarz / 256
enable timer1
enable interrupts

do
loop

ontimer1:
timer1 = XXXXX 'dein voreingestellter wert
Sekunde = Sekunde + 1
return

mfg franzl

EDatabaseError
29.06.2006, 18:56
Gibt es kein Tutorial oder ein fertiges Projekt / eine Formel die mir sagt wie der Prescaler bei 16 MHz eingestellt sein muss das er jede Sekunde interruptet.

Mfg
Tobi

uwegw
29.06.2006, 18:59
Im Wiki steht schon der passende Code dafür:
https://www.roboternetz.de/wissen/index.php/Bascom_und_Timer
(auch mal den Artikel komplett lesen!)

Marco78
29.06.2006, 19:05
Auch auf der Gefahr in das dir der Link bekannt vorkommt ;) http://www.rowalt.de/mc/avr/avrboard/06/avrb06.htm
Nichtnur Artikel komplett lesen, sondern auch Links die man als Tipp bekommt!

Zum Tut für eine Sekunde bei 16MHz:
Im Donwloadbereich gibt es ein Programm, mit dem du die Timer für gänige Taktfrequenzen und alle möglichen Auslösezeiten berechnen lassen kannst.
Es nennt sich RNAVR. Es erzeugt gleich einen Bascomcode.

PS: Beim Mega128 kannst du auch ein Uhrenquarz anschliessen und hast damit eine vom Programm unabhänige und genauere Uhr. Damit wird dein Programm auch nicht immer durch den Timer unterbrochen. Evtl brauchst du ihn ja auch noch für was anderes?!

EDatabaseError
29.06.2006, 19:07
:oops: sry... danke

EDatabaseError
29.06.2006, 20:31
Ich hab jetzt noch ein kleines Prob bei der Erstellung des Zeitstrings:


Dim Tresult As String * 8
Dim Dresult As String * 8

Dim D1 As String * 2
Dim D2 As String * 2
Dim D3 As String * 2

If Second < 10 Then D1 = "0" + Hex(second) Else D1 = Hex(second)
If Minute < 10 Then D2 = "0" + Hex(minute) Else D2 = Hex(minute)
If Hour < 10 Then D3 = "0" + Hex(hour) Else D3 = Hex(hour)

Tresult = Hour + ":" + Minute + ":" + Second

Hex wandelt einen numerischen Wert in einen String (laut Hilfe)

Das funktioniert leider nicht richtig :-( was mache ich jetzt schon wieder falsch. Dazu sagt das RN-Wissen leider auch nichts.

Ich bekomme stadt bspw. 03:24:01 leider nur 3:24:1 und das zusammenführen des tresults klappt auch nicht.


Mfg
Tobi

Marco78
29.06.2006, 20:45
Schau dir mal die Befehle Format und Fusing an.

EDatabaseError
29.06.2006, 21:06
funktioniert leider nicht :-( :cry: was mach ich falsch:


D1 = Format(hex(second) , "00") 'Hier kommt auch bei 3 nur 3 statt 03
D2 = Format(hex(minute) , "00")
D3 = Format(hex(hour) , "00")

Tresult = Hour + ":" + Minute + ":" + Second 'Hier kommt ein Compilerfehler E242


Mfg

Marco78
29.06.2006, 21:13
Wie kommst du eigentlich auf deine HEX-Zahlen???

Was für eine Uhr benutzt du denn jetzt? Timer mit 32kHz-Quarz oder Timer im Sekundentakt in einer INT-Routine?

EDatabaseError
29.06.2006, 21:20
ich hab z.Zt. folgenden Code:

$regfile = "m128def.dat"
$crystal = 16000000

Config Timer1 = Timer , Prescale = 256
Enable Timer1
On Timer1 Tini
Enable Interrupts
Timer1 = 68569

Dim Tresult As String * 8
Dim Dresult As String * 8

Dim D1 As String * 2
Dim D2 As String * 2
Dim D3 As String * 2
Dim Year As Word
Dim Month As Word
Dim Day As Word
Dim Hour As Word
Dim Minute As Word
Dim Second As Word

minute = 58

Do
'....Hauptprogramm
Loop
End

Tini:
Timer1 = 68569
Second = Second + 1
If Second = 60 Then Gosub Addminute
If Minute = 60 Then Gosub Addhour
If Hour = 24 Then Gosub Addday
If Day = 30 Then Gosub Addmonth
If Month = 12 Then Gosub Addyear


D1 = Format(hex(second) , "00")
D2 = Format(hex(minute) , "00")
D3 = Format(hex(hour) , "00")

Tresult = Hour + ":" + Minute + ":" + Second

Print Tresult
Return

Addminute:
Minute = Minute + 1
Second = 0
Return

Addhour:
Hour = Hour + 1
Minute = 0
Return

Addday:
Day = Day + 1
Hour = 0
Return

Addmonth:
Month = Month + 1
Day = 0
Return

Addyear:
Year = Year + 1
Month = 0
Return

Mfg
Tobi

Marco78
29.06.2006, 21:31
Timer1 = 68569
Der Wert geht nur bis 65536. Benutz doch das Programm RNAVR.

Dim Month/Day/Hour/... As Word
Byte geht bis 256. Das reicht also locker für Minuten, Stunden, Tage, ...
Word verbraucht mehr Speicher (Auch wenn der M128 relativ gesehen genug hat).

Aber ich verstehe immer noch nicht, was du mit HEX willst. Du arbeitest doch mit Dezimalzahlen!

EDatabaseError
29.06.2006, 21:37
Ich kenn leider keinen Bascom Befehl wie in Delphi IntToStr mit dem man einen Numerischen wert Byte, Word... in einen String umwandeln kann.
Und dann weiß ich leider auch nicht wie ich mehrere String in einen großen Packe.

Das mit dem Byte werde ich machen.
RNAVR werde ich mir herunterladen. (Die Zeit ist aber trotzdem noch relativ genau :lol:)

Ich bin nur auf Hex() gekommen weil dazu in der Hilfe steht das er eine Numerische Var. in einen String umwandelt. Bin ich drübergestolpert ;-)

EDatabaseError
29.06.2006, 21:45
Das RNAVR ist ein Super Tool! Läuft Perfekt im Sekundenrhythmus!

Marco78
29.06.2006, 21:57
Ich kenn leider keinen Bascom Befehl wie in Delphi IntToStr mit dem man einen Numerischen wert Byte, Word... in einen String umwandeln kann.
STR()


Ich bin nur auf Hex() gekommen weil dazu in der Hilfe steht das er eine Numerische Var. in einen String umwandelt.
Kann ich mir so nicht vorstellen. Aber mit STR() wirst du sicherlich Erfolg haben.

Beachte in der hilfe auch den Punkt See Also. Da stehen verwandte Befehle oder die Gegenstücke zum Befehl.
Vielleicht ist es dir auch eine Hilfe eine Liste aller Befehle auszudrucken. Wenn man die Befehle vor Augen hat, kann man sich in etwa vorstellen, was sie wohl bewirken könnten und in der Hilfe nachschauen was sie wirklich machen und dann ggf unter See Also den richtigen Befehl finden.

Eine weitere (aber meist auch mühsame) Möglichkeit ist das durchsuchen des Forums. Fast alles wurde schon einmal behandelt.

Du benutzt den Befehl Print im Listing. Hast aber zuvor keine Baudrate eingestellt. Wie du siehst geht es trotzdem. Im Menü von Bascom unter Options/Compiler ist eine Baudrate eingestellt.
Dort sind auch viele andere Einstellungen möglich. z.B. Welcher AVR verwendet wird, welcher Quarz, Stackwerte, LCD-Pins.
Immer wenn du im Programm nicht gesondert angibst, was du verwendest werden diese Einstellungen genommen.

Im Prinzip könntest du dir auch:
$regfile = "m128def.dat"
$crystal = 16000000
sparen. Wenn es nicht angegeben wird, werden die Compilersettings genommen.
Aber das erleichtert nicht grade das nachvollziehen für andere. Und wenn du mal einen falschen Chip einstellst funktioniert das Program ggf. nicht mehr.
Oder wenn du viele verschiedene AVR-Typen hast, weisst du nachher nicht mehr, welches Programm für welchen AVR war.

Dies nur als kleinen Tipp zu Bascom.

Du könntest die Baudrate im Listing auch angeben, ohne das du sie brauchst.
So lange kein RS232-Befehl wir Print oder so kommt, wird Bascom "unnötige" Einstellungen einfach nicht beachten.

Die Angabe der Taktfrequenz ist auch dann erst relevant, wenn du was zeitabhäniges programmierst. Wobei ein Timer nicht zeitabhänig ist, den muss man zuvor schon ausrechnen. Die Befehle Wait oder auch Print benötigen nur die Frequenzangabe.
Wait 1 wartet im Programm (ungefähr) eine Sekunde. Damit Bascom weiss, wie lange ein Takt dauert muss die Frequenz angegeben werden oder es wird auf die Compilersettings zurückgegriffen.

Marco78
29.06.2006, 22:03
Das RNAVR ist ein Super Tool! Läuft Perfekt im Sekundenrhythmus!
100%ig perfekt auch nicht. Nach einigen Tage wirst du ein paar Sekunden Abweichung feststellen.
Das liegt zum einen an der Genauigkeit des Quarz, aber auch an der Berechnung des Prescalers und Preload.
Wenn der Timer aufgerufen wird, werden erstmal ein paar Takte benötigt um die Register zu sichern.
Um dieses Problem kümmert sich aber Bascom. Aber bevor der Timer wieder mit dem berechneten Wert aufgeladen wird, sind schon ein paar µS vergangen, die zuvor nicht berechnet wurden.

EDatabaseError
29.06.2006, 22:07
Bekomme leider immer noch folgendes:
1:23:8 statt 01:23:08
was um himmels willen mache ich falsch?!?

Und wie kann ich die Strings in einen großen packen???

Das mit dem $baud ist mir bewusst ich bin grad nur an einer Demo und da hab ich es mir erlaubt das wegzulassen.

PS: Mein aktueller Source:

$regfile = "m128def.dat"
$crystal = 16000000
$baud = 9600

Config Timer1 = Timer , Prescale = 256
Enable Timer1
On Timer1 Tini
Enable Interrupts

Dim Tresult As String * 8
Dim Dresult As String * 8

Dim D1 As String * 2
Dim D2 As String * 2
Dim D3 As String * 2
Dim Year As Byte
Dim Month As Byte
Dim Day As Byte
Dim Hour As Byte
Dim Minute As Byte
Dim Second As Byte

minute = 58

Do
'....Hauptprogramm
Loop
End

Tini:
Timer1 = 3036
Second = Second + 1
If Second = 60 Then Gosub Addminute
If Minute = 60 Then Gosub Addhour
If Hour = 24 Then Gosub Addday
If Day = 30 Then Gosub Addmonth
If Month = 12 Then Gosub Addyear


D1 = Format(str(second) , "00")
D2 = Format(str(minute) , "00")
D3 = Format(str(hour) , "00")

Print Hour ; ":" ; Minute ; ":" ; Second
' Tresult = Hour + ":" + Minute + ":" + Second

' Print Tresult
Return

Addminute:
Minute = Minute + 1
Second = 0
Return

Addhour:
Hour = Hour + 1
Minute = 0
Return

Addday:
Day = Day + 1
Hour = 0
Return

Addmonth:
Month = Month + 1
Day = 0
Return

Addyear:
Year = Year + 1
Month = 0
Return

EDatabaseError
29.06.2006, 22:09
Das RNAVR ist ein Super Tool! Läuft Perfekt im Sekundenrhythmus!
100%ig perfekt auch nicht. Nach einigen Tage wirst du ein paar Sekunden Abweichung feststellen.
Das liegt zum einen an der Genauigkeit des Quarz, aber auch an der Berechnung des Prescalers und Preload.
Wenn der Timer aufgerufen wird, werden erstmal ein paar Takte benötigt um die Register zu sichern.
Um dieses Problem kümmert sich aber Bascom. Aber bevor der Timer wieder mit dem berechneten Wert aufgeladen wird, sind schon ein paar µS vergangen, die zuvor nicht berechnet wurden.

das bissen ist egal die Uhrzeit wird alle 2 Tage via RS232 ins Modul gesendet.

Marco78
29.06.2006, 22:12
Ich müsste jetzt erst nachschauen um es genau zu sagen, aber ich bin der Meinung du musst Seconds usw. erst als String umwandelt und dann formartieren.
Evtl geht es mit Fusing einfacher?!

Das mit Baud hab ich auch nur erzählt, weil man es erstmal wissen muss, das es so ist. So lange etwas funktioniert ist ja alles ok, aber irgendwann fragt man sich warum es auf einmal nicht mehr geht.

So, ich muss jetzt ins Bett. Viel Spaß noch beim testen.

EDatabaseError
29.06.2006, 22:14
werde ich testen.

gute nacht.

EDatabaseError
29.06.2006, 22:23
So format funktioniert alles wunderbar. (Fehler in der Ausgabe der Daten :oops: )

The Final Code:

$regfile = "m128def.dat"
$crystal = 16000000
$baud = 9600

Config Timer1 = Timer , Prescale = 256
Enable Timer1
On Timer1 Tini
Enable Interrupts

Dim Tresult As String * 8
Dim Dresult As String * 8

Dim D1 As String * 2
Dim D2 As String * 2
Dim D3 As String * 2
Dim S As String * 2
Dim Year As Byte
Dim Month As Byte
Dim Day As Byte
Dim Hour As Byte
Dim Minute As Byte
Dim Second As Byte

minute = 58

Do
'....Hauptprogramm
Loop
End

Tini:
Timer1 = 3036
Second = Second + 1
If Second = 60 Then Gosub Addminute
If Minute = 60 Then Gosub Addhour
If Hour = 24 Then Gosub Addday
If Day = 30 Then Gosub Addmonth
If Month = 12 Then Gosub Addyear


D1 = Format(str(second) , "00")
D2 = Format(str(minute) , "00")
D3 = Format(str(hour) , "00")

Tresult = D3 + ":" + D2 + ":" + D1

Print Tresult
Return

Addminute:
Minute = Minute + 1
Second = 0
Return

Addhour:
Hour = Hour + 1
Minute = 0
Return

Addday:
Day = Day + 1
Hour = 0
Return

Addmonth:
Month = Month + 1
Day = 0
Return

Addyear:
Year = Year + 1
Month = 0
Return



Danke @ all wirklich super forum!


Mfg
Tobi

//EDIT: Ich geh nu au ins bett :erschöpf: