Atmega328P - Wie soll die Brown-Out-Erkennung funktionieren?

[GELÖST][UPDATE]:

Das Problem war mit Sicherungsbits. Irgendwie wurden die Sicherungen fälschlicherweise als 0xFE und nicht als 0xFD geschrieben. FE entspricht 1,8 V und somit arbeitete das Arduino-Board auf 1,8 V. Ich habe Arduino neu installiert und alles von Grund auf neu gestartet und mit dem von bigjosh vorgeschlagenen Show Info- Code konnte ich die Fuse-Bits überprüfen. Ich habe den BOD-Pegel auf 2,7 V eingestellt und jetzt funktioniert es wie erwartet. Mikrocontroller, der alle Operationen wieder aufnimmt, sobald ausreichend Spannung vorhanden ist.

Ein weiteres Update: Ich sah erweiterte Sicherungseinstellungen für 1,8 V aufgrund von Dateischreibberechtigungen auf C:\ in Windows. Anscheinend war die Board-Datei schreibgeschützt und Windows löst keine Fehler aus, wenn ich Strg + S drücke. Es führte mich zu der Annahme, dass die Board-Datei aktualisiert wurde, während sie noch auf dem standardmäßigen BOD-Pegel von 1,8 V feststeckte. Beim zweiten Mal habe ich mich für die Installation auf D:\ entschieden und alles funktioniert perfekt.


Ich versuche herauszufinden, wie ich BOD verwenden kann, um mein Arduino-Projekt robuster zu machen, aber es scheint ein weiteres Problem zu sein. Mein System läuft mit 3,3 V, daher habe ich mich entschieden, den BOD-Pegel auf 2,7 V einzustellen (erweiterte Sicherungen = 0x05).

Nur als Prüfstandstest habe ich einen seriellen Druckcode hochgeladen, der "Gestartet" druckt, wenn der Mikrocontroller zum ersten Mal startet, und dann alle halben Sekunden "Arbeiten".

Das Experiment bestand darin, den Atmega mit einem Tischnetzteil einzuschalten und den Serientext auf einem PC zu überwachen. Ich hatte erwartet, dass etwas Seltsames passiert, sobald die Spannung unter 2,7 V fällt. Bis 2,2V passierte nichts. Unter 2,2 V gab es mehrere Szenarien:

(Experimenteller Aufbau: Ich habe kein Arduino-Board verwendet. Ich habe es auf einem separaten Steckbrett gebaut und die Spannung wurde direkt über ein Tischnetzteil zugeführt. Es gab Filterkappen - 300 uF 16 V in der Nähe der IC-Pins. Seriell war mit dem PC verbunden direkt ohne galvanische Trennung. Gemeinsamer GND wurde ebenfalls hergestellt.)

Fall 1: Der Mikrocontroller wurde einige Male zurückgesetzt und funktionierte normal bei etwa 2,1 V. Beim weiteren Reduzieren hörte es auf zu drucken. Beim Erhöhen der Spannung kehrte es nie wieder in einen normalen Arbeitszustand zurück. Ein externer Reset brachte ihn in den Normalzustand.

Fall 2: Es druckte weiterhin einige zufällige Dinge auf Seriell, bis ich die Spannung weiter senkte, an welchem ​​​​Punkt es aufhörte zu drucken. Der Druckvorgang wurde nicht fortgesetzt, selbst nachdem die Spannung auf ein normales Niveau gebracht wurde. Ein externer Reset brachte ihn in den Normalzustand.

Fall 3: Es wurde einige Male zurückgesetzt und druckte weiterhin "Wmrkmng". An diesem Punkt begann ich, die Spannung auf normale Werte (3,3 V) zu erhöhen, aber es wurde immer noch falscher Text gedruckt. Ein externer Reset brachte ihn in den Normalzustand.

