Hi, ich habe hier eine Funktion um den ADC 10 mal auszulesen, den
Mittelwert abzuspeichern und dem MUX auf den nächsten Kanal zu stellen.
Für die 10 Messungen soll der conversion_counter je um eins
incrementiert werden.
Zum testen gebe ich den Wert des Zählers mit var_out bei jedem Aufruf
aus.
Und hier ist das Problem: der Zähler hat IMMER den Wert 1. Ich habe den
ganzen Code durchsuchen lassen ob ich den Wert aus versehen irgendwo
nochmal benutze oder resette, negativ. Er Zählt ihn einfach nicht hoch.
Sollte die If-Condition betreten werden soll ein "in" gesendet werden,
auch das passiert nie, also wird der Zähler auch da nicht zurückgesetzt.
Andere Zähler im Code Funktionieren, jemand eine Idee warum das nicht
klappt?
AVR-Studio und Atmega8535.
1
//Globale Variablen
2
#define ADC_CYCLES 10 //Umläufe Genauigkeit <-> Zeit
3
unsignedcharadmux_counter;//Zähler für ADC Kanal
4
unsignedcharconversion_counter;//Zähler für Umläufe im ADC für höhere Genauigkeit
5
intadc_buffer;//Pufferspeicher des ADC
6
7
voidconvert_adc_channels()
8
{
9
adc_buffer+=ADCW;//Wert zu Pufferspeicher Addieren
10
if(conversion_counter>=ADC_CYCLES)//wenn Wandlungszähler gleich Zahl der Umläufe ist
Hatte es vorher auch als volatile deklariert weil ich das erst per ISR
machen wollte. Gleiches Ergebnis. Hardcoded ändert auch nichts, hatte
ich auch schon versucht.
Ist conversion_counter vielleicht irgendwie von GCC reserviert oä?
Hehe, scheint so, bin grade auf die Idee gekommen den Namen mal zu
ändern. mit adc_conversion_counter gehts plötzlich...???
Läubi .. schrieb:
> Wenn der Zähler nur in der Funktion benötigt wird kannst du ihn auch> dort lokal anlegen.
ich glaube das ist falsch, weil wenn ich die funktion aufrufe, bekomme
ich genau das resultat mit der 1 und weiter zählt er nicht. wenn dann
musst du die das in einer while schleife machen, aber soweit ich mir das
vorstellen kann, kommen die daten von einer interruptquelle und darin
wird die fkt aufgerufen.
such mal in deinem quelltext, wo die variable sonst noch
gebraucht/benutz/geschrieben wird.
@Läubi:
Du meinst static oder? Ja kann ich auch machen, allerdings wundert es
mich trotzdem warum es mit adc_conversion_counter geht und mit
conversion_counter nicht.
Das ELSE hat da nichts zu suchen, er soll IMMER einen weiter zählen.
@Kurz: Wasn das schon wieder für ein Gezicke? War ein Vorschlag, und der
von Benjamin hat ja leider auch nichts gebracht.
@Benjamin, nene das ist schon richtig, mit STATIC (nicht const) kann ich
dem Compiler sagen, er soll die Variable nach Funktinsende nicht
löschen (Speicher nicht Freigeben) sondern beim nächsten Aufruf mit dem
vorhandenen Wert weiter arbeiten.
An anderer Stelle im Text wird die Variable nicht mehr verwendet, habe
eben schon eine textsuche laufen lassen um das auszuschliessen.
Phillip Hommel schrieb:
> @Läubi:> Du meinst static oder? Ja kann ich auch machen, allerdings wundert es> mich trotzdem warum es mit adc_conversion_counter geht und mit> conversion_counter nicht.> Das ELSE hat da nichts zu suchen, er soll IMMER einen weiter zählen.
ja static... sorry. Ich vermute/befürchte das sich da irgenwas
überlagert, daher sollten Variablen halt einen so klein wie möglichen
Gültigkeitsbereich haben, dann ist die Gefahr geringer das was schief
geht.
Vieleicht mal mit nem Clean des Projektes versuchen?
> Das ELSE hat da nichts zu suchen, er soll IMMER einen weiter zählen.
Ja aber nur wenn er nicht auf 0 gesezt wird, sonst ist die zählung
nämlich:
0 1 2 ... 9, 1 ... 9, 1... 9, 1....9 weil sofort wieder erhöht wird.
Also jetzt geht es ja, hab die Variable einfach umbenannt.
Nochmal zur sicherheit, da ich es jetzt doch per interrupt machen
möchte:
Ich kann innerhalb des ISR auch static volatile definieren oder?
Dann würde ich den code mal dahingehend aufräumen und alles etwas
übersichtlicher machen.
Phillip Hommel schrieb:
> Also jetzt geht es ja, hab die Variable einfach umbenannt.> Nochmal zur sicherheit, da ich es jetzt doch per interrupt machen> möchte:> Ich kann innerhalb des ISR auch static volatile definieren oder?> Dann würde ich den code mal dahingehend aufräumen und alles etwas> übersichtlicher machen.
volatile bracuhst du nur wenn Interupt UND Hauptprogramm auf die
Variable zugreifen ODER sich der Wert auserhalb des Sichtbereiches des
Compilers ändern könnte (z.B. weil es sich um ein Hardwareregister
handelt)
Stimmt, so war das. Dh einfach im ISR die variablen static
initialisieren und gut is?
Nächstes kleines Problem ist, daß das ganze jetzt per interrupt läuft,
hab den ADC Prescaler auf 64 gestellt damit kommen ca 58kHz raus.
Der ADC liefert jetzt aber seltsame Werte.
Habe mal nur einen Kanal, ADC0 in Benutzung. Wenn ich ihn testweise an
gnd lege dann liefert er brav die 0, lege ich ihn aber an AVCC (kommt
vom USB-Port und ist die Versorgungssannung des Controllers) dann
schickt er abwechselnd 768 und 1022/1023. Ne Idee wo die 768 herkommen?
Habe inzwischen den o.g. Code noch dahingehend ergänzt, daß in der
If-Condition der ADC Buffer natürlich noch geleert wird.
AVCC ausreichend abgeblockt mit Spule+100nF? Kondesator an AREF?, ggf
nen kleinen Kondesator an den ADC Pin gegen GND.
Ansonstent soltest du auch besser über 8 oder 16 Werte mitteln dann kann
das der Compiler ggf. in einen Schift anstelle einer Division umsetzen.
Hardwaremäßig habe ich gar nichts abgesichert da es grade nur ums testen
geht (nich schimpfen ;)).
Das Problem scheint aber wo anders zu liegen da er immer exakt 1022 und
768 in ganz periodischer Sequenz sendet...Immer 8mal 768, dann einmal
1022. Irgendwo im Code muß da noch was hängen, ich suche weiter...
Phillip Hommel schrieb:
> Also jetzt geht es ja, hab die Variable einfach umbenannt.
Du hast das Symptom beseitigt, aber nicht die Ursache :-)
Dein Programmfehler, der nach deiner Schilderung ganz woanders steckt,
ist immer noch im Programm. Wahrscheinlich irgendwo ein Arrayüberlauf,
so wie in 95% aller Fälle, in denen es zu solch seltsamen Symptomen
kommt.
Edit: Deine weitere Schilderung der Ereignisse bestärkt mich eigentlich
in meiner Vermutung, dass du den 'Fehler' durch Umbenennen der Variable
nicht behoben hast :-)
Naja, ich habe ja jetzt ein ganz anderes Problem. Das eine war daß er
partout einen Zähler nicht incrementieren wollte, das zweite scheint
jetzt ein Anderes Problem zu sein:
Da ich ein Timer-interrupt und das ADC interrupt benutze, vermute ich
mal daß genau dort das problem liegen könnte.
Und zwar ist das ADCW ja eignetlich zweiteilig.
Die 768 sind genau 11 00 00 00 00. Also genau der High-Part von 1023.
Eventuell funkt jedes mal (ausser jedes 8. mal, da hab ich nämlich
1023))der Timer genau beim auslesen des ADCW dazwischen und der Low Part
geht verloren.
Beim Initialisiren, also der first conversion braucht er ja etwas länger
(25 anstatt 13 cycles) und da sind es auch keine 8 mal...
Mal schauen ob und wie ich das geregelt kriege...
Phillip Hommel schrieb:
> Naja, ich habe ja jetzt ein ganz anderes Problem. Das eine war daß er> partout einen Zähler nicht incrementieren wollte,
Das ist Blödsinn.
Das ist das Symptom, welches du gesehen hast. Die Ursache war aber mit
Sicherheit etwas anderes.
Was du getan hast war nichts anderes, als den Zähler an eine andere
Stelle im Speicher zu lanzieren. Dadurch wirkt sich dein Programmfehler
nicht mehr an diesem Zähler aus. Stattdessen wird halt irgendeine andere
Variable unzulässig verändert. Dein ursprüngliches Symptom ist weg,
dafür hast du ein anderes Symptom.
Und solange du das eigentliche Problem nicht behebst, wird das immer so
weitergehen. Solange bis du entweder das Problem behebst oder aber bis
du zufällig eine Konfiguration hast, in der das Problem eine
Speicherstelle verändert, die ansonsten keiner braucht und daher das
Problem etwas anstellt, was sich nicht mehr auswirkt. Aber wehe, du
veränderst dein Programm dann noch einmal. Dann ist er ganz plötzlich
wieder da :-)
Poste mal das komplette Programm, wenn es nicht zu lang ist (unter 300
Zeilen hat). Ich wette, da findet sich irgendwo ein zu klein
dimensinoiertes Array.
Sorry, das sollte gar nicht so sehr nach Widerspruch klingen wie es tut.
Eher als Gegenfrage ob diese beiden Phänomene wirklich zusammenhängen
können, aber das hast Du ja schon erklärt.
Habt Ihr nen Tip wie ich bei der Fehlersuche Vorgehen könnte? Da steh
ich nämlich grade echt im Wald.
Aufgetreten ist das ganze ab dem Moment wo ich das ADC-Interrupt ins
Spiel gebracht habe...Ich nehme das ganze nochmal aus dem ISR raus und
lass die Funkt mal in der Main laufen, mal sehn wie es dann aussieht.
Ich meld mich gleich nochmal.
Das Programm hat über 700 Zeilen plus config.h, das will ich Euch nicht
antun. Aber ich werde mal alle arrays checken.
All sowas ist arg Böswillig im Interupt!
Uart ausgaben dauern je nach Baudrate extrem lange, ebenso die Division
und Modulo mit nicht 2er Potenzen...
Außerdem solltest du deine Arrays/Zähler überprüfen auf das gleiche
Problem was du eben schon hattest mit dem zurücksetzen.
Phillip Hommel schrieb:
> Das Programm hat über 700 Zeilen plus config.h, das will ich Euch nicht> antun.
Das ginge zur Not auch noch, wenn es nicht zu chaotisch ist.
@ Läubi.
Die Ausgabe über den uart hatte ich nur drin um zu checken was er macht.
Die kommt in der eigentlichen Anwendung natürlich nicht vor.
Werde die Cycle-Zahl mal auf 8 setzen.
Arrays sehen eigentlich alle ok aus.
Ich habs!
In tiefster Ehrfurcht verneige ich mich vor Karl Heinz' 7.Sin inkl
seiner Erfahrung.
Danke natürlich auch an alle anderen die geholfen haben.
Problem lag hier
Dachte ich eigentlich auch, Problem is: wie finde ich den Fehler wenn
das Symptom nicht mehr auftritt?
Edit: Habe die 2. wieder auf die erste Version zurück-geändert und das
alte Problem taucht wieder auf...
Optimierung steht auf -Os.
Zusatzinfo, die o.g. Zuweisung mache ich in einem eingebundenen
Header-file, könnte es damit zusammenhängen?