Variable in einem Inerrupt wird nicht verarbeitet

Hallo zusammen,

ich schreibe grade ein Programm zur schnellen Messung von 4 Spannungen.

Scheinbar funktionier dies auch. Jedoch bin ich beim Erweitern auf ein Problem gestoße. In der Zeile 350:

if (MessEingang == 0) { ...

scheint das Programm nicht zu verzweigen. Ein Versuch zum Debuggen (Zeile 351):

FloatRMSTemp[3] = FloatRMSCounter+200;

bringt nicht die gewünschte Anzeige im Display. Hier sollten Werte zwischen 200 und 203 angezeigt werden. Wenn ich direkt vor das “if” die Variable “MessEingang” = 0 setze funktioniert es.

Nun eine Kurze beschreibung:

Loop ==> Ausgabe der Variablen PeakTemp, MaxTemp und FloatRMSTemp auf dem Display

MessenIRQ ==> Abfrage der Messwerte und Aufbereitung.

Und hier nun der komplette Code:

#include <EEPROM.h>
#include <TimerOne.h>
//*******************************************************************************************************************************
//*                                                                                                                             *
//*    Programmbeschreibung : Das Programm dient zur Messung von 4 Spannungen zwischen 0 und 10 V                               *
//*                           Die Werte werden in einstellbare Göße umgerechnet und zur Anzeige gebracht                        *
//*                           In der Anzeige stehen RMS, peek und Maxhold zur Verfügung                                         *
//*                           Jerder Eingang wird alle (4x60µs) 240µs abgefragt                                                 *
//*                                                                                                                             *
//*                                                                                                                             *
//*    Lauffähig auf        : Arduino Nano                                                                                      *
//*                                                                                                                             *
byte   Version              = 1;//  V0.02                                                                                       *
//*    Autor                : Peter Luckner-Piecha                                                                              *
//*    Letzt Änderung       : 2025-03-06                                                                                        *
//*    Letzt Änderung       : 2025-09-01 div. Korrekturen, FloatRMS                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*                                                                                                                             *
//*******************************************************************************************************************************

// Variablen für Timing *********************************************************************************************************
unsigned long DisplayTimerLetzterDurchlauf      =    0;
unsigned long DisplayTimerSystemzeit            =    0;
unsigned long DisplayTimerInterval_ms           =  100;           // Ausgabe und Tastaturabfrage alle 500ms
unsigned long MessTimerZeit                     =   300075;           // Messen alle 68µs. 245µs OK, in "alter" Version (AnalogRead); 1 X Analog Read 130µs ==> AnalogRead dauert 115µs!!
// ------------------------------------------------------------------------------------------------------------------------------
// Variablen für Messwerterfassung **********************************************************************************************
const uint16_t ADCPreScale                      = B101;           //ADPS:  ADC Prescaler Select Bits 000 > 2, 001 > 2, 010 > 4, 011 > 8, 100 > 16, 101 > 32; 110 Y 64; 111 > 128
const uint16_t MessEingangEcht[4]               = {0,2,4,6};      // AD-In 0,2,4 & 6
volatile uint8_t  MessEingang                   = 0;              // Enthält die Messung (Eingang), welche der ADC grade bearbeitet
volatile uint8_t  MessEingangTemp               = 0;              // Enthält die Messung (Eingang), welche grade weiter bearbeitet wird
volatile uint16_t MessWert[4]                   = {0,0,0,0};      // Enthält den Messwert direkt nach dem Auslese aus dem ADC, Dieser wird mit Max und Peak verglichen, sowie zum Errechnen vom RMS benutzt
// ------------------------------------------------------------------------------------------------------------------------------
// FloatRMS-Bildung .............................................................................................................
const uint16_t  FloatRMS                        =   16;             // Zähler für Floating RMS (Werte von 0 bis Wert-1 ==> 16 ==> 0 bis 15)
volatile uint16_t  FloatRMSSpeicher[4][16];                         // Achtung Array-Größe an FloatRMS anpassen 
volatile uint16_t  FloatRMSCounter              =    0;             // Counter für aktuellen Wert
volatile uint16_t  FloatRMSCounterAlt           =    0;             // Counter für den ältesten Wert
volatile long FloatRMSTemp[4]                   = {0,0,0,0};        // Summe aller Messungen für RMS Berechnung
volatile long FloatRMSWert[4]                   = {0,0,0,0};        // Zwischenspeicher RMS vor der umrechnung auf Float
float RMSWert[4]                                = {0,0,0,0};        // Ergebnis nach Umrechnung, zur Ausgabe auf display

// ------------------------------------------------------------------------------------------------------------------------------
volatile long  PeakTemp[4]                      = {0,0,0,0};             
float Peak[4]                                   = {0,0,0,0};

volatile long  MaxTemp[4]                       = {0,0,0,0};
float Max[4]                                    = {0,0,0,0};
// ------------------------------------------------------------------------------------------------------------------------------
// Variablen für Display ********************************************************************************************************
char DisplayZeile[4][21] = {"01234567890123456789","abcdefghijklmnopqrst","ABCDEFGHIJKLMNOPQRST","01234567890123456789"}; //Text nach Start festlegen
int  CounterZeile     = 0;
// ------------------------------------------------------------------------------------------------------------------------------

// Variablen für die Einstellungen **********************************************************************************************
uint8_t  EichWert[4]         = {20,22,20,21};                              // gemessen ohne Cal {10,0; 9,98; 10,0; 9,99}
const int EichGrundwert      = 980;
//                             -  0  ,-  1  ,-  2  ,-  3  ,-  4  ,-  5  ,-  6  ,-  7  ,-  8  ,-  9  ,- 10  ,- 11  ,- 12  ,- 13  ,- 14  ,- 15  ,- 16  ,
char  MessBereicheStr[16][5] = {"2.00","2.50","5.00","10.0","12.0","15.0","20.0","50.0","100.","200.","250.","500.","1000","1200","2000","5000"}; // Verfügbare Einstellungen bei 10V zur Zeit 16 Einstellmöglichkeiten
float MessBereiche[16]       = { 2    , 2.5  , 5    , 10   , 12   , 15   , 20   , 50   , 100  , 200  , 250  , 500  , 1000 , 1200 , 2000 , 5000 };
uint8_t  MessBereich[5]      = {   3,   3,   3,   3,   0};                 // Eingestellter Angezeigter Wert bei 10V Eingangsspannung
char  MessEinheitenStr[6][3] = {"mV"," V","kV","mA"," A", "kA"};           // Verfügbare Einheiten für Messungen
uint8_t  MessEinheit[5]      = {  4 ,  4 ,  4 ,  4 ,  0 };
char  MessEinheitStr[8][3]   = {" V","mA","kV"," A","  ","  ","  ","  "};  // Eingestellte Einheit der Messung
char  adj[7]                 = " adj. ";                                   // Text für Einstellung
int   PosEinstellungBereich  = 0;
int   PosEinstellungEinheit  = 0;


const byte Normal            = 0;
const byte Grundeinstellung  = 1;
const byte Eichen            = 2;
byte  BetriebsMode           = Normal;


// Variablen für Tastaturabfrage ************************************************************************************************
//byte TastaturCounter = 0;
boolean NeueEingabe    = true;
byte TempTaste         = 0;
byte Taste             = 0;
int TasteZeit          = 0;
// Variablen EEPROM *************************************************************************************************************
int EEPROMSpeicherPlatz = 0;
// Allgemeine Variablen *********************************************************************************************************
byte TempByte          = 0;
int Temp               = 0;
// ------------------------------------------------------------------------------------------------------------------------------
String TempString      = "";


void setup() {
  noInterrupts();
  
  // Ports setzen
  DDRD = B11111111;  // Datenbus auf Ausgang
  PORTD = B00000000; // Daten = 0
  DDRB = B00001111;  // RS, R/W, E1, E2 auf Ausgang, (Bit 5) Eingang für Tastatur
  PORTB = B00000000; // Steuerleitungen = 0
  DDRC = B00000000;  // Port C 
  // Variablen setzen
  // 1. Ausgabe auf dem Display *************************************************************************************************
  strcpy(DisplayZeile[0], "01234567890123456789"); strcpy(DisplayZeile[1], "abcdefghijklmnopqrst"); strcpy(DisplayZeile[2], "ABCDEFGHIJKLMNOPQRST"); strcpy(DisplayZeile[3], "01234567890123456789");
  EinstellungenLaden();
  strcpy(MessEinheitStr[0],MessEinheitenStr[MessEinheit[0]]); strcpy(MessEinheitStr[1],MessEinheitenStr[MessEinheit[1]]); strcpy(MessEinheitStr[2],MessEinheitenStr[MessEinheit[2]]); strcpy(MessEinheitStr[3],MessEinheitenStr[MessEinheit[3]]);
  //analogReference(INTERNAL); 	// INTERNAL = 3; DEFAULT = 1; EXTERNAL = 0
  // Einstellungen aus EEPORM lesen
  // ADC einstellen
  // Arrays löschen
  DisplayReset();
  // IRQ-Timer vorbereiten ******************************************************************************************************
  Timer1.initialize(MessTimerZeit);
  Timer1.attachInterrupt(MessenIRQ);
  ADCReset();
  delay(40);
  // AD-Wandler vorbereiten *****************************************************************************************************
  AufDisplayAusgeben();

  MaxTempReset();
  ClearFloatRMSSpeicher();
  DisplayTimerLetzterDurchlauf    = millis();
  //cls();
  interrupts();
  
}

void loop() {
  // Daten auf Display ausgeben *************************************************************************************************
  
  DisplayTimerSystemzeit   = millis();
  if (DisplayTimerSystemzeit - DisplayTimerLetzterDurchlauf >= DisplayTimerInterval_ms ) { // DisplayTimerZeit = Interval ( alle 100ms)
    DisplayTimerLetzterDurchlauf    = millis();
    switch (BetriebsMode) {
      case Grundeinstellung:
        EinstellungenZusammenstellen();
      break;
      case Eichen:
        MessBereich[0] = 3;MessBereich[1] = 3;MessBereich[2] = 3;MessBereich[3] = 3;
        for (int Counter = 0; Counter < 4; Counter++) {
          RMSWert[Counter] = Skaliere(FloatRMSWert[Counter], Counter);
          EichenZusammenstellen(Counter);
        }
      break;
      case Normal:
        for (int Counter = 0; Counter < 4; Counter++) {
          RMSWert[Counter] = Skaliere(FloatRMSWert[Counter], Counter);
          Peak[Counter]    = Skaliere(PeakTemp[Counter], Counter);
          Max[Counter]     = Skaliere(MaxTemp[Counter], Counter);
          MesswerteZusammenstellen(Counter);
        }
      break;
    }
    AufDisplayAusgeben();
    // Peakmessung reduzieren, -2% nach der Ausgabe auf dem Display ************************************************************
    for(int Counter =0; Counter < 4; Counter++){PeakTemp[Counter] = PeakTemp[Counter]*98/100;}

    // Tastatur abfragen********* ***********************************************************************************************
    //Taste = 0;
    TempTaste = 0;
    PORTD = B00000001;
    for (byte TastaturCounter = 1; TastaturCounter < 8;TastaturCounter++){
      do{
        TempByte = PINB & B00100000;
      } while (TempByte != (PINB & B00100000));
      TempByte = TempByte << 2;
      TempTaste = TempTaste | TempByte;
      TempTaste = TempTaste >> 1;
      PORTD = B00000001 << TastaturCounter;
    }
    if (TempTaste > 0){
      if (TasteZeit <1){Taste = TempTaste;     TasteZeit = TasteZeit + DisplayTimerInterval_ms/100; } 
      else             {if (TempTaste == Taste){TasteZeit = TasteZeit + DisplayTimerInterval_ms/100; } }
      Taste = TempTaste;
    }
    else {TasteZeit = 0; Taste = 0; TempTaste = 0; NeueEingabe = true;}
    // Taste Links         >  2 s ==> Grundeinstellungen (Messbereich, Einheit); Taste Mitte ==> Wählen; Taste Rechts ==> Speichern
    // Taste Links & Mitte > 10 s ==> Eichen (bei Eingang 10V, Anzeige = 10V)  ; Taste Mitte ==> Wählen; Taste Rechts ==> Speichern
    // Taste Rechts        >  3 s ==> MaxHold zurück setzen
    if (NeueEingabe){
      switch (Taste) {
        case 1:
    // Test Grundeinstellungen an - nächste Enstellung ***************************************************************************

          switch (BetriebsMode) { 
            case Grundeinstellung:         // Grundeinstellungen durchführen - nächste Einstellung
              NeueEingabe = false;
              if(PosEinstellungEinheit & 0x0004){
                PosEinstellungEinheit &= 0x0003; PosEinstellungBereich |= 0x0004;
              }
              else{
                PosEinstellungEinheit &= 0x0003; PosEinstellungEinheit ++;if (PosEinstellungEinheit > 3){PosEinstellungEinheit = 0;} PosEinstellungEinheit |= 0x0004;
                PosEinstellungBereich &= 0x0003; PosEinstellungBereich ++;if (PosEinstellungBereich > 3){PosEinstellungBereich = 0;}               
              }
            break;
            case Normal:                   // Keine Einstellung - nach 2s in Mode Grundeinstellung schalten
              if(TasteZeit > 20) {
                NeueEingabe = false;
                BetriebsMode = Grundeinstellung;
                PosEinstellungBereich = 0;
                PosEinstellungEinheit = 4;
              }
            break;
            }  
          break;
        case 2:
    // Test Grundeinstellungen aus ***********************************************************************************************
          switch (BetriebsMode) {
            case Grundeinstellung:             // Grundeinstellungen durchführen
              NeueEingabe = false;
              if(PosEinstellungBereich <4){     // Messbereich einstellen
                MessBereich[PosEinstellungBereich]++; if(MessBereich[PosEinstellungBereich] > 15){MessBereich[PosEinstellungBereich]=0;}
              }
              if(PosEinstellungEinheit <4){     // Einheiten einstellen
                MessEinheit[PosEinstellungEinheit]++; if(MessEinheit[PosEinstellungEinheit] >  5){MessEinheit[PosEinstellungEinheit]=0;}
                MessEinheitStr[PosEinstellungEinheit][0] = MessEinheitenStr[MessEinheit[PosEinstellungEinheit]][0];
                MessEinheitStr[PosEinstellungEinheit][1] = MessEinheitenStr[MessEinheit[PosEinstellungEinheit]][1];
              }
            break;
          }
        break;
        case 3:
    // Statement(s)
          switch (BetriebsMode){
            case Normal:
              if(TasteZeit > 100) {
                NeueEingabe = false;
                BetriebsMode = Eichen;
              }            
            break;
          }
        break;
        case 4:
    // Einstellungen Speichern ***************************************************************************************************
          switch (BetriebsMode) {
            case Grundeinstellung:           // Grundeinstellungen verlassen und Daten speichern
              NeueEingabe = false;
              EinstellungenSpeichern();       //Daten in EEPROM schreiben
              BetriebsMode = Normal;
            break;
            case Eichen:
              NeueEingabe = false;
              EinstellungenSpeichern();       //Daten in EEPROM schreiben
              BetriebsMode = Normal;
            break;
            case Normal:                    // Reset MaxTemp bei Taste Rechts länger 3s 
              if(TasteZeit > 30) {
                NeueEingabe = false;
                MaxTempReset();
              }
            break;
          }
        break;
        case 5:
    // Statement(s)
        break;
        case 6:
    // Statement(s)
        break;
        case 7:
    // Statement(s)
        break;
        default:
    // Statement(s)
        break; // Wird nicht benötigt, wenn Statement(s) vorhanden sind
      }
    }

    PORTD = B00000000;
  }
  
  // ----------------------------------------------------------------------------------------------------------------------------

}



// Display +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Display reset ****************************************************************************************************************
void DisplayReset(){
  DisplaySchreibeRegister (0x38);// B0011 1000 Function Set     8 Bit; 2 Zeilen; 5x8
  DisplaySchreibeRegister (0x39);// B0011 1001 Function Set     8 Bit; 2 Zeilen; 5x8; instruction table select
  DisplaySchreibeRegister (0x14);// B0001 0100 Frequenz         Wert aus Datenblatt für 5V
  DisplaySchreibeRegister (0x79);// B0111 1001 Contrast set     Wert aus Datenblatt für 5V
  DisplaySchreibeRegister (0x50);// B0101 0000 Power/ICON       Wert aus Datenblatt für 5V
  DisplaySchreibeRegister (0x6C);// B0110 1100 Follower control Wert aus Datenblatt für 5V 
  DisplaySchreibeRegister (0x0C);// B0000 1100                  Display On; Curser Off; Blink Off
  DisplaySchreibeRegister (0x01);// B0000 0001 Clear Display
  delay( 1);
}
void DisplaySchreibeRegister(byte Daten) { //  RS und R/W sind L
  PORTB |= B00000011; // E1 & E2 auf H
  delayMicroseconds(1); // ev unnötig
  PORTD = Daten; // Daten Schreiben
  delayMicroseconds(40); // ev unnötig
  PORTB &= B11111100; // E1 & E2 auf L
}
// ------------------------------------------------------------------------------------------------------------------------------
// Display Zeichen Schreiben ****************************************************************************************************
void DisplaySchreibeZeichen(char Zeichen){
  PORTB |= B00001000; // RS auf H       (H:Data.L:Instruction code)
  PORTB |= B00001011; // E1 & E2 auf H
  PORTD = Zeichen; // Zeichen; //Zeichen; // Daten Schreiben
  delayMicroseconds(40); 
  PORTB &= B11111100; // E1 & E2 auf L
}
// Display Zeile Schreiben ******************************************************************************************************
void AufDisplayAusgeben(){
  for (byte Zeichen = 0; Zeichen < 20; Zeichen++){ DisplaySchreibeZeichen(DisplayZeile[0][Zeichen]); }
  for (byte Zeichen = 0; Zeichen < 20; Zeichen++){ DisplaySchreibeZeichen(DisplayZeile[2][Zeichen]); }
  for (byte Zeichen = 0; Zeichen < 20; Zeichen++){ DisplaySchreibeZeichen(DisplayZeile[1][Zeichen]); }
  for (byte Zeichen = 0; Zeichen < 20; Zeichen++){ DisplaySchreibeZeichen(DisplayZeile[3][Zeichen]); }
}
// ------------------------------------------------------------------------------------------------------------------------------
//  Messen +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// IRQ-für Messungen ************************************************************************************************************
void MessenIRQ(void){
  noInterrupts();
  // Messungen durchführen ******************************************************************************************************
  // Die Messungen der 4 Spannungen werden nacheinander durchgeführt. Das "Durchschalten" übernimmt der "MessEingang" 0 bis 3
  // Da direkt nach dem auslesen des Messwertes auf den nächsten Eingang geschaltet wird, wir der derzeit zu messende Kanal
  // in MessEingangTemp gespeichert.
  MessEingangTemp = MessEingang;                                        // MessEingangTemt = Aktuelle Messung
  MessEingang++; if(MessEingang > 3){MessEingang = 0;FloatRMSTemp[1] = MessEingang + 880;}                  // Auf nächsten Eingang schalten. MessEingang steht nun auf dem als nächstes zu messenden Kanal
  // ADCs auslesen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  MessWert[MessEingangTemp] = ADCRead();                                // Aktuellen Messwert auslesen (0)
  ADCStart(MessEingangEcht[MessEingang]);                               // Auf nächsten Kanal schalten, und Neue Messung starten

  // Peak detekt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  if (MessWert[MessEingangTemp] > PeakTemp[MessEingangTemp]) {PeakTemp[MessEingangTemp] = MessWert[MessEingangTemp];}

  // Max detekt +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  if (MessWert[MessEingangTemp] >  MaxTemp[MessEingangTemp]) { MaxTemp[MessEingangTemp] = MessWert[MessEingangTemp];}
  // FloatRMS ...................................................................................................................
  FloatRMSCounterAlt = FloatRMSCounter+(FloatRMS-1); if (FloatRMSCounterAlt > FloatRMS-1) {FloatRMSCounterAlt = FloatRMSCounterAlt-FloatRMS;}   //Position des Alten Wertes berechnen  
  FloatRMSSpeicher[MessEingangTemp][FloatRMSCounter] = MessWert[MessEingangTemp];                                                               // Aktuellen Messwert in Array speichern
  FloatRMSTemp[MessEingangTemp] = FloatRMSTemp[MessEingangTemp] - FloatRMSSpeicher[MessEingangTemp][FloatRMSCounterAlt];                        // Alten Messwert von RMSwert (Summe aus "allen Messungen") abziehen
  FloatRMSTemp[MessEingangTemp] = FloatRMSTemp[MessEingangTemp] + MessWert[MessEingangTemp];                                                    // Neuen Messwert zu RMSwert (Summe aus "allen Messungen") addieren

  FloatRMSWert[MessEingangTemp] = FloatRMSTemp[MessEingangTemp] / 1;//FloatRMS;                                                                 // RMSwert (Summe aus "allen Messungen") durch anzahl der Messungen teilen
    FloatRMSTemp[2] = MessEingang + 100;
    FloatRMSTemp[3] = MessEingangTemp +100;
  if (MessEingang == 0) {     
    FloatRMSTemp[3] = FloatRMSCounter+200;                                                                                                      // Wenn der gestartete Messeingang = 0 ist, dann wir der
    FloatRMSCounter++;
    if (FloatRMSCounter > 15) {
      FloatRMSCounter = 0;
      FloatRMSTemp[3] = FloatRMSCounter+400;}                                                  // FoatCounter auf nächsten Speicheplatz gestellt
  }
  // ----------------------------------------------------------------------------------------------------------------------------
  interrupts();
}
// Messwerte für Anzeige zusammenstellen ****************************************************************************************
void MesswerteZusammenstellen(byte Messwert){
  TempString =  String(RMSWert[Messwert], 3);
  for(byte Counter =  0; Counter <  4; Counter++){DisplayZeile[Messwert] [Counter] = TempString[Counter];}
  for(byte Counter =  4; Counter <  6; Counter++){DisplayZeile[Messwert] [Counter] = MessEinheitStr[Messwert][Counter-4];}
  for(byte Counter =  6; Counter <  7; Counter++){DisplayZeile[Messwert] [Counter] = 32;}
  TempString =  String(Peak[Messwert], 3);
  for(byte Counter =  7; Counter < 11; Counter++){DisplayZeile[Messwert] [Counter] = TempString[Counter-7];}
  for(byte Counter = 11; Counter < 13; Counter++){DisplayZeile[Messwert] [Counter] = MessEinheitStr[Messwert][Counter-11];}
  for(byte Counter = 13; Counter < 14; Counter++){DisplayZeile[Messwert] [Counter] = 32;}
  TempString =  String(Max[Messwert], 3);
  for(byte Counter = 14; Counter < 18; Counter++){DisplayZeile[Messwert] [Counter] = TempString[Counter-14];}
  for(byte Counter = 18; Counter < 20; Counter++){DisplayZeile[Messwert] [Counter] = MessEinheitStr[Messwert][Counter-18];}
  //DisplayZeile[Messwert][19] = 32;
}
void ADCReset(){
  ADCSRA = B00000000;
  ADCSRB = B00000000;     // 7      ==> [z]           keine Funktion
                          // 6      ==> [z]    ACME:  analog comparator multiplexer enable bit
                          // 5 - 3  ==> [0]           keine Funktion
                          // 2 - 0  ==> [zzz]  ADTS:  ADC Auto Trigger Source   000 > free Running,       001 > Analog comperator
  
  ADCSRA = B00000000 | ADCPreScale;     // Presacalor = 32 ==> 0,5MHz Siehe Deklaration.
                          // 7      ==> [1]    ADEN:  ADC anable; 
                          // 6      ==> [1]    ADSC:  ADC Start Conversion
                          // 5      ==> [0]    ADATE: ADC Auto Trigger Enable     1 ==> Freerun, 0 ==> Einzelmessung
                          // 4      ==> [0]    ADIF:  ADC Interrupt Flag
                          // 3      ==> [0]    ADIE:  ADC Interrupt Enable
                          // 2 - 0  ==> [101]  ADPS:  ADC Prescaler Select Bits 000 > 2, 001 > 2, 010 > 4, 011 > 8, 100 > 16, 101 > 32; 110 Y 64; 111 > 128
  ADMUX  = B00000000;
  ADMUX  = B11000000;     // Ref = 1.1V; Ausgabe rechtsbündig; Eingang 0
                          // 7, 6   ==> [11]   INTERNAL = 3; DEFAULT = 1; EXTERNAL = 0
                          // 5      ==> [0]    ADLAR: ADC Left Adjust Result
                          // 4      ==> [0]           keine Funktion
                          // 3 - 0  ==> [xxxx] MUX 0 - 7, 14 ==> 1,1V, 15 ==> GND
  MaxTemp[3]=ADMUX;                          
}
void ADCStart(byte Eingang){
  ADCSRA = ADCPreScale;               // ADC off & Halt
  ADMUX  = B11000000 | Eingang;       // Eingang setzen
  ADCSRA = ADCPreScale | B11000000;   // ADC an & Start
  //MaxTemp[0]=ADCSRA;
} 
int ADCRead(){ //int ADCWert
  //ADCWert = 0;
  while (bit_is_set(ADCSRA, ADSC));
  return ADCW;//ert;
}
void MaxTempReset(){
  MaxTemp[0] = 0;
  MaxTemp[1] = 0;
  MaxTemp[2] = 0;
  MaxTemp[3] = 0;
}
// in float wandeln, Auf Endwert scalieren und "Eichen" (Eingangsspannungsteiler) ***********************************************
float Skaliere(float messung, int Kanal) {
  float temp   = 0; 
  float result = 0;
  temp = messung * MessBereiche[MessBereich[Kanal]] * (EichGrundwert + EichWert[Kanal]) /1000; 
  result = temp /1000;
  return result;
}
void ClearFloatRMSSpeicher(){
  
  for(uint16_t Counter1 = 0; Counter1 < 4; Counter1++){
    for(uint16_t Counter2 = 0; Counter2 < FloatRMS; Counter2++){FloatRMSSpeicher[Counter1][Counter2] = 0;}
  }
}
//  Einstellungen +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void EinstellungenZusammenstellen(){
//DisplayZeile[Zeile] [Stelle]

  for (int CounterZeile = 0;CounterZeile <4;CounterZeile++){
    if(PosEinstellungBereich == CounterZeile) { for (byte Counter =  0; Counter <   6; Counter++){DisplayZeile[CounterZeile][Counter] = adj[Counter-00];} }
    else                                      { for (byte Counter =  0; Counter <   6; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;}         }
    for                                             (byte Counter =  6; Counter <  10; Counter++){DisplayZeile[CounterZeile][Counter] = MessBereicheStr[MessBereich[CounterZeile]][Counter- 6];}
    if(PosEinstellungEinheit == CounterZeile) { for (byte Counter = 10; Counter <  16; Counter++){DisplayZeile[CounterZeile][Counter] = adj[Counter-10];} }
    else                                      { for (byte Counter = 10; Counter <  16; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;}         }
    for                                             (byte Counter = 16; Counter <  18; Counter++){DisplayZeile[CounterZeile][Counter] = MessEinheitStr[CounterZeile][Counter-16];}
    for                                             (byte Counter = 18; Counter <  19; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;} //MessBereich[CounterZeile] + 0x30;}
    for                                             (byte Counter = 19; Counter <  20; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;} //Version + 0x30;} //MessBereich[CounterZeile] + 0x30;}    
  }
}
void EinstellungenSpeichern(){
  EEPROMSpeicherPlatz = 0;
  EEPROM.update(EEPROMSpeicherPlatz, Version);EEPROMSpeicherPlatz++;
  for(int Counter = 0; Counter < 4; Counter++){
    EEPROM.update(EEPROMSpeicherPlatz    , MessBereich[Counter]);
    EEPROM.update(EEPROMSpeicherPlatz + 4, MessEinheit[Counter]);
    EEPROMSpeicherPlatz++;
  }
  EEPROMSpeicherPlatz = EEPROMSpeicherPlatz + 4;
}
void EinstellungenLaden(){
  EEPROMSpeicherPlatz = 0;
  Version = EEPROM.read(EEPROMSpeicherPlatz);EEPROMSpeicherPlatz++;
  if (Version > 0) {
    for(int Counter = 0; Counter < 4; Counter++){
      MessBereich[Counter] = EEPROM.read(EEPROMSpeicherPlatz    );
      MessEinheit[Counter] = EEPROM.read(EEPROMSpeicherPlatz + 4);
      EEPROMSpeicherPlatz++;
    }
  }
  EEPROMSpeicherPlatz = EEPROMSpeicherPlatz + 4;
}
//  Eichen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void EichenZusammenstellen(byte Messwert){
  for (int CounterZeile = 0;CounterZeile <4;CounterZeile++){
    TempString =  String(RMSWert[Messwert], 4);
    if(PosEinstellungBereich == CounterZeile) { for (byte Counter =  0; Counter <   6; Counter++){DisplayZeile[CounterZeile][Counter] = adj[Counter-00];} }
    else                                      { for (byte Counter =  0; Counter <   6; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;}         }
    for                                             (byte Counter =  6; Counter <  11; Counter++){DisplayZeile[Messwert] [Counter] = TempString[Counter- 6];}
    //for                                             (byte Counter =  6; Counter <  11; Counter++){DisplayZeile[CounterZeile][Counter] = MessBereicheStr[MessBereich[CounterZeile]][Counter- 6];}
    for                                             (byte Counter = 11; Counter <  12; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;}
    for                                             (byte Counter = 12; Counter <  13; Counter++){DisplayZeile[CounterZeile][Counter] = 0x40 + 0x16;}
    for                                             (byte Counter = 13; Counter <  20; Counter++){DisplayZeile[CounterZeile][Counter] = 0x20;}    
  }
}
  /*
  #include <string.h>

  DisplayZeile[Messwert] = "";
  strcat(DisplayZeile[Messwert], TempString);
  strcat(DisplayZeile[Messwert], MessEinheitStr);
  strcat(DisplayZeile[Messwert], " ");
  */

  /*
  #include <stdio.h>
  // sprintf(DisplayZeile[Messwert], "%4s%2s ", TempString, MessEinheitStr[Messwert]);
  sprintf(DisplayZeile[Messwert], "%1.2f%2s ", RMSWert[Messwert], MessEinheitStr[Messwert]);
  */
