Arduino als Frequenzteiler

Mein Code ist für Entwurf einer Messgerätesynchronisation und ich verwende Arduino dafür. Die Zustände und Frequenzen für jeden Pin werden von Bediener eingegeben. Damit die PINs möglichst präzise Frequenzen arbeiten, brauche ich in meinem Code hohe Frequenz-Interrupt. Im Anhang finden Sie zwei Fotos. Erstes Foto von Frequenz-Interrupt (5000 Hz Interrupt) und es läuft gut, aber es bietet nicht so präzise Frequenz und beim 10000 Hz Interrupt beim zweiten Foto das Code wird nicht funktioniert. (serialEvent()) wird nicht ganz im Code bearbeitet.

unsigned int VERG = 200;    // 10000 Hz INTERRUPT FREQUENCY repräsentiert 0.0001 Sekunde
boolean state[8];           // state =0 ==> LOW state =1 ==> HIGH
boolean state2[8];          // welche PINS (Ausgänge)sind aktiviert oder deaktiviert , state2 =0 ==> PIN deaktiviert state2 =1 ==> PIN aktiviert
static int pinhigh[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000}; // PINS 0-7 Aktiviert
static int pinlow[8] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};  // PINS 0-7 Deaktiviert
int F[8];  // PINS 0-7
int VCS10 = 0;
int VCS11 = 1;
int VCS12 = 0; // Prescale 8
boolean state_periode[8]; // funktioniert der PIN nur eine Periode oder normal(Sequenzen), state_periode =0 ==> Sequenzen  state_periode =1 ==> eine Periode
int counter_periode[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // wie viel LOW und HIGH brauche ich, um eine periode zu realisieren
double value_Frequenz[8] ;  //  die eingegebene Frequenzen

void setup() {
  Serial.begin(9600);
  Serial.println("Geben Sie Faktoren fuer jeden Pin ein mit ; zwischen jedem Pin ");
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  DDRC = 0xFF;   // PORTD (digitale PINS 0-7) Ausgänge
  AZ();          // Anfangszustand
  serialEvent() ;
  
}                                                  

void loop() {

}

//==========SUBROUTINEN====================

//Anfangszustand
void AZ() {

  TCCR1A = 0;
  TCCR1B = 0;               //Timer abgeschaltet
  PORTC = 0x00;        // Alle Pins (Digital) auf 0 setzen
  int i;
  for (i = 0; i < 8; i++) {      //state auf 1 am Anfang damit erster Puls für jeden PIN HIGH beginnt
    state[i] = 1; state2[i] = 0; F[i] = 1;
    state_periode[i] = 0;         // state2 auf 0 am Anfang damit alle PINs deaktiviert werden
    // F[i] auf 1 am Anfang damit alle Zähler auf 1 gesetzt werden
  }
}
//============Timerdefinition========================
void Timer_def() {
  TCCR1A = 0;                //Register  Timer 1 16 bit, Prescale drinnen geschrieben
  TCCR1B = 0;               //Timer abgeschaltet

  TCNT1 = 0;                // Register mit 0 initialisieren;// timer 1 16Bit (counts 0 to 65,535)  intial 0;

  OCR1A = VERG;            // Output Compare Register vorbelegen;

  TCCR1B = TCCR1B | (VCS10 << CS10) | (VCS11 << CS11) | (VCS12 << CS12); //Konfiguration des Prescaler; ==> TCCR1B=00000100 ==> 256 Prescaling
  TIMSK1 |= (1 << OCIE1A);  // Timer Compare Interrupt aktivieren
}
//============INTERRUPTS========================
ISR(TIMER1_COMPA_vect)
{
  //Serial.println("1");    // check ob Interrupt gestoppt
  TCNT1 = 0;                // Register mit 0 initialisieren
  int i = 0;
  int TEMP = B00000000;    // start   alle PINS  deaktivieren
  for (i = 0; i < 8; i++)
  {
    if (!state2[i]) {   // state2 =0 ==> PIN deaktiviert state2 =1 ==> PIN aktiviert
      continue;
    }
    state[i] ? TEMP = TEMP | pinhigh[i] : TEMP = TEMP & pinlow[i]; //ternary operator ist gleich wie if unten in Kommentar
    F[i]++;                     //  state =1--> PIN HIGH, state =0--> PIN LOW.// beginnt der PIN mit HIGH oder mit LOW // jedes mal nächstes PIN

    if (F[i] == round(value_Frequenz[i])) { // die Frequenz von jedem PIN repräsentiet eine bestimmte Zahl , z.B. 1Hz ==>500
      F[i] = 1;                     // soll der Zähler bis diese Zahl (500) soll 2 Mal zählen, einmal HIGH(0.5 Sekunde) und einmal LOW(0.5 Sekunde)
      state[i] = !state[i];         // zählt der Zähler bis diese Zahl (500), toggelt es von HIGH auf LOW oder von LOW auf HIGH, jedes Mal toggelt es,counter_periode+1
      counter_periode[i]++;         // wenn jeder Zähler (F[i]) bis seine bestimmte Zahl zählt, er wird auf 1 (Anfangswert) gesetzt.
    }

    if (counter_periode[i] == 2 && state_periode[i] == 1) { // braucht nur eine Periode (state_periode =1), dann wenn counter_periode =2 (es toggelt 2 Mal)
      state2[i] = 0;                                        // wird der PIN deaktiviert (state2 =0)
    }
  }

  PORTC = TEMP;                    // PORTC 0-7

}

//===========USB-Kommunikation=================

void serialEvent() {
  //AZ();          // Anfangszustand
  int value[8];
  boolean first_check = 1, second_check = 1, check_freq = 1, flag, print_zustand = 0, print_zustand2 = 0, print_frequenz = 0, print_frequenz2 = 0 ;
  while (Serial.available() > 0) { // Serial empfängt etwas   
    while (first_check || second_check) { // 2 Checks, first_check für 8 Zustände(0 oder 1 oder 2 oder 3 oder 4) für PINS
      String Eingabe = Serial.readStringUntil("\n");  //Zust1;Zust2;Zust3;Zust4;Zust5;Zust6;Zust7;Zust8
      int LEN = Eingabe.length() + 1;
      if (LEN != 17 ) {                    // Überprüfung dem Length von eingegebene Zustände
        
          Serial.println("Anzahl der eingegebene Werte ungueltig (soll 8 sein)"); // nicht gültig, first_check =1 und LOOP wiederholt sich
        first_check = 1;
        continue;
      } else {                             // die eingegebenen Zustände sind gültig, first_chec =0 und erster Check erfüllt
        first_check = 0;
      }
      char copy[LEN];
      Eingabe.toCharArray(copy, LEN);
      value[0] = atoi(strtok(copy, ";"));
      flag = 1;
      for (int i = 1; i < 8; i++)
      {
        value[i] = atoi(strtok(NULL, ";"));
        if (!(value[i] == 0 || value[i] == 1 || value[i] == 2 || value[i] == 3 || value[i] == 4)) // der zweite Check für die Überprüfung von eingegebenen Werten für Pins
        {
            Serial.println("die eingegebenen Werte fuer Pins sind ungueltig ");
           
          flag = 0;                                       // die eingegebenen Werte für Pins sind ungültig, flag=0 und second_check = 1, LOOP wiederholt sich
          break;
        }
      }
      flag == 1 ? second_check = 0 : second_check = 1;       // die eingegebenen Werte für Pins sind gültig, dann second_check = 0 und LOOP wiederholt sich nicht mehr
    }
    
    }
    while (check_freq) {  // ein Check für die Überprüfung der Gültigkeit von eingegebenen Frquenzen (0.1 Hz - 100 Hz)
      boolean flag2 = 1; 
      Serial.println("Geben Sie Frquenzen fuer jeden Pin in Hertz ein, ; zwischen jeder Frequenz");
      String Frequenz = Serial.readStringUntil("\n"); //Freq1;Freq2;Freq3;Freq4;Freq5;Freq6;Freq7;Freq8
      int LEN_Frequenz = Frequenz.length() + 1;
      Frequenz = Frequenz.substring(0, Frequenz.length()); //\n aus String entfernen
      char copy_Frequenz[LEN_Frequenz];
      Frequenz.toCharArray(copy_Frequenz, LEN_Frequenz);
      value_Frequenz[0] = atof(strtok(copy_Frequenz, ";"));
      for (int i = 0; i < 8; i++)
      {
        if (i != 7) {
          value_Frequenz[i + 1] = atof(strtok(NULL, ";"));
        }
        if (!(value_Frequenz[i] >= 0.1 && value_Frequenz[i] <= 100)) { // die eingegebenen Frequenzen sind ungültig, flag2 = 1 und check_freq = 1, LOOP wiederholt sich
          flag2 = 1;
            Serial.println("die eingegebenen Frequenz fuer Pins sind ungueltig ");
          break;
        } else {
          flag2 = 0;
        }// die eingegebenen Frequenzen sind gültig, flag2 = 0 und check_freq = 0, LOOP wiederholt sich nicht
      }
      flag2 == 1 ? check_freq = 1 : check_freq = 0;
    }
    
    Serial.println("Zum Stoppen geben Sie stop ein ");
    int k;
    for (k = 0; k < 8; k++) {        // jeder eingegebene Zustand wird für seinen PIN gesetzt
      value_Frequenz[k] = round(1250.00 / value_Frequenz[k]);
      switch (value[k]) {
        case 1:
          state2[k] = 1; //aktiviert
          break;

        case 2:
          state2[k] = 1;
          state[k] = 0; //invertiert
          break;

        case 3:
          state2[k] = 1;
          state_periode[k] = 1; // 1 Periode
          break;

        case 4:
          state2[k] = 1;  //aktiviert
          state[k] = 0; //invertiert
          state_periode[k] = 1; // 1 Periode
          break;
      }
    } 
    first_check = 1, second_check = 1, check_freq = 1; // Anfangswerte fuer Checks
    Timer_def();
  }

}

sketch_may31a.ino (10.6 KB)

Wie war noch gleich die Frage?

Der Code scheint vollständig zu sein, aber warum sollte ihn irgendjemand analysieren und Vermutungen anstellen? Eine menschenlesbare Beschreibung des Projekts und der Probleme wäre hilfreich.

Wieso Interrupts, wofür?

Welcher Arduino?

DrDiettrich:
Wie war noch gleich die Frage?

Der Code scheint vollständig zu sein, aber warum sollte ihn irgendjemand analysieren und Vermutungen anstellen? Eine menschenlesbare Beschreibung des Projekts und der Probleme wäre hilfreich.

Wieso Interrupts, wofür?

Welcher Arduino?

Vielen Dank Herr DrDiettrich,
Ich verwende Arduino Mega als Frequenzgenerator für Messgerät. Die Frequenzen(Rechteckfolge) von Messgeräten werden Von bediener eingegeben. Ich verwende Interrupt um die Periode zu realisieren.
meine Frage, Warum mit Hohe Interrupt-Frequenz (10000 Hz wie in Foto2) die Serialevent() nicht ganz bearbeitet. während bei Interrupt-Frequenz (5000 Hz wie in Foto1) der Code läuft Code. gibt es funktion um Interrupt zu blockieren bis Serialevent() ganz bearbeitet

Wenn Du die Interruptbearbeitung blockierst, bis Dein zu langer und damit zu langsamer SerialEvent durch ist, stimmt Deine Frequenz nicht mehr.

Auch wenn Du alles auf mehrere Threads verteilst, bleiben Deine Fehler die gleichen.

Gruß Tommy

Reichen die Timer nicht für die Frequenzerzeugung?