Arduino Spannungsproblem?

Hallo zusammen,

ich bin neu hier im Forum und möchte mich gleich mit einer Frage an euch wenden. Vorweg: Ich habe keine Erfahrung im Programmieren und habe mir deshalb mit ChatGPT Unterstützung geholt, um den Code für mein Projekt zu erstellen.

Ich habe mir mit einem Arduino Mega einen Interrupter für meine Tesla-Spule gebaut. Die Aufgabe des Interrupters ist es, die Frequenz und Pulsweite für den Treiber meiner Tesla-Spule einzustellen – und grundsätzlich funktioniert das auch.

Das Problem:
Der Arduino läuft einwandfrei, solange er per USB am PC angeschlossen ist. Sobald ich jedoch eine externe Stromquelle verwende (z. B. ein Handy-Ladegerät über USB), startet der Arduino zwar normal, aber nach ein paar Sekunden scheint der Code zu „hängen“.

Meine aktuelle Hardware:

Arduino Mega

Kleines OLED-Display

Eine LED

Zwei Drehencoder zur Anpassung von Frequenz und Pulsweite

Was ich bereits ausprobiert habe:

Verschiedene USB-Netzteile (z. B. Handy-Ladegeräte) → Problem bleibt bestehen

Powerbank als Stromquelle → Gleiches Problem: Der Code läuft nur für einige Sekunden, dann hängt sich alles auf

Interessanterweise funktioniert es, wenn die Powerbank selbst am Netz hängt und ich den Arduino über die Powerbank betreibe

Mein Ziel ist es, das Ganze in ein 3D-gedrucktes Gehäuse zu packen, sodass der Interrupter portabel und unabhängig von einer Steckdose betrieben werden kann.

Hat jemand eine Idee, woran das liegen könnte oder wie ich das Problem beheben kann? Ich wäre für jede Hilfe dankbar!

Viele Grüße!

ChatGPT hat dir doch sicher ein Schaltbild geliefert, wie alles zusammengestellt ist. Zeige uns bitte das Schaltbild.

Das Einzige, was ich von ChatGPT wollte, war, dass er mir einen Code erstellt, der genau meinen Anforderungen entspricht. Das hat auch gut funktioniert – der Code tut genau das, was er soll. Das eigentliche Problem liegt woanders: Solange der Arduino am PC angeschlossen ist, läuft alles einwandfrei, aber sobald ich ihn an eine andere Stromquelle anschließe, funktioniert es nicht mehr richtig.

Falls es um die PIN-Belegung geht – ich habe dazu zwei Screenshots gemacht, die ich gerne zur Verfügung stelle.


Und genau die scheint nicht vollständig oder falsch zu sein.
Ein richtiges Schaltbild ist da deutlich aussagekräftiger.
Aber ich rate mal, es fehlt eine GND-Verbindung.
Dank fehlender Schaltung kann ich nicht sagen wo.

1 Like

So in etwa?

Wo ist die Teslaspule angeschlossen?

Da wo die Led ist kommt noch ein HFBR1414tz (LWL Sende modul) dazu. Und das wird dann mit einem lwl Kabel an meinen Treiber der DRSSTC angeschlossen.

Woher weißt du denn, dass der Code 'hängt'? Ich habe auch mal versucht, einen Controller mit einer Powerbank zu betreiben, das Problem war nur, dass die Schaltung zu wenig Strom gezogen hat, so dass der Regler der Powerbank die Last für zu gering hält und sich komplett abschaltet. Mit angeschlossener Stromversorgung hingegen powert die Powerbank durch.

Also wenn ich das Ganze über eine Powerbank oder ein Handyladegerät versuche, funktioniert der Arduino ein paar Sekunden, und dann kann ich mit den Encodern nichts mehr einstellen. Das Display bleibt so wie es ist, z. B. Freq: 450 Hz, Pulse: 100 µs. Ich kann aber nichts mehr verstellen, und der Ausgang am Pin 11 bleibt in der zuvor eingestellten Einstellung, also der „funktioniert“ noch.

