Forum: Mikrocontroller und Digitale Elektronik Grenzwertproblem


von anfänger0815 (Gast)


Lesenswert?

Hallo Forum, ich habe einen Frequenzmesser mit dem ATmega programmiert. 
Nun mein Problem: Wenn die Frequenz, sagen wir bei 6000 Hz liegt können 
da ab und an Schnitzer von 30 Hz gemessen werden. Die Geister wissen 
warum. Ich weiß es nicht. Ich lese immer den Timer nach einem Interrupt 
aus und da kommt es ab und an vor, daß der Wert eklatant vom eigentliche 
erwarteten abweicht. Habt ihr eine Lösung wie ich solche Schnitzer (muß 
ja nicht genau 30 Hz sein kann mehr oder weniger sein) die extrem vom 
erwarteten abweichen erkennen kann?

von Karl H. (kbuchegg)


Lesenswert?

anfänger0815 schrieb:

> Ich weiß es nicht.

Ich habe eine Vermutung.
Es könnte an deinem Programm liegen.

von Cyblord -. (cyblord)


Lesenswert?

Karl Heinz schrieb:
> anfänger0815 schrieb:
>
>> Ich weiß es nicht.
>
> Ich habe eine Vermutung.
> Es könnte an deinem Programm liegen.

Ich tippe eher auf Bug im Compiler oder libc. Sein Programm hört sich 
richtig an, so wie er es beschreibt ;-)

von Udo S. (urschmitt)


Lesenswert?

Vieleicht ein mikroskopisch kleines schwarzes Loch, das eine 
Zeitdilatation verursacht.
Wohnst du vieleicht in der Nähe vom Cern?

Im Ernst:
SOURCECODE, und bitte siehe Netiquette dazu.

von Cyblord -. (cyblord)


Lesenswert?

Udo Schmitt schrieb:
> Vieleicht ein mikroskopisch kleines schwarzes Loch, das eine
> Zeitdilatation verursacht.
> Wohnst du vieleicht in der Nähe vom Cern

Das klingt schlüssig. Raumschiff Enterprise hatte ja öfter mal Probleme 
mit dem Bordcomputer in der Nähe von Singularitäten. Da kann dann auch 
mal ganz schnell das Raum-Zeit-Kontinuum instabil werden. Uiuiui.

von Karl H. (kbuchegg)


Lesenswert?

cyblord ---- schrieb:
> Udo Schmitt schrieb:
>> Vieleicht ein mikroskopisch kleines schwarzes Loch, das eine
>> Zeitdilatation verursacht.
>> Wohnst du vieleicht in der Nähe vom Cern
>
> Das klingt schlüssig. Raumschiff Enterprise hatte ja öfter mal Probleme
> mit dem Bordcomputer in der Nähe von Singularitäten. Da kann dann auch
> mal ganz schnell das Raum-Zeit-Kontinuum instabil werden. Uiuiui.

Ja, schon. Aber spätestens seit Cpt. Piccard ist ja bekannt, wie man das 
löst: Man weißt den Computer an, die Schilde auf ein Zufallsmuster mit 
exakt 78.652985% Anteil von weißem Rauschen zu progammieren. Mach es so!

von anfänger0815 (Gast)


Lesenswert?

Anbei mein Code für den Kern des Frequenzmessers. Ist aber nicht so ganz 
mein Problem. Wie bekomme ich diese, nennen wir sie mal Spitzen, weg

1
;Hier werden die Voreinstellungen gemacht
2
.cseg
3
4
zaehler1_messen_vor:
5
  ldi tmp1,0
6
  out TCCR1A,tmp1
7
;Vorverteiler durch 8
8
  ldi tmp1,0b10000010
9
  out TCCR1B,tmp1
10
;Timer Interupt Mask
11
  in tmp1,TIMSK
12
  ori tmp1, (1<<TICIE1 | 1<<TOIE1)
13
  out TIMSK,tmp1
14
  ret
15
;-------------------------------------------------------------------------------------------------------------  
16
zaehler1_ueberlauf_int:
17
;Beim Ueberlauf des Zaehler 1 wird diese Spz um
18
;eins erhoeht. Dadurch koennen sehr kleine Frequenzen
19
;gemessen werden
20
  push tmp6
21
  in tmp6,sreg
22
  push tmp6
23
  lds tmp6,zaehler1_hoch_temp_temp
24
  inc tmp6
25
  sts zaehler1_hoch_temp_temp,tmp6
26
  pop tmp6
27
  out sreg,tmp6
28
  pop tmp6
29
  reti
30
;-------------------------------------------------------------------------------------------------------------   
31
;Dieser Programmteil wird angesprochen wenn sich am Steuereingang fuer Zaehler 1 der Pegel von Low nach High aendert.
32
zaehler1_start_stop:
33
  push tmp4
34
  in tmp4,sreg
35
  push tmp4
36
  push tmp5
37
  push tmp6
38
  push tmp7
39
  push tmp8
40
  push tmp9
41
  lds tmp5,zaehler1_status
42
  sbr tmp5,2
43
  sts zaehler1_status,tmp5
