Forum: Mikrocontroller und Digitale Elektronik Hilfe bei Programmierung / Fehlersuche in C benötigt.


von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute.

Wie ihr in der Überschrift schon erkennen könnt benötige ich etwas Hilfe 
bei der Fehlersuche in meinem kleinen Programm. Ich nehme es vorweg, 
dass ich noch nicht viel Erfahrung in der Programierung habe und 
deswegen vielleicht einiges umständlich oder falsch geschrieben habe.

Programiert habe ich in C/C++ und mein uC ist ein Atmega 16 mit einer 
Taktung von 1MHz.

Hier die Beschreibung meines Programmes:
Es handelt sich um einen Empfänger für 5 Ziele die bei einem Treffer 
einen PNP-Transistor ansteuern sollen. Des weiteren habe ich eine 
Überwachung für meine Akkuspannung und die Ladespannung welche durch 
LEDs signalisiert wird.

-Die Auswertung der Treffer erfolgt an PINA0 bis A5. Beim Treffen wird 
eine Spannung von 1.1V von dem Ziel abgegeben und entsprechend vom ADC 
registriert. Wurde zB Ziel_1 (PINA0) getroffen wird der Ausgang PIND2 
von Hi auf Low geschaltet. Ausgangspins für die Trefferanzeige sind 
PIND2 - PIND6.

-Wenn alle 5 Ziele getroffen sind, sollen diese noch 5 Sekunden 
nachleuchten und dann alle wieder abgeschaltet werden.

-Die Akkuspannung wird mit Hilfe eines Spannungsteilers (1:1) auf max. 
4.7V begrenzt. Liegt am Akku eine Spannung >= 6.6V an, wird eine Led an 
PINB0 eingeschaltet.
Wird die Akkuspannung kleiner als 6.6V, wird die Led an PINB0 
deaktiviert und eine andere an PINB1 aktiviert.

-Die Ladespannung wird auch wieder mit einem Spannungsteiler (1:2) auf 
max. 4.7V begrenzt. Ist die Akkuspannung <6.6V und die Ladespannung >10V 
schaltet die Led an PINB0 in den Blinkbetrieb.


Nun zu meinem Problem:
Ich habe meinen Quellcode Stück für Stück in Betrieb genommen.

-Der "Empfang" aller Treffer sowie die Anzeige des Treffers 
funktionieren.

-Das Nachleuchten für 5Sek und anschließendes Abschalten aller 5 Ziele 
funktioniert auch.

-Aktiviere ich die Akkuüberwachung gemeinsam mit dem Rest meines 
Programmes, funktioniert diese, aber die ADC-Pins 0 bis 3 sind ohne 
Funktion. Nur der PINA4 funktioniert.

Standardmäßig liegen PINA0 bis PINA5 an Masse.
Lege ich PINA0 bis PINA3 auf +5V, schalte dann erst die 
Spannungsversorgung ein, und dann PINA4 auf +5V, funktioniert die 
Messung des PINA4 sowie das Nachleuchten für 5Sek. Danach ist dieser 
Teil des Programmes wieder ohne Funktion.

-Die Überwachung der Ladespannung funktioniert gar nicht, da meine LED 
an PINB0 nicht blinkt. Ich vermute einen Fehler in meinem Timer, finde 
aber auch diesen nicht.


Ich hoffe ich habe es verständlich erklärt und mit Hilfe meiner 
Kommentare in der Programierung kann mir jemand weiter helfen und mir 
sagen, wo ich meine Fehler mache.

MFG Alex

von Stefan F. (Gast)


Lesenswert?

Du solltest hardwaremäßig sicherstellen, dass die Spannung an allen Pins 
niemals höher ist, als VCC und niemals niedriger als GND. Denn dies wäre 
ein nicht definierter Betriebszustand, indem fehlfunktionen zu erwarten 
sind.

Erst Signale anlegen und danach VCC darf nicht passieren.

> die ADC-Pins 0 bis 3 sind ohne Funktion
Warum denkst du das? An welchen Sympromen hast du das erkannt?

Dein Quelltext ist schrecklich formatiert. Öffne die Datei mal in einem 
Editor mit Auto-Format Funktion und wende diese dann an.