Wie schließt du denn die externe Stromversorgung an? Direkt an den Pins (5V+GND), über den Rundstecker oder versuchst du, das Board über die USB-Schnittstelle mit Strom zu versorgen? Letzteres könnte vielleicht Probleme machen, wenn auf den RX/TX-Leitungen ggfs. Störimpulse übertragen werden. Ist aber nur eine Vermutung und ohne den Code kann man nicht ausschließen, dass die Ursache nicht doch im Programm selber liegt.

Das heißt nicht, dass er noch funktioniert.
Wenn der Controller hängt, funktioniert nichts mehr, auch Pin 11 nicht.

Meine Vermutung, die Schaltung ist nicht vollständig oder fehlerhaft.
Oder aber der geheime Sketch ist fehlerhaft.

Ich habe die Powerbank über die USB-Schnittstelle angeschlossen und habe es auch über den 5V-Pin und GND versucht; funktioniert nicht. Ich habe dann auch noch versucht, einen Kondensator zwischen 5V und GND zu hängen; ändert nichts.

Laut Oszilloskop habe ich Ausgang an Pin 11. Also, nach meinem Verständnis habe ich an Pin 11 noch das, was ich vorher eingestellt habe.

#include <Encoder.h>
#include <U8g2lib.h>
#include <avr/io.h>

// =======================================
// Pin-Definitionen
// =======================================
#define PIN_PWM_OUT       11   // Hardware-PWM-Ausgang (OC1A, Timer1)

// Frequenz-Encoder (Pins 2 & 3)
#define ENC_FREQ_A        2
#define ENC_FREQ_B        3
// Frequenz-Encoder-Button
#define PIN_FREQ_BUTTON   23   // Taster nach GND, INPUT_PULLUP

// Pulsweiten-Encoder (Pins 18 & 19)
#define ENC_PULSE_A       18
#define ENC_PULSE_B       19
// Pulsweiten-Encoder-Button
#define PIN_PULSE_BUTTON  24   // Taster nach GND, INPUT_PULLUP

// Separater Taster (Output an/aus)
#define PIN_TASTER        22   // Taster nach GND, INPUT_PULLUP

// =======================================
// Display (SSD1306, I2C)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);

// =======================================
// Encoder-Objekte
// =======================================
Encoder freqEncoder(ENC_FREQ_A, ENC_FREQ_B);
Encoder pulseEncoder(ENC_PULSE_A, ENC_PULSE_B);

// =======================================
// Einstellbare Parameter
// =======================================
// Frequenz: 30..1000 Hz, start=30
// Pulsweite: 0..400 us, start=0
volatile int frequency  = 30;
volatile int pulseWidth = 0;

// Letzte bekannte Encoder-Positionen
long lastFreqPos  = 0;
long lastPulsePos = 0;

// Accumulatoren (4 Flanken => 1 Rastung)
long freqAcc  = 0;
long pulseAcc = 0;

// Output an/aus (start=false)
bool outputEnabled = false;

// Kurze Meldung bei Umschalten
bool showOutputMsg     = false;
unsigned long msgUntil = 0;

// Taster-Abfrage
bool oldButtonState = true; // globaler Taster (Pin22)

// =======================================
// Timer1: Fast-PWM, ICR1=TOP, OCR1A=Duty
// =======================================
void updateTimer1(int freq, int pw_us);

// =======================================
// Splash-Screen (2,5 s)
// =======================================
void showSplashScreen() {
  unsigned long start = millis();
  while (millis() - start < 2500) {
    u8g2.firstPage();
    do {
      u8g2.setFont(u8g2_font_ncenB08_tr);
      const char* splash = "NG Interrupter";
      uint8_t w = u8g2.getStrWidth(splash);
      uint8_t x = (128 - w) / 2;
      u8g2.drawStr(x, 32, splash);
    } while(u8g2.nextPage());
  }
}