void cls(){
  //    (DisplayZeile[0], "01234567890123456789"); strcpy(DisplayZeile[1], "abcdefghijklmnopqrst"); strcpy(DisplayZeile[2], "ABCDEFGHIJKLMNOPQRST"); strcpy(DisplayZeile[3], "!§$%&/()[]ÖÜÄ,.-;:_#");
  strcpy(DisplayZeile[0], "                    "); strcpy(DisplayZeile[1], "                    "); strcpy(DisplayZeile[2], "                    "); strcpy(DisplayZeile[3], "                    ");
  AufDisplayAusgeben();

}











Vielen Dank für eure Unterstützung

Peter

Breche Deinen Code soweit runter, dass Du das Problem noch nachstellen kannst.

Deine Routine in der ISR ist aufgebläht und macht das Wesen einer ISR zu nichte.
Da gehört 90% raus und in extra Funktion(en) gesetzt.

1 Like

Entgegen meiner Einstellung:

void MessenIRQ(void)
{
  noInterrupts();
  // Messungen durchführen ******************************************************************************************************
  // Die Messungen der 4 Spannungen werden nacheinander durchgeführt. Das "Durchschalten" übernimmt der "MessEingang" 0 bis 3
  // Da direkt nach dem auslesen des Messwertes auf den nächsten Eingang geschaltet wird, wir der derzeit zu messende Kanal
  // in MessEingangTemp gespeichert.
  Serial.print(F("vor: ")); Serial.print(MessEingang); Serial.print(F(" nach: "));
  MessEingangTemp = MessEingang;                                        // MessEingangTemt = Aktuelle Messung
  MessEingang++; if (MessEingang > 3) {MessEingang = 0; FloatRMSTemp[1] = MessEingang + 880;}               // Auf nächsten Eingang schalten. MessEingang steht nun auf dem als nächstes zu messenden Kanal
  Serial.println(MessEingang);
  // ADCs auslesen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  MessWert[MessEingangTemp] = ADCRead();                                // Aktuellen Messwert auslesen (0)
  ADCStart(MessEingangEcht[MessEingang]);                               // Auf nächsten Kanal schalten, und Neue Messung starten

  // Peak detekt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  if (MessWert[MessEingangTemp] > PeakTemp[MessEingangTemp])
  {
    PeakTemp[MessEingangTemp] = MessWert[MessEingangTemp];
  }

  // Max detekt +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  if (MessWert[MessEingangTemp] > MaxTemp[MessEingangTemp])
  {
    MaxTemp[MessEingangTemp] = MessWert[MessEingangTemp];
  }

  // FloatRMS ...................................................................................................................
  FloatRMSCounterAlt = FloatRMSCounter + (FloatRMS - 1); if (FloatRMSCounterAlt > FloatRMS - 1) {FloatRMSCounterAlt = FloatRMSCounterAlt - FloatRMS;} //Position des Alten Wertes berechnen
  FloatRMSSpeicher[MessEingangTemp][FloatRMSCounter] = MessWert[MessEingangTemp];                                                               // Aktuellen Messwert in Array speichern
  FloatRMSTemp[MessEingangTemp] = FloatRMSTemp[MessEingangTemp] - FloatRMSSpeicher[MessEingangTemp][FloatRMSCounterAlt];                        // Alten Messwert von RMSwert (Summe aus "allen Messungen") abziehen
  FloatRMSTemp[MessEingangTemp] = FloatRMSTemp[MessEingangTemp] + MessWert[MessEingangTemp];                                                    // Neuen Messwert zu RMSwert (Summe aus "allen Messungen") addieren
  FloatRMSWert[MessEingangTemp] = FloatRMSTemp[MessEingangTemp] / 1;//FloatRMS;                                                                 // RMSwert (Summe aus "allen Messungen") durch anzahl der Messungen teilen
  FloatRMSTemp[2] = MessEingang + 100;
  FloatRMSTemp[3] = MessEingangTemp + 100;

  if (MessEingang == 0)
  {
    Serial.println(F("TICK"));
    FloatRMSTemp[3] = FloatRMSCounter + 200;                                                                                                    // Wenn der gestartete Messeingang = 0 ist, dann wir der
    FloatRMSCounter++;

    if (FloatRMSCounter > 15)
    {
      FloatRMSCounter = 0;
      FloatRMSTemp[3] = FloatRMSCounter + 400;
    }                                                  // FoatCounter auf nächsten Speicheplatz gestellt
  }

  // ----------------------------------------------------------------------------------------------------------------------------
  interrupts();
}