44
45
;Der aktuelle Zaehlerstand wird in die Register gespeichert  
46
  in tmp4,TCNT1L  
47
  in tmp5,TCNT1H 
48
  lds tmp6,zaehler1_hoch_temp_temp  
49
50
;Der alte Zaehlerstand wird in die Register gespeichert
51
  lds tmp7,zaehler1_nieder_tmp
52
  lds tmp8,zaehler1_mittel_tmp
53
  lds tmp9,zaehler1_hoch_tmp
54
55
;Der aktuelle Zaehlerstand wird gesichert
56
  sts zaehler1_nieder_tmp,tmp4
57
  sts zaehler1_mittel_tmp,tmp5
58
  sts zaehler1_hoch_tmp,tmp6
59
  
60
;Der Zählerstand (Drei Byte) wird vom vorhergehenden abgezogen. 
61
  sub tmp4,tmp7
62
  sbc tmp5,tmp8
63
  sbc tmp6,tmp9
64
  
65
  brcc zaehler1_start_stop_10
66
;Sollte das Ergebnis negativ sein wird noch das Zweierkomplement gebildet.
67
  clc
68
  com tmp4
69
  com tmp5
70
  com tmp6
71
  ldi tmp7,1
72
  add tmp4,tmp7
73
  ldi tmp7,0
74
  adc tmp4,tmp7
75
  adc tmp5,tmp7
76
77
 
78
zaehler1_start_stop_10:
79
;Die Differenz des Zählerstanden aktuell zu alt wird abgespeichert. Der ZS ist umgekehrt proportional zur Frequenz
80
  sts frequenz_nieder_tmp,tmp4
81
  sts frequenz_mittel_tmp,tmp5
82
  sts frequenz_hoch_tmp,tmp6
83
84
  pop tmp9
85
  pop tmp8
86
  pop tmp7
87
  pop tmp6
88
  pop tmp5
89
  pop tmp4
90
  out sreg,tmp4
91
  pop tmp4
92
  reti

von Matthias L. (Gast)


Lesenswert?

>exakt 78.652985% Anteil

reicht da ein float normaler Genauigkeit aus?


->
Vielleicht erklärst Du erstmal mit wenigen Worten, wie das Programm 
arbeiten soll.

von Karl H. (kbuchegg)


Lesenswert?

1
;Sollte das Ergebnis negativ sein wird noch das Zweierkomplement gebildet.
2
  clc
3
  com tmp4
4
  com tmp5
5
  com tmp6
6
  ldi tmp7,1
7
  add tmp4,tmp7
8
  ldi tmp7,0
9
  adc tmp4,tmp7
10
  adc tmp5,tmp7

Das brauchst du nicht.
Da du unsigned (also nicht vorzeichenbehaftet) rechnest, kannst du die 
Werte bedenkenlos einfach voneinander abziehen. Das Ergebnis ist 
trotzdem korrekt. Ob die Subtraktion unterläuft oder nicht, interessiert 
hier nicht.

> Ist aber nicht so ganz mein Problem.

Doch,
Denn deine 'Spitzen' sind das Symptom, dass irgendwo im Programm etwas 
nicht stimmt. Du willst aber das Problem angehen und nicht die Symptome.


Ein weiteres Problem kann dann entstehen, wenn der Input Capture fast 
zeitgleich zum Overflow auftritt. Denn dann hängt es von Mykrosekunden 
ab, ob der zum Zählerstand gehörende Overflow gezählt wird oder nicht. 
Je nachdem ist aber das Ergebnis korrekt oder du hast einen Overflow zu 
viel oder zu wenig gerechnet.

: Bearbeitet durch User
von anfänger0815 (Gast)


Lesenswert?

Wenn am Anschluß ICP1 sich der Pegel von Low nach High ändert wird der 
Programmteil, den ich sinnigerweise "zaehler1_start_stop" genannt habe 
angesprungen. Dort werden die zwei Zählerbytes und das  Byte 
zaehler1_hoch_temp_temp ausgelesen und für die nächste 
Unterbrechungsanforderung abgespeichert. Die drei Bytes werden von den, 
von dem letzten Unterbrechungsanforderung, abgespeicherten Zählerbytes 
abgezogen. Das Ergebnis ist dann eine Zahl, die im umgekehrten 
Verhältnis, unter Einbeziehung des Teilers und der akt. Quarzfrequenz, 
zur gemessenen Frequenz steht.

von anfänger0815 (Gast)


Lesenswert?

Am besten den Overflow weglassen?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Ein weiteres Problem kann dann entstehen, wenn der Input Capture fast
> zeitgleich zum Overflow auftritt. Denn dann hängt es von Mykrosekunden
> ab, ob der zum Zählerstand gehörende Overflow gezählt wird oder nicht.
> Je nachdem ist aber das Ergebnis korrekt oder du hast einen Overflow zu
> viel oder zu wenig gerechnet.


Das hier schlägt in eine ähnlich Kerbe
1
...
2
;Der aktuelle Zaehlerstand wird in die Register gespeichert  
3
  in tmp4,TCNT1L  