Meine Erwartung war, dass der Mikrocontroller heruntergefahren wird, wenn ein Brownout erkannt wird (alle GPIOs LOW und UART drucken nichts - ähnlich wie bei einem ausgeschalteten Mikrocontroller) und sobald die Spannung normal wird, sich so verhält, als wäre er eingeschaltet aus einem AUS-Zustand. Die Ergebnisse sind jedoch völlig unterschiedlich. Wenn ich es also in einem Produkt verwende und aus irgendeinem Grund ein Brownout auftritt, besteht die einzige bequeme Möglichkeit, es in einen funktionierenden Zustand zu versetzen, darin, es AUS- und wieder EINZUSCHALTEN, damit es das Power-On-Reset-Signal empfängt. In vielen Fällen (einschließlich meines) wird ein solches Verfahren definitiv nicht akzeptabel sein. Was sollte ich als solches tun, um einen solchen Sperrzustand zu verhindern? Ich bin mir nicht sicher, ob selbst Watchdog eine große Hilfe sein wird (betrachten Sie Fall 3 - Der größte Teil des Codes hat funktioniert. Was ist, wenn WDT kein Problem sieht und den Mikrocontroller so laufen lässt, wie er läuft).

(Bearbeiten: WDT ist in einigen Fällen wie erwartet fehlgeschlagen)

Ich konnte im Atmel-Datenblatt nicht viel finden, aber ich bin hier auf eine Stackexchange-Frage gestoßen , die ein ähnliches Problem für die PIC-Familie beschreibt.

(Edit 2: Während ich auf Antworten auf diese Frage wartete, führte ich einige andere Tests durch, die überhaupt keine externe Verbindung beinhalteten. Ich entfernte seriell und lud einen einfachen Code hoch, um eine LED mit 1 Hz zu blinken, wenn ein Pin HIGH war und bei 5 Hz, als der Pin auf LOW ging. Auch dieser Code hat nicht funktioniert. Die Ergebnisse in diesem Fall können mit Fall 1, 2 und 3 verglichen werden. Ich habe auch WDT getestet. Kein Nutzen. Eine seltsame Sache, die mir aufgefallen ist war, dass, obwohl ich die Bootloader-Konfiguration geändert habe, um verschiedene BOD-Pegel einzustellen - 1,8 V, 2,7 V und 4,5 V, der Code, der in allen Fällen bei etwa 2,2 V durcheinander gebracht wurde). Hier ist die Arduino-Definition:

uno.name=Arduino Uno

uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001
uno.vid.2=0x2A03
uno.pid.2=0x0043

uno.vid.0x2A03.warning=Uncertified

uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200

uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0x05
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard

Ich habe die erweiterten Fuse-Bits auf 0x04, 0x05 und 0x06 geändert, um die drei BSB-Werte zu testen.

Grundlegender LED-Blinkcode zum Testen:

int ledPin = 17;
int inputPin = 2;