mit im setup():

  Serial.begin(115200);
  Serial.println(F("Start..."));

bringt folgende Ausgabe:

11:32:29.274 -> Start...
11:32:29.308 -> vor: 0 nach: 1
11:32:29.606 -> vor: 1 nach: 2
11:32:29.905 -> vor: 2 nach: 3
11:32:30.203 -> vor: 3 nach: 0
11:32:30.203 -> TICK
11:32:30.502 -> vor: 0 nach: 1
11:32:30.801 -> vor: 1 nach: 2
11:32:31.099 -> vor: 2 nach: 3
11:32:31.398 -> vor: 3 nach: 0
11:32:31.398 -> TICK
11:32:31.696 -> vor: 0 nach: 1
11:32:31.994 -> vor: 1 nach: 2
11:32:32.293 -> vor: 2 nach: 3
11:32:32.591 -> vor: 3 nach: 0
11:32:32.591 -> TICK

Du suchst an der falschen Stelle.

Auf welchem Arduino soll das denn laufen?

Wo hast Du denn die Interruptverarbeitung abgeschrieben? Diese Quelle ist Mist :frowning:

1 Like

Ich hab auch nicht verstanden, warum da eine ISR eingesetzt werden muss.

Für mich gehört das umgeschrieben, die Eingänge mit jedem Umlauf abgefragt, der Wert evtl. gemittelt, und erst wenn die Ausgabe erfolgt aufbereitet.