In der Prozedur Akkubetrieb() steuerst du die LED's nur dann an, wenn 
Ladespannung=0 ist.
Aber in der Prozedur Ladekontrolle  steuerst du die LED's immer an. Ich 
denke, hier solltest du ebenfalls die Ladespannung berücksichtigen, 
damit immer nur eine der beiden Prozeduren die LED's ansteuert und 
niemals beide "gleichzeitig".

> if ((Ladespannung >= 860) && (Akkuspannung < 983))  // Ladespannung > 10 V LED

Für mich liest sich der Code eher so, als ob die LED's nur angesteuert 
werden, wenn die Akkuspannung in einem kleinem Bereich liegt. Der 
Kommentar ist ganz sicher falsch.

Deine LED blinkt möglicherweise nicht, weil die Akkuspannung mehr als 
982 ist. Du solltest Dir mit Hilfe von Debug Meldungen oder einem 
Hardware-Debugger mal die konkreten Werte anzeigen lassen, die der ADC 
liefert.

Dann hast du hier noch einen Fehler:
1
if ((Ladespannung >= 860) && (Akkuspannung < 983))              // Ladespannung > 10 V LED 
2
  { 
3
    if(Timer_1_Sek == 970)
4
    {
5
      PORTB |= (1<<Akku_ok);
6
    }
7
  
8
    if(Timer_1_Sek == 1940)
9
    {
10
      PORTB &= ~(1<<Akku_ok);
11
      Timer_1_Sek = 0;
12
    }
13
  }

Was ist, wenn dein Timer zum Beispiel den Wert 1941 erreicht hat während 
die Ladespannung gerade <860 oder >=983 war? Dann wird der Timer 
überlaufen und das Blinken der LED für diese Zeit ausbleiben.

von Karl H. (kbuchegg)


Lesenswert?

Tu dir selbst einen Gefallen und hol dir von hier
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe#Der_interne_ADC_im_AVR

erst mal die ADC Basisroutinen.
Das ist doch unsinnig, wenn du die ADC Ansteuerung immer wieder in jeder 
Funktion neu in allen Details ausführst. Das schreibt man sich einmal 
als Funktion und benutzt die dann.

Deine 'Treffer' Auswertungen könnten zb so aussehen
1
void Treffer1 (void){
2
3
  if( ADC_Read( Ziel_1_hit ) > 190 )
4
    PORTD &= ~(1<<Treffer_1);
5
}

selbiges für alle anderen Funktionen.
Einfach nur Code weiter zu kopieren und ein paar Konstanten austauschen 
ist keine gute Idee, vor allen Dingen wenn die Funktionen umfangreich 
sind. Man kommt dann schnell in die Situation, dass man vor lauter 
(unwichtigem) Code die wesentlichen Dinge nicht mehr sieht.
Ganz abgesehen davon, dass dann massenhaft Code völlig unnötiger weise 
zu Stande kommt.

von Karl H. (kbuchegg)


Lesenswert?

> -Die Ladespannung wird auch wieder mit einem Spannungsteiler (1:2)
> auf max. 4.7V begrenzt. Ist die Akkuspannung <6.6V und die
> Ladespannung >10V schaltet die Led an PINB0 in den Blinkbetrieb.

Die Ladespannung und die Akkuspannung sind wie miteinander verschaltet?

von Karl H. (kbuchegg)


Lesenswert?

> Programiert habe ich in C/C++ und mein uC ist ein Atmega 16 mit einer Taktung 
von 1MHz.

Dann hast du dich verrechnet.

WEnn der µC mit 1Mhz läuft und du beim Timer einen Vorteiler von 1024 
einstellst, dann erhält der Timer pro Sekunde 976 Pulse seinen Wert zu 
erhöhen.
Da du den Interrupt auf den Overflow gelegt hast, erfolgt alle 256 
Timererhöhungen ein Overflow. Pro Sekunde hast du also 976 / 256 gleich 
3.8 (sagen wir 4) Overflows.
Damit ...
1
  ISR (TIMER0_OVF_vect)
2
  {
3
  Timer_1_Sek ++;
4
5
....
6
7
}
8
...
9
    if(Timer_1_Sek == 970)
10
...
... 970 Overflows zu stande kommen, müsstest du also 3698 Sekunden vor 
der LED ausharren. Also eine knappe Stunde.

: Bearbeitet durch User
von Alex (Gast)


Lesenswert?

> ADC Pin 1-3 ohne Funktion:
- Ich habe eine Spannung angelegt und konnte keine Reaktion darauf 
feststellen. Daher war ich der Annahme, dass mein Programm die an irgend 
einer Stelle funktionslos macht.