void setup() {
  // put your setup code here, to run once:
//  Serial.begin(115200);
//  Serial.println("BOOT");
  pinMode(ledPin,OUTPUT);
  pinMode(inputPin,INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
//  delay(500);
//  Serial.println("XXXXXXXXXX");

  if (digitalRead(inputPin)==1)
  toggle(17,1000);
  else if (digitalRead(inputPin)==0)
  toggle(17,200);
}

void toggle(int pin_number, long int delay_time)
{
  digitalWrite(pin_number, HIGH);
  delay(delay_time);
  digitalWrite(pin_number, LOW);
  delay(delay_time);
}
Verwenden Sie ein echtes Arduino-Board? Welcher? Diese Platinen haben normalerweise einen Spannungsregler. Versorgen Sie den Chip über diesen Regler oder direkt mit dem Vcc-Pin?
Code? Schema (welche Pins sind mit Strom / LED verbunden)?
Wie brennen Sie die Sicherungen auf dem Zielchip? Avrdude direkt verwenden? Den Bootloader in der Arduino IDE brennen? Versuchen Sie vielleicht, ein kleines Testprogramm auszuführen, das die Sicherungen zur Laufzeit überprüft , um die Annahme zu überprüfen, dass die Sicherungen überhaupt gesetzt werden?
Das scheint eine großartige Idee zu sein, da ich in diesem Teil etwas zweifelhaft bin, ob die Sicherungen wie erwartet funktionieren. Idealerweise hätte ich bei BOD = 4,5 V nicht auf 2,2 V heruntergehen können. Funktioniert dieses Codebeispiel in einer Arduino-Umgebung? Ich lade den Bootloader mit einem anderen Arduino Uno hoch, das als Arduino ISP programmiert ist.
RE: Funktioniert dieses Codebeispiel in der Arduino-Umgebung? Diese ShowInfo-Arduino-Skizze sollte die aktuellen Sicherungsbits drucken.

Antworten (1)

Der Brownout-Detektor versetzt den Chip in den Reset-Modus, wenn die Spannung am Vcc-Pin unter den Schwellenwert fällt. Beim Zurücksetzen gehen alle GPIO-Pins in den Hochimpedanzmodus und es wird kein Code ausgeführt. Wenn die Versorgungsspannung für eine Mindestzeitdauer wieder über den Schwellenwert ansteigt, verlässt der Chip den Reset und beginnt mit der Ausführung von Code am Reset-Vektor, ähnlich wie bei einem normalen Start.

Denken Sie daran, dass viele Arduino-Boards über zusätzliche Stromschaltkreise wie einen Spannungsregler verfügen. Dies bedeutet, dass die Spannung, die Sie an das Arduino-Board liefern, möglicherweise nicht die Spannung ist, die der tatsächliche Chip an seinem Vcc-Pin sieht. Sie können ein Voltmeter verwenden, um die tatsächliche Spannung an diesem Pin zu überprüfen, also sehen Sie, ob sie Ihren Erwartungen entspricht.

Denken Sie auch daran, dass AVR-Chips an ihren Eingängen Klemmdioden haben. Wenn also ein GPIO-Pin mit einer höheren Spannung als der Vcc-Pin verbunden ist, kann der Chip weiterhin über den Eingangspin mit Strom versorgt werden. Aus diesem Grund bin ich auf einen sehr interessanten Fehler gestoßen ...

https://wp.josh.com/2014/03/03/the-mystery-of-the-zombie-ram/

Wie stellst du deine serielle Verbindung zum Chip her? Ist es möglich, dass Strom durch diese Verbindung hereinkommt?

Um die Dinge einfach zu halten, während Sie dies herausfinden, möchten Sie vielleicht versuchen, den Chip aus dem Arduino zu ziehen und ihn alleine auf ein Brotbrett zu legen, damit Sie die Stromversorgung direkt steuern können. Vielleicht möchten Sie auch die serielle Verbindung loswerden und stattdessen eine blinkende LED verwenden, um anzuzeigen, ob das Programm läuft oder gestoppt ist.

Abschließend würde ich die Annahme überprüfen, dass die Sicherungen während Ihres Programmiervorgangs wie erwartet eingestellt werden. Sie können entweder avrdudedie Sicherungen vom programmierten Chip zurücklesen, um zu sehen, ob sie Ihren Wünschen entsprechen, versuchen, die Sicherungen zur Laufzeit per Software zu lesen , oder einfach versuchen, die Taktrate über Sicherungen zu ändern, den Chip mit Ihrem Blinkcode zu programmieren. und dann Verifizieren, dass sich die Blinkrate geändert hat, um mit den neuen Sicherungseinstellungen konsistent zu sein.

Sobald der erwartete BOD wie erwartet funktioniert, können Sie damit beginnen, die Komplexität wieder zu erhöhen, um das Problem zu finden.

+1 für serielle Phantomspeisung - dies verursacht alle möglichen seltsamen Fehler.
Danke Bigjosh für die Antwort. Den Versuchsaufbau habe ich nun in der Frage beschrieben. Chip war auf einem separaten Steckbrett. Es wurden keine Regler verwendet. An IC-Pins wurden Spannungsmessungen durchgeführt. Serial könnte ein Problem gewesen sein, also habe ich das Setup getestet, indem ich eine LED blinken ließ. Mein Mikrocontroller hat sich auch in diesem Fall nicht erholt.
BOD funktioniert definitiv, also gibt es etwas Idiosynkratisches an Ihrem Setup, das das Problem verursacht. Mit genügend Informationen kann ich Ihr Setup neu erstellen und sehen, ob ich das Problem auch reproduziere.
@bigjosh - Vielen Dank, Mann. Mit dem von Ihnen vorgeschlagenen Code konnte ich überprüfen, wo ich falsch liege. Meine Sicherungsbits entsprachen 1,8 V, obwohl ich verschiedene Pegel ausprobiert hatte. Eine Neuinstallation von Arduino und ein erneutes Brennen des Bootloaders, gefolgt von einer Überprüfung, machten die Dinge einfach. Einen schönen Tag noch. :)