void setup() {
  pinMode(PIN_PWM_OUT, OUTPUT);
  digitalWrite(PIN_PWM_OUT, LOW);

  // Taster
  pinMode(PIN_TASTER,        INPUT_PULLUP); // Output on/off
  pinMode(PIN_FREQ_BUTTON,   INPUT_PULLUP); // Freq-Encoder push
  pinMode(PIN_PULSE_BUTTON,  INPUT_PULLUP); // Pulse-Encoder push

  // Serial.begin(9600);  <-- entfernt

  u8g2.begin();

  // Splash-Screen (2,5s)
  showSplashScreen();

  // Encoder-Startwerte
  lastFreqPos  = freqEncoder.read();
  lastPulsePos = pulseEncoder.read();

  // Timer1: Fast PWM, Mode=14
  TCCR1A = 0;
  TCCR1B = 0;
  // WGM13:1, WGM12:1, WGM11:1 => Mode=14
  TCCR1A |= (1 << WGM11);
  TCCR1B |= (1 << WGM12) | (1 << WGM13);

  // COM1A1=1 => non-inverting, wir starten AUS
  TCCR1A &= ~(1 << COM1A1);

  // Anfangswerte
  updateTimer1(frequency, pulseWidth);
}

void loop() {
  // --------------------------------------------
  // 1) Globaler Taster (Output an/aus)
  // --------------------------------------------
  bool currentButton = digitalRead(PIN_TASTER);
  if (oldButtonState == true && currentButton == false) {
    // Toggle
    outputEnabled = !outputEnabled;
    showOutputMsg = true;
    msgUntil      = millis() + 500;

    if (outputEnabled) {
      // PWM an
      TCCR1A |=  (1 << COM1A1);
      updateTimer1(frequency, pulseWidth);
      // Serial.println("OUTPUT: ON");  <-- entfernt
    } else {
      // PWM aus
      TCCR1A &= ~(1 << COM1A1);
      digitalWrite(PIN_PWM_OUT, LOW);
      // Serial.println("OUTPUT: OFF");  <-- entfernt
    }
  }
  oldButtonState = currentButton;

  // --------------------------------------------
  // 2) Frequenz-Encoder
  // --------------------------------------------
  {
    long newFreqPos = freqEncoder.read();
    // Invertierte Richtung => rawDeltaF = (lastFreqPos - newFreqPos)
    long rawDeltaF   = (lastFreqPos - newFreqPos);
    if (rawDeltaF != 0) {
      lastFreqPos = newFreqPos;
      freqAcc    += rawDeltaF;

      // => pro 4 Flanken => 1 Rastung
      while (freqAcc >= 4) {
        freqAcc -= 4;
        // Drückt man den Frequenz-Encoder?
        bool freqPressed = (digitalRead(PIN_FREQ_BUTTON) == LOW);
        // Schrittgröße: wenn gedrückt => 10, sonst => 1
        int step = freqPressed ? 10 : 1;
        frequency += step;
      }
      while (freqAcc <= -4) {
        freqAcc += 4;
        bool freqPressed = (digitalRead(PIN_FREQ_BUTTON) == LOW);
        int step = freqPressed ? 10 : 1;
        frequency -= step;
      }

      if (frequency < 30)   frequency = 30;
      if (frequency > 1000) frequency = 1000;

      if (outputEnabled) {
        updateTimer1(frequency, pulseWidth);
      }
      // Serial.print("Frequency => ");  <-- entfernt
      // Serial.println(frequency);      <-- entfernt
    }
  }

  // --------------------------------------------
  // 3) Pulsweiten-Encoder
  // --------------------------------------------
  {
    long newPulsePos = pulseEncoder.read();
    // Invertierte Richtung => rawDeltaP = (lastPulsePos - newPulsePos)
    long rawDeltaP   = (lastPulsePos - newPulsePos);
    if (rawDeltaP != 0) {
      lastPulsePos = newPulsePos;
      pulseAcc    += rawDeltaP;

      // => pro 4 Flanken => 1 Rastung
      while (pulseAcc >= 4) {
        pulseAcc -= 4;
        bool pulsePressed = (digitalRead(PIN_PULSE_BUTTON) == LOW);
        // Schrittgröße: wenn gedrückt => +5, sonst => +1
        int step = pulsePressed ? 5 : 1;
        pulseWidth += step;
      }
      while (pulseAcc <= -4) {
        pulseAcc += 4;
        bool pulsePressed = (digitalRead(PIN_PULSE_BUTTON) == LOW);
        int step = pulsePressed ? 5 : 1;
        pulseWidth -= step;
      }

      if (pulseWidth < 0)   pulseWidth = 0;
      if (pulseWidth > 400) pulseWidth = 400;

      if (outputEnabled) {
        updateTimer1(frequency, pulseWidth);
      }
      // Serial.print("Pulse => ");   <-- entfernt
      // Serial.println(pulseWidth);   <-- entfernt
    }
  }

  // --------------------------------------------
  // 4) Display
  // --------------------------------------------
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB08_tr);

    // Zeile 1: Frequenz
    char buf[24];
    sprintf(buf, "Freq: %d Hz", frequency);
    uint8_t w = u8g2.getStrWidth(buf);
    uint8_t x = (128 - w) / 2;
    u8g2.drawStr(x, 12, buf);

    // Zeile 2: Pulsweite
    sprintf(buf, "Pulse: %d us", pulseWidth);
    w = u8g2.getStrWidth(buf);
    x = (128 - w) / 2;
    u8g2.drawStr(x, 28, buf);

    // Zeile 3: OUTPUT: ON/OFF Meldung
    if (showOutputMsg) {
      const char* outText = outputEnabled ? "OUTPUT: ON" : "OUTPUT: OFF";
      w = u8g2.getStrWidth(outText);
      x = (128 - w) / 2;
      u8g2.drawStr(x, 44, outText);
    }

  } while(u8g2.nextPage());

  // Meldung ausblenden nach 0,5 s
  if (showOutputMsg && (millis() > msgUntil)) {
    showOutputMsg = false;
  }

  // Kein Encoder-Delay => loop() läuft schnell
  delay(5);
}