> Die Formatierung:
- Ganz klar mein Fehler. Ich habe es mit dem programmers Notepad von 
WinAVR geschrieben und da sah es noch schön übersichtlich aus mit der 
Formatierung.

> blinkende Led:
- Der Zustand, dass die Ladespannung kleiner als 860 wird, passiert nur 
wenn das Ladegerät aus ist und dann befinde ich mich ja wieder im 
Akkubetrieb.


>Lade/Akkuspannung:
- Als Akku dient ein 8,4V (9V) NiMh Akku. Als Ladespannung habe ich ein 
12V 600mA Ladegerät. Schaltbild ist im Anhang.
Spannungsteiler für den Akku habe ich am In vom 7805 und gegen Masse.
Spannungsteiler für die Ladespannung habe ich direkt zwischen +12V und 
Masse von der Ladebuchse.

>Basisroutine:
-mit der kürzeren Schreibweise hast du schon recht. So wie es jetzt ist, 
war es für mich als Anfänger noch am übersichtlichsten. Mit der Übung 
und der Zeit entwickelt man sich weiter.

>Timer:
-So langsam wird es peinlich für mich....


Danke für die schnelle Hilfe!

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Anhang:

von Stefan F. (Gast)


Lesenswert?

Schau mal, ob du dem Editor die Verwendung von Tabulator-Zeichen 
abgewöhnen kannst. Wenn du stattdessen mit Leerzeichen einrückst (die 
meisten Text Editoren können die Tab Taste mit Leerzeichen belegen) 
vermeidest du solche Probleme beim Dateiaustausch.

> Der Zustand, dass die Ladespannung kleiner als 860 wird, passiert
> nur wenn das Ladegerät aus.

Sicher? Was ist, wenn der Akku ziemlich leer ist und dann erst geladen 
wird. Die Spannung steigt doch nicht sprunghaft an, nur weil ein 
ladegerät angeschlossen ist. Das dauert seine Zeit - denke ich.

> Als Akku dient ein 8,4V (9V) NiMh Akku.
> Als Ladespannung habe ich ein 12V 600mA Ladegerät.

Falls es ein 9V Block in der üblichen Größe ist, lädst du ihn 
hoffentlich nicht mit den vollen 600mA Ladestrom.

Wie stellst du denn eigentlich, dass der Akku nicht überladen wird? Ich 
denke, dein Konzept, den Füllstand an der Spannung auszumachen, ist 
grundsätzlich falsch.

Ein zuverlässiges und sicheres Ladegerät kombiniert das sogenannte 
Delta-U Verfahren mit einer Temperaturüberwachung und einem Timeout.

Das hat alles nichts mit dem Programmcode zu tun, aber mich beschleicht 
das Gefühl, dass hier die Funktionalen Mängel schon beim 
Funktionskonzept beginnen. Wir helfen Dir gerne, das in ordnung zu 
bringen.

von Alex (Gast)


Lesenswert?

Wegen dem Akku gebe ich dir gerne Recht. Es ist klar, dass moderne 
(universal) Ladegeräte mit einer Temperaturüberwachung etc ausgestattet 
sind. Bei LiPo Akkus (Modellbau) sind noch deutlich mehr Faktoren als 
die Temperatur und die Spannung zu überwachen. Das ist ein kleiner 
Vorteil von den NiMh Akkus. Die sind da etwas robuster und einfacher 
gehalten, haben dafür aber auch eine geringere Spannung und einen 
kleineren Strom. Die Angabe mit 8.4V ist schon richtig gewesen. Von der 
Bauform her sind es normale 9V Blöcke aber aufgrund dessen, dass es NiMh 
Akkus sind bestehen sie aus 7 Zellen á 1,2V was 8,4V bei max. 200mAH 
macht. Ich habe mein Schaltbild gepostet. Darauf ist ersichtlich, dass 
ich den LM317 durch den 9R3 Widerstand als Konstantstromquelle benutze 
wodurch der Ladestrom auf 217mA begrenzt wird.
Während des Ladevorganges steigt die Ladespannung am Akku langsam auf 
bis zu 9.6V an. Ist dieser Punkt erreicht ist der Akku auch voll 
geladen. Deshalb sollte die Led in meinem Programm auch bei 9.6V 
Ladespannung aufhören zu blinken.