Das läuft auf einem Nano,

Wie kann man das (Interruptverarbeitung) die Besser machen?

Ohne jetzt ins Detail gehen zu wollen....

Alle volatile weg machen, denn die machen dir die automatische Optimierung kaputt.

Stattdessen die Atomic Macros nutzen.

Ja, dein Programm ist schön rechteckig.
Aber auch verworren, nicht klar in Module/Komponenten aufgeteilt.

Globale Variablen im Übermaß!
Keine Strukturen.

Und nein, ich verstehe dein Programm nicht.
Kann also auch keine Detail Verbesserungen zeigen.

@peter_2024: Die grundsätzliche Frage ist: Warum überhaupt per Interrupt? Kannst du die beantworten. Und falls die Antwort ist: weil es dann schneller geht, ist die Antwort falsch.

1 Like

Es geht um die Anzahl der Messungen pro Sekunde. Ich nutze die Zeit, in der der AD Wandler Arbeitet für berechnungen und Ausgaben auf dem Display. Sobald der Wandler fertig ist (ca. 70µs) wird der Wert ausgelesen, und eine neue Messung auf einem anderen Kanal gestartet.

Das lässt sich auch mit einer Statemaschine erreichen.

Darauf kann man auch ohne Interrupt warten. Wenn die Rechnung länger dauert als die Konvertierung des nächsten Kanals dann kann das mit Interrupt auch nicht schneller werden.

OK, und wie?
Ziel ist, bei 4 Messkanälen ca. 3500 Messungen (besser 4000 Messungen) pro Sekunde und Kanal, zu realisieren, und daraus RMS aus 256 Einzelmessungen, Peak und Maxhold auf einem 4X16 LCD darzustellen.

Ich bin für Vorschläge offen.

Danke

Peter

LCD lassen wir mal weg. Du hast also 250µs Zeit um die RMS Berechnung zu machen und Peak und Maxhold abzuspeichern. Wie lange dauert die Berechnung? Wenn die Berechnung länger dauert, musst du die Messwerte zwischenspeichern. Ganz schön anspruchsvoll.

Sehe ich das richtig, dass du 16000 Einzelmessungen/s machen möchtest?

Auch das deutet darauf hin!
(zumindest der Kommentar)

Dir ist schon klar, dass du damit die Spezifikation eines m328p deutlich überschreitest?


So hast du 32*250µs = 8ms Zeit für die Berechnung und Ausgabe.

Dann verteile das auf mehrere Arduinos, dann geht das bis zu 4 mal schneller.

Sehe ich gerade die beiden in einer ISR?
Die sind flüssiger als Wasser!
(überflüssig)

Schrieb ich ja schon: die abgeschriebene Quelle ist Mist! Wer meint, effizienten Code so zusammenzuklauben, der wird es wohl nie lernen :frowning:

Nein.

Trenne Dich von Deiner Konfiguration oder Deinem Lastenheft.

1 Like

Zustimm - geht jedenfalls nicht unter dieser Randbedingung:

Oder ist das ein Nano R4?
Dann kann ich das nicht beurteilen.