// =======================================
// Timer1-Update
// =======================================
void updateTimer1(int freq, int pw_us) {
  if (!outputEnabled) {
    digitalWrite(PIN_PWM_OUT, LOW);
    return;
  }
  if (freq < 30)   freq = 30;
  if (freq > 1000) freq = 1000;
  if (pw_us < 0)   pw_us = 0;
  if (pw_us > 400) pw_us = 400;

  unsigned long period_us = 1000000UL / freq;
  byte prescalers[5] = {1, 8, 64, 256, 1024};
  byte chosenPrescaler = 1;
  unsigned long top = 0;

  for (int i = 0; i < 5; i++) {
    unsigned long ps = prescalers[i];
    unsigned long t  = period_us * (F_CPU / ps / 1000000UL);
    if (t <= 65535UL) {
      chosenPrescaler = ps;
      top = t;
      break;
    }
  }
  if (top == 0) {
    chosenPrescaler = 1024;
    top = 65535UL;
  }

  ICR1 = (uint16_t) top;

  unsigned long pw_ticks = pw_us * (F_CPU / chosenPrescaler / 1000000UL);
  if (pw_ticks > top) {
    pw_ticks = top;
  }
  OCR1A = (uint16_t) pw_ticks;

  // Prescaler bits
  TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10));
  switch(chosenPrescaler) {
    case 1:    TCCR1B |= (1 << CS10); break;
    case 8:    TCCR1B |= (1 << CS11); break;
    case 64:   TCCR1B |= (1 << CS11) | (1 << CS10); break;
    case 256:  TCCR1B |= (1 << CS12); break;
    case 1024: TCCR1B |= (1 << CS12) | (1 << CS10); break;
  }
}

Das heißt immer noch nicht, dass dieser Pin noch funktioniert.
Der Controller hängt und dann macht der Pin nix mehr.
Da ich aktuell an der Schaltung keinen Fehler erkennen kann, solltest du den Sketch debuggen und dazu einige serielle Eingaben einsetzen, mit den der Absturz dokumentiert werden kann.

Also für meinen Geschmack hast du da einige Schleifen drin, wo sich dein Programm 'verirren' kann. Vor allem die Schleifen für die Anzeigen verstehe ich nicht so wirklich, warum arbeitest du da mit firstPage und nextPage? Und warum der Loop darum? Im Loop() brauchst du auch nur die Anzeige refreshen, wenn sich etwas geändert hat und nicht bei jedem Durchlauf? Und die Schleifen für die Pulsweitenberechnung sehen mir auch was kompliziert aus. Hier mein schneller Vorschlag nach überfliegen von deinem Code (ohne das jetzt selber auscodiert und getestet zu haben):

//den Ablauf
pulseAcc    += rawDeltaP;

// => pro 4 Flanken => 1 Rastung
while (pulseAcc >= 4) {
	pulseAcc -= 4;
	bool pulsePressed = (digitalRead(PIN_PULSE_BUTTON) == LOW);
	// Schrittgröße: wenn gedrückt => +5, sonst => +1
	int step = pulsePressed ? 5 : 1;
	pulseWidth += step;
}
while (pulseAcc <= -4) {
	pulseAcc += 4;
	bool pulsePressed = (digitalRead(PIN_PULSE_BUTTON) == LOW);
	int step = pulsePressed ? 5 : 1;
	pulseWidth -= step;
}


//durch den ersetzen
int faktor = rawDeltaP / 4;
int step = (digitalRead(PIN_PULSE_BUTTON) == LOW) ? 5 : 1;
pulseWidth += faktor * step;
//den Ablauf
u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB08_tr);

    // Zeile 1: Frequenz
    char buf[24];
    sprintf(buf, "Freq: %d Hz", frequency);
    uint8_t w = u8g2.getStrWidth(buf);
    uint8_t x = (128 - w) / 2;
    u8g2.drawStr(x, 12, buf);

    // Zeile 2: Pulsweite
    sprintf(buf, "Pulse: %d us", pulseWidth);
    w = u8g2.getStrWidth(buf);
    x = (128 - w) / 2;
    u8g2.drawStr(x, 28, buf);

    // Zeile 3: OUTPUT: ON/OFF Meldung
    if (showOutputMsg) {
      const char* outText = outputEnabled ? "OUTPUT: ON" : "OUTPUT: OFF";
      w = u8g2.getStrWidth(outText);
      x = (128 - w) / 2;
      u8g2.drawStr(x, 44, outText);
    }

  } while(u8g2.nextPage());

//durch den ersetzen, könnte aber flackern des Displays verursachen
//wenn das wirklich bei jedem Loop ausgeführt wird
	u8g2.clearBuffer();
	u8g2.setFont(u8g2_font_ncenB08_tr);

	// Zeile 1: Frequenz
	char buf[24];
	sprintf(buf, "Freq: %d Hz", frequency);
	uint8_t w = u8g2.getStrWidth(buf);
	uint8_t x = (128 - w) / 2;
	u8g2.drawStr(x, 12, buf);

	// Zeile 2: Pulsweite
	sprintf(buf, "Pulse: %d us", pulseWidth);
	w = u8g2.getStrWidth(buf);
	x = (128 - w) / 2;
	u8g2.drawStr(x, 28, buf);

	// Zeile 3: OUTPUT: ON/OFF Meldung
	if (showOutputMsg) {
	  const char* outText = outputEnabled ? "OUTPUT: ON" : "OUTPUT: OFF";
	  w = u8g2.getStrWidth(outText);
	  x = (128 - w) / 2;
	  u8g2.drawStr(x, 44, outText);
	}
	u8g2.sendBuffer();
}

Problem gelöst:

Ursache war anscheinend, dass sowohl die Powerbank als auch das USB-Ladegerät eine Mindestlast benötigen, um stabil Strom zu liefern. Der Arduino allein zieht nicht genug Strom, wodurch es zu Ausfällen kam.

Durch das Parallelschalten von drei 47-Ohm-Widerständen zwischen 5V und Ground wurde die Last erhöht (ca. 300mA), und jetzt läuft alles stabil. Arduino seit 20 Minuten ohne Ausfall in Betrieb.

Dann hast du uns aber falsche Informationen geliefert.
Wenn die Powerbank abschaltet, muss auch der Controller ausgeschaltet (spannungslos) sein. Somit muss da noch ein anderes Problem sein.

Das hatte ich ja in Post #8 schon erwähnt, aber du hast darauf geantwortet, das das Display so bleibt wie es ist. Hat das dann eine eigene Stromversorgung oder war das dann nur ein Mißverständnis? Glühen die Widerstände noch nicht? Die alleine verbraten ja zusammen schon rein rechnerisch 1,5 W, dann sollten die jeweils mindestens für 0,5W ausgelegt sein, besser 1W

Naja, sieh es mal so:
Wenn man bei der Technik kalte Füße bekommt, baut man sich eine Heizung ein. :wink:
Ich kann da beim TO noch einiges an Lernpotential erkennen.