>Ladespannung kleiner 860
-Es ist blöd ausgedrückt von mir. Es ist nicht die eigentliche 
Ladespannung sondern die Spannung, direkt an der Ladebuchse. Also eine 
Kontrolle ob das Ladegerät angeschlossen ist oder nicht.

Die eigentliche Kontrolle welche Spannung der Akku hat (Ladevorgang oder 
Betrieb ist egal) wird von der Variable "Akkuspannung" gemessen.

von Karl H. (kbuchegg)


Lesenswert?

Karl H. schrieb:

> ... 970 Overflows zu stande kommen, müsstest du also 3698 Sekunden vor
> der LED ausharren. Also eine knappe Stunde.

Äh. Da muss ich mich jetzt verrechnet haben.
Wenn pro Sekunde ca 4 Overflows auftreten, dann können 970 Overflows 
nicht 1 Stunde brauchen. Es sind nur ca. 250 Sekunden (überschlagsmässig 
gerechnet 1000 / 4). Also irgendwas um die 4 Minuten. Macht es aber auch 
nicht besser, denn so lange hast du sicher nicht gewartet.

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:

>>Basisroutine:
> -mit der kürzeren Schreibweise hast du schon recht. So wie es jetzt ist,
> war es für mich als Anfänger noch am übersichtlichsten. Mit der Übung
> und der Zeit entwickelt man sich weiter.

Code zu duplizieren ist praktisch nie die übersichtlichere Variante.
Deinen jetzigen Code kann man von geschätzten 250 Zeilen auf vielleicht 
60 oder 70 Zeilen (ebenfalls geschätzt) einstampfen. Wenn 2/3 vom Code 
durch eine andere Organisation wegfallen, kann man nicht davon sprechen, 
dass das Original übersichtlicher gewesen wäre.

3 Streichhölzer vor sich auf dem Tisch liegen haben ist übersichtlich. 
Ein Haufen von 300 Streichhölzer vor sich zu haben ist nicht mehr 
übersichtlich.

von lm317 (Gast)


Lesenswert?

Der Schaltplan mit dem LM317 ist mistig.

Schau doch noch mal ins Datenblatt, da ist eine richtiges Beispiel drin.

Und die Diode (V2) ist als Verpolschutz gedacht? Wenns sein muß.
Eine Diode sollte aber auch hinter den LM317, für den Fall, daß die 
12Volt mal nicht anliegen.

von Wolfgang A. (Gast)


Lesenswert?

Stefan U. schrieb:
> Du solltest hardwaremäßig sicherstellen, dass die Spannung an allen Pins
> niemals höher ist, als VCC und niemals niedriger als GND. Denn dies wäre
> ein nicht definierter Betriebszustand, indem fehlfunktionen zu erwarten
> sind.

Eine Spannung von deutlich weniger als 0.5V bzw. mehr als VCC+0.5V 
stellt ohne Strombegrenzung sogar ganz schnell einen sehr definierten 
Betriebszustand her: Die Eingangsschutzdiode wird überlastet und die 
Chancen stehen nicht schlecht, dass der Pin danach zu nichts 
Vernünftigem mehr zu gebrauchen ist.

von Stefan F. (Gast)


Lesenswert?

Ich hatte mal gelesen, dass I/O Pins häufig trotz defekter Schutzdiode 
noch funktionieren. Aber sie werden dann sehr anfällig gegen hohe 
Fremdspannung z.B. durch einfaches berühren.

von Alex (Gast)


Lesenswert?

Bin grade dabei eure Tips und Vorschläge umzusetzen, kann aber noch 
etwas dauern bis ich damit fertig bin.
Um die Diskusion um defekte I/O Pins auszuräumen; bei meiner Schaltung 
kommt keine Spannung vor die größer ist als VCC und präzise 5V hat.

von Stefan F. (Gast)


Lesenswert?

Damit widersprichst du deiner vorherigen Information, dass Du Signale 
angelegt hast, bevor die Stromversorgung (VCC) angelegt wurde.

Wen VCC Null Volt ist, und ein Signal 5V hat, dann ist das Signal um 5V 
höher, als VCC. Dann ist es 10x höher, als zulässig.

> Lege ich PINA0 bis PINA3 auf +5V, schalte dann erst die
> Spannungsversorgung ein ... Danach ist dieser
> Teil des Programmes wieder ohne Funktion.

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.