4
  in tmp5,TCNT1H 
5
...

wenn ich mir den Rest des Codes dazu denke, den du wieder mal nicht 
gezeigt hast, dann ist das in einer Interrupt Routine, die du an den 
Input Capture gehängt hast.
Dann willst du dir den Zählerstand aber nicht von TCNT1 holen, sondern 
vom Input Capture Register ICR1. Denn genau dazu ist es da: Tritt eine 
entsprechende Flanke auf, dann wird der Zählerstand von der Hardware 
sofort (also ohne Verzögerung) in ICR1 gespeichert. Die Chancen, das 
dieser Wert dann mit den gezählten Overflows dann auch tatsächlich 
zusammenpasst steigen dadurch enorm, wenn der Timer gerade von FFFF auf 
0000 umspringt, während die Flanke auftritt, bzw. kurz danach.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

anfänger0815 schrieb:
> Am besten den Overflow weglassen?

Das kommt auf deine zu messenden Frequenzen an. Wenn es sich im dich 
interessierenden Bereich so ausgeht, dass du nie mehr als 65535 
Zählertakte zu verrechnen hast, dann brauchst du den Overflow nicht 
berücksichtigen. Einfach Zählerstand_am_Ende weniger 
Zählerstand_am_Anfang rechnen, und es kommt das richtige Ergebnis raus 
(selbst wenn da ein Overflow dazwischen lag). Nur dürfen zur 
Zeitbestimmung einer Messperiode nicht mehr als 65535 Timer-Takte 
anfallen, denn dann muss der erste Overflow entsprechend berücksichtigt 
werden.

: Bearbeitet durch User
von anfänger0815 (Gast)


Lesenswert?

Bitte verstehe wenn ich den Rest des Codes mit angeben würde, würde ich 
den Rahmen sprengen. In der Zwischenzeit habe ich in dem Programm 5558 
Bytes, sagt der Assembler zumidest, geschrieben. Aber dasmit dem 
Registern muß ich gleich mal testen.

von lalala (Gast)


Lesenswert?

um nur Dein Symptom zu lösen: Wenn Du oft die richtigen Werte bekommst, 
und ab und zu einen Schnitzer, dann mach 'best of three'

von Karl H. (kbuchegg)


Lesenswert?

anfänger0815 schrieb:
> Bitte verstehe wenn ich den Rest des Codes mit angeben würde

Als Anhang geht das schon.
Es gibt hier genug Leute, die sich auch in 400 Zeilen Assembler 
innerhalb kürzester Zeit zurecht finden.

: Bearbeitet durch User
von anfänger0815 (Gast)


Lesenswert?

Soll jetzt nicht abwertend gemeind gewesen sein. Tschuldigung. Ich 
dachte wegen der Länge.

von anfänger0815 (Gast)


Lesenswert?

Die Sache mit den zwei Registern scheint zu funktionieren. Ich bastel 
jetzt noch a weng rum und melde mich demnächst wieder. Vielen Dank für 
die Hilfe.

von W.S. (Gast)


Lesenswert?

anfänger0815 schrieb:
> Hallo Forum, ich habe einen Frequenzmesser mit dem ATmega programmiert.
und
Karl Heinz schrieb:
> Ich habe eine Vermutung.
> Es könnte an deinem Programm liegen.

Na klasse. Tolles Vorhaben und dazu passende Antwort vom Mod.

Ich lese in diesem Forum immer wieder, daß gerade Atmel-Fans ganz extrem 
dazu neigen, für solche Vorhaben wie Zählfrequenzmesser irgendwelche 
Software-Akrobatik mit ihrem ATmega und dessen internen Timern nebst 
Capture-Registern zu betreiben - OHNE zuvor die Sache gründlich 
durchdacht zu haben. Man zähle z.B. mal die Anzahl von 
Firmware-Versionen vom Axel Schwenke zu seinem Projekt. Ja, ja, man 
kriegt es nach langer Odyssee schon hin, daß es irgendwie zu 
funktionieren beginnt, aber weil eben diese grandiosen 
Software-Kunststücke immer wieder sowas wie Sampling-Zeitpunkte, nicht 
erfaßte Überläufe, Vorrang zwischen verschiedenen Interrupts usw. nicht 
WIRKLICH berücksichtigen, funktioniert das Produkt eben nur meistens und 
nicht immer. Der Teufel liegt eben im Detail, das sollten Eleven sich 
mal gut einprägen.

Das Schlimme an all diesen scheinbaren Steilvorlagen ist, daß sie von 
Neulingen blind nachgebaut werden und selbige sich nie fragen, ob das 
verwendete Konzept überhaupt tragfähig ist. Stattdessen wird hier 
gefragt "warum geht es nicht wie erwartet, ich hab doch alles richtig 
nachgeäfft.."

Mein Ratschlag an den TO ist: Mach es anders, spendiere deinem Projekt 
ein paar IC's mehr - wenn's das Problem vereinfacht, sowas kostet nicht 
die Welt, aber mach es geradlinig und OHNE Software-Tricks.

W.S.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.