Forum: Mikrocontroller und Digitale Elektronik Probleme mit LED blinken lassen, Frequenz ändert sich nicht


von Jürgen S. (jsachs)


Lesenswert?

Hallo,

ich traue mich mit dem Problem ja fast nicht zu fragen.
Aber so langsam habe ich das Gefühl, der ATmega1284p bootet einfach 
ständig neu und daher blinkt die LED scheinbar immer im gleichen Takt.
Selbst wenn ich die LED nur einfach einschalte, flackert diese ?!?!

Also Programm auf ein Minimum lesbar reduziert.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define LED_PIN (PD6)
5
#define LED_PORT (PORTD)
6
#define LED_DDR (DDRD)
7
8
#define SET_LED_ON (LED_PORT |= _BV(LED_PIN))
9
#define SET_LED_OFF (LED_PORT &= ~_BV(LED_PIN))
10
#define SET_LED_TOGGLE (LED_PORT ^= _BV(LED_PIN))
11
12
#define nop() asm("nop;")
13
14
int main(void)
15
{
16
    LED_DDR|= _BV(LED_PIN);
17
    while(1)
18
    {
19
        SET_LED_ON;       // Testweise, aber auch flackert die LED
20
      //SET_LED_TOGGLE;
21
      _delay_ms(1000);    // egal welchen Wert ich nehme 200,500,1000 Das Flackern ändert sich nicht
22
    }
23
}

compiliert und geladen wird es mit (Zum test sogar ohne Makefile):
1
avr-gcc -mmcu=atmega1284p -Os -c main.cpp -o main.o -DF_CPU=16000000
2
avr-gcc -mmcu=atmega1284p main.o -o main.elf
3
avr-objcopy -O ihex -j .text -j .data main.elf main.hex
4
avrdude -c stk200 -p atmega1284p -B50 -U flash:w:main.hex

die Fuses sind wie folgt gesetzt:
avrdude: safemode: Fuses OK (E:FC, H:D1, L:FF)

Der ATmega1284 läuft mit einem externen 16MHz Quarz an 5V

Was habe ich übersehen ?!

Anfangs hatte ich for schleifen als delay eingebaut, selbes Ergebnis.

Wäre dankbar, wenn mir jemand das Brett vor dem Kopf weg nimmt.

Juergen

von Jörg R. (solar77)


Lesenswert?

Jürgen S. schrieb:
> Selbst wenn ich die LED nur einfach einschalte, flackert diese ?!?!

Fehler im Aufbau?

von Jürgen S. (jsachs)


Lesenswert?

Der Aufbau geht.
Habe auch schon mehrere IO Pins versucht.
Die Prinzipielle Ansteuerung geht auch.
Schalte ich die LED am Anfang mit SET_LED_OFF aus, also nie an, bleibt 
die Dunkel.
Erst wenn ich einen SET_LED_ON nutze geht die auch an, oder besser 
flackert eben sehr schnell.

Ich denke eher ich bin in so einem Kompatibilitätsmodus und daher stürzt 
das Program ab und der AVR bootet ständig neu, wodurch die Ports zurück 
gesetzt werden und die LED ausgeht.

Juergen

von Jürgen S. (jsachs)


Lesenswert?

Kuriose Sache.

hatten die Platine jetzt für ca. 5 Minuten abgeschaltet.
und seither geht alles wie erwartet.
Ich kann auch die Zeiten ändern, einspielen und tut.

WTF ? (sorry)

Jürgen

von Toxic (Gast)


Lesenswert?

Jürgen S. schrieb:
> WTF ? (sorry)

Why sorry?
whiskey tango foxtrot => What the fuck: an expression of shock.

Du bist geshocked - that's all....?

von Christian S. (roehrenvorheizer)


Lesenswert?

Hallo,

jetzt stellt sich die Frage, ob man den Fehler reproduzieren kann...

MFg

von Teo D. (teoderix)


Lesenswert?

Bei dem Fehlerbild, hat er entweder garnicht oder immer das selbe 
Hex-File gebrannt.

von Jürgen S. (jsachs)


Lesenswert?

Teo D. schrieb:
> Bei dem Fehlerbild, hat er entweder garnicht oder immer das selbe
> Hex-File gebrannt.

Das kann ich 100% ausschließen.
1. Hatte ich das auch vermutet und daher genauer drauf geachtet
2. war das File immer unterschiedlich groß durch die tests
3. hat avrdude auch immer die passende Größe, also Unterschiedliche 
Größe übertragen.

Reproduzieren läst es sich auch nicht mehr, es tut seither einfach, ich 
kann einspielen, Änderungen vornehmen, es geht wie es soll....

Dachte auch schon an den STK200, habe aber den Reset abgezogen um sicher 
zu sein. Hat aber keinen Unterschied gemacht.

Mich ärgert dabei immer die Zeit die man in den Sand setzt und nicht 
weis warum.

Danke trotzdem.
Juergen

von 2 Cent (Gast)


Lesenswert?

Jürgen S. schrieb:
> hatten die Platine jetzt für ca. 5 Minuten abgeschaltet.
> und seither geht alles wie erwartet.
> Ich kann auch die Zeiten ändern, einspielen und tut.

Ohne ein einziges Byte am Code zu ändern? Dann werden wir es nie 
erfahren.

Ähnlicher Fall: Was mich mal sehr sehr lange beschäftigt gehalten hatte: 
Der Compiler hatte mein (selbstgeschriebenes) delay einfach 
wegoptimiert.

von Teo D. (teoderix)


Lesenswert?

Jürgen S. schrieb:
> Teo D. schrieb:
>> Bei dem Fehlerbild, hat er entweder garnicht oder immer das selbe
>> Hex-File gebrannt.
>
> Das kann ich 100% ausschließen.
> 1. Hatte ich das auch vermutet und daher genauer drauf geachtet
> 2. war das File immer unterschiedlich groß durch die tests
> 3. hat avrdude auch immer die passende Größe, also Unterschiedliche
> Größe übertragen.

Dann haste nen echten Gremlin erwischt. ;)
Das lässt mich dann auch nicht mehr los. Wenn sie sich dann doch 
zeigten, war's eigentlich immer, ein saudämlicher Fehler von mir. :D
Das ist wie ein eingebrannter Blinder-Fleck.

von Jürgen S. (jsachs)


Lesenswert?

Nun, ich kann das ganze doch etwas Reproduzieren.

Und zwar, wenn ich Code in den Bereich des Bootloaders lade.
Der Bootloader Funktioniert wie erwartet (ist ja auch unverändert seit 
Jahren, außer dass ich nun mit 16MHz, statt 8MHz CPU Takt fahre.

Soweit alles ok.

Lade ich nun per Bootloader den neuen Code in die CPU, habe ich das 
Flackern wieder.
Ein Hardware Reset der CPU ändert nichts, ich muss jetzt wirklich einen 
Power OFF=>On machen, dann läuft das eingespielte Programm wie erwartet.

Springe ich nun von meinem Programm aus in den Bootloader, bekomme ich 
wieder das Flackern.
Ich meine mich Dunkel zu erinnern, dass man bei manchen ATmega nach 
einen Software Reset manche Register nicht im gleichen Zustand hat wie 
bei einem Power On ?!

Oder habe ich mich komplett verlaufen....

Sowohl Bootloader und Programm funktionieren so eigentlich schon auf 
einer Baugleichen Platine.
Nur läuft da die CPU noch mit dem Internen 8MHz Takt (Taktteiler ist 
aus).

Der Bootloader ist als normales eigenständiges Programm implementiert 
und wird an die Start Adresse des Bootloaders geladen.
Einen Sprung dorthin löst also die Neuintialisierung per Code aus.

Der Gedanke ist eigentlich folgender:
Strom AN
AVR springt in den Bootloader
Bootloader macht eine Checksummen Prüfung des Flash
Ist die Checksumme ok, noch etwas Delay (damit man ein update starten 
kann) und Sprung ins Hauptprogramm, was ein Sprung an Adresse 0x0000 
bedeutet....

Der Bootloader läuft komplett ohne Interrupts, das Hauptprogramm 
schon...
Interrupts werden natürlich im Bootloader sofort deaktiviert.

Aber genau so mache ich das schon seit Jahren.
Also kann es ja fast nur etwas mit den Fuses sein, die habe ich ja im 
ersten Post aufgeführt.

Hoffe einer bringt mir die Erleuchtung.
Gruss
Jürgen

NACHTRAG:
ich habe sowohl im Hauptcode, als auch im Bootloader folgenden Code, der 
wohl notwendig ist, um den Watchdog aus zu schalten:
1
#ifdef __AVR_ATmega1284P__
2
// Function Pototype
3
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
4
5
// Function Implementation
6
void wdt_init(void)
7
{
8
    MCUSR = 0;
9
    wdt_disable();
10
    return;
11
}
12
#endif

: Bearbeitet durch User
von Jürgen S. (jsachs)


Lesenswert?

ich kann nur sagen "Mea culpa", Asche auf mein Haupt...

Alles gut, alles geht.
In meinem Testcode hatte ich genau den obigen Code zum Initialisieren 
des Watchdog nicht eingebaut, oder besser auskommentiert.

Nachdem dieser wieder im Bootloader und Hauptprogramm aktiv ist, ist 
alles ok, bis jetzt.
1
#ifdef __AVR_ATmega1284P__
2
// Function Pototype
3
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
4
5
// Function Implementation
6
void wdt_init(void)
7
{
8
    MCUSR = 0;
9
    wdt_disable();
10
    return;
11
}
12
#endif

Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv 
und man muss den sehr früh abschalten. Daher oberer Code, der im frühen 
"Init" des Programms liegt, den noch der Compiler Automatisch erzeugt.

Ein wdt_disable(); im Hauptprogramm kommt da wohl zu spät.

Und herausgefunden habe ich das durch Subversion, womit ich mein 
Projekte verwalte (Und Nein, ich nutze kein git :-) ). Einmal die 
History durchsehen und TATA, da steht es doch direkt im Kommentar der 
Revision :-)

Gruss
Juergen

: Bearbeitet durch User
von Teo D. (teoderix)


Lesenswert?

Jürgen S. schrieb:
> Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv

Ist nicht meine Welt aber lässt er sich nicht auch per Fuses 
deaktivieren?
KA, ob das bequemer ist.

von c-hater (Gast)


Lesenswert?

Jürgen S. schrieb:

> Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv

Nicht ab Werk, nein.

Er muss also später aktiviert worden sein, entweder direkt durch dich 
selber oder als "Nebenprodukt" durch das Flashen des Bootloaders. Also 
auch wieder: durch dich selber, wenn auch vielleicht nicht absichtlich.

Vermutlich ist es so: Der Bootloader benutzt den Watchdog-Reset, um die 
Anwendung garantiert mit dem Reset-Hardwarezustand zu starten, der im DB 
steht.
Nötig ist das nicht wirklich. Ein anständiger Bootloader kann diesen 
Zustand auch gezielt herstellen, ohne dazu den Watchdog benutzen zu 
müssen. Er wird dann allerdings eine Handvoll Bytes größer ausfallen 
müssen, was bei einem Mega1284P keine Rolle spielt (bei kleinen AVR8 
aber eventuell wichtig sein kann).

von Jürgen S. (jsachs)


Lesenswert?

Springen zwischen Bootloader und APP mache ich nicht durch den Watchdog, 
der bringt mich nur zurück in den Bootloader :-)

Der Bootloader ist wie folgt definiert:
1
typedef void ( *bootloader_stub ) ( void );
2
bootloader_stub bootloader = (bootloader_stub)(BOOTLOADER_ADR / 2);  // Need to be in WORD Address

Und so kann ich einfach mit "bootloader();" in den Bootloader springen.
Den Watchdog benutze ich aktuell nur, wenn ich den ATmega gezielt 
Reseten möchte.

Wobei ich Praktisch als erstes in jedem Hauptprogramm ein wdt_disable() 
stehen habe. Er sollte also in jedem Fall aus sein, wohl nur nicht 
schnell genug.

Wieso flackerte dann die LED, obwohl ich nicht mal den Ausgang anmachen 
konnte?

Spekulation:
- Portpin geht direkt auf den Eingang eines ULN2803, an dessen Ausgang 
die LED hängt.
- Was mir nun auffällt ist, dass wenn der Pin noch ein Eingang ist, 
Glimmt die LED bereits
- Dadurch das die LED bereits glimmt, kam es zur Fehlinterpretation, der 
ATmega würde die LED bereits ansteuern, soweit kam er wohl nicht, wurde 
resetet => LED AUS.

Nun denn, der Fehler ist gefunden und eingrenzbar.

Der Hintergrund zu dem Code ist etwas näher hier erläutert:
Beitrag "problem mit wdt zurücksetzen"

Gruss
Juergen

von Peter D. (peda)


Lesenswert?

Jürgen S. schrieb:
> Wenn ich das richtig verstehe, ist bei diesem ATmega der Watchdog aktiv
> und man muss den sehr früh abschalten.

Nö, der ist nicht aktiv.
Wurde er jedoch gesetzt, läßt er sich nur durch Power off oder diese 
spezielle Sequenz abschalten.
Ein anderes Reset oder Setzen der Fuses schaltet ihn nicht ab!

Das frühe Abschalten oder Setzen auf eine längere Zeit ist nur 
notwendig, wenn viel externes RAM angeschlossen ist oder der CPU-Takt so 
langsam, daß das RAM-Init nicht innerhalb 16ms abgeschlossen ist.

von Jürgen S. (jsachs)


Lesenswert?

Aus den Tiefen der avr-libc

    Note that for newer devices (ATmega88 and newer, effectively any
    AVR that has the option to also generate interrupts), the watchdog
    timer remains active even after a system reset (except a power-on
    condition), using the fastest prescaler value (approximately 15
    ms).  It is therefore required to turn off the watchdog early
    during program startup, the datasheet recommends a sequence like
    the following:

Da habe ich auch den Code her.
Ich verstehe das so, hat man den Watchdog einmal aktiv, kriegt man ihn 
nur damit wieder aus.

Der ATmega1284p hat ja schon etwas mehr RAM. eventuell dauert das Init 
deswegen zu lange.

Das ist auf alle Fälle die Lösung zu meinem Problem.

Und da dies selbst einen Reset überlebt, überlebt der Watchdog 
vermutlich auch ein Programm upload per ISP.
Ist das "Problem", also Watchdog aktiv, einmal da, hilft nur noch der 
Power Off.

Gruss
Juergen

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.