- fchao-Sinus-Wechselrichter AliExpress         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 24

Thema: TWI stört meinen Interrupt zur Frequenzmessung

  1. #11
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Anzeige

    Powerstation Test
    Ähm, sorry Doppelpost
    Software is like s e x: its better when its free.
    Linus Torvald

  2. #12
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Könnte folgender Code aus meiner TWI-Bibliothek meinen INT0 beeinflussen?

    /*
    ** Wait until transmission completed
    */
    while (!(TWCR & (1<<TWINT)));
    Nein, der µC steckt solange in der Schleife, bis die Übertragung beendet ist.
    Interrupt wird nur dann ausgeführt, wenn TWIE in TWCR gesetzt ist.

    Ich kann ehrlich gesagt das Problem nicht orten

    Fassen wir mal zusammen.

    Wie wird die Messung ohne TWI ausgegeben ? UART ?
    Und wenn TWI dazukommt, wo gibt es den Fehler bei der TWI Übertragung oder bei UART , oder beides ?

    Ich nutze selber die Fleury Lib in Verbundung mit Interrupts, es Funktioniert einwandfrei

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #13
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    55
    Beiträge
    524
    Hallo,

    kannst du diese Funktion mal posten. Es macht mich stutzig, dass der Rückgabewert in das erste Feld eines 8 Byte Array geschrieben wird.
    Code:
                 Data[0] = TWIM_ReadNack ();

    Die gemessene Frequenz wird von einem Atmega8 generiert.
    Das ist gut, damit sollte das Signal immer ein definiertes Potential haben, nicht floaten und nicht prellen. Dennoch, hast du mal bei 'Drehzahl' 0 geprüft, ob die TWI Signale in die Leitung zum Interrupt strahlen und diesen auslösen?

    Hast du NumberOverflowX nur aus Gewohnheit als 16Bit deklariert oder kann der Wert größer als 255 werden? Falls der Wert größer werden kann. möchte ich dir Sebastians erste Antwort noch einmal ans Herzen legen. Der 8Bit Controller kann die Variable nicht in einem Takt abarbeiten. Der Sprung in den Interrupt TIMER1_OVF_vect kann aber jederzeit eintreten, auch während des Übergangs von 00000000 11111111
    nach 00000001 00000000

    Gruß

    Jens

  4. #14
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22
    Ich konnte den Fehler jetzt etwas eingrenzen. Ich habe die I2C-Funktionen direkt hinter die Drehzahlberechnung gesetzt. Also direkt vor dem Update = False Flag. Jetzt tritt der Meßfehler nicht mehr auf!

    Leider weiß ich jetzt genauso wenig wie vorher, warum das so ist. Der I2C-Teil kann da auch nicht bleiben, sondern muss ja wieder in die main-Schleife.

    Derzeit wird nur ein byte in Data[0] geschrieben, geplant sind aber acht. Sämtliche andere Ursachen mit der Frequenzmessung kann ich eigentlich ausschließen, da es ja so Funktioniert. Irgendwas funkt dazwischen, sobald der I2C-Teil im main-Loop steht.

  5. #15
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Prinzipiell finde ich bei Deinem Aufbau die Warteschleifen problematisch -- sowohl die blockierenden TWI-Schleifen als auch die wait() in der Hauptschleife.

    Also: entweder so umcoden, daß Dein Prog *ohne* Warteschleifen auskommt. Oder: die Berechnung der Drehzahl in die ISR verlagern. Falls nämlich wegen des Rumgammelns in den Wartern mehr als 1 Periode der Drehzahlmessung vergeht, hast du ein Problem.

    Ein weiteres Problem bereitet der Überlauf von TCNT1, ich sehe nicht, wo der Fall EndTime-StartTime < 0 behandelt wird.

    Hast du mal überlegt, den InputCapture von Timer1 zu verwenden? Für Zeitmessung passt das vielleicht besser.
    Disclaimer: none. Sue me.

  6. #16
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22
    Die 1ms-Delays musste ich einbauen, da sonst der I2C nicht richtig funktioniert hat. Wie macht man das ohne Wartezeit? Hat ein Interrupt nicht trotzdem Vorang?

    Und wie führe ich die TWI-Funktionen nicht blockierend aus?

    Den InputCapture wollte ich mal verwenden. Aber ich messe ja zwei Frequenzen. Das nützt ja nichts, wenn nur eine richtig gemessen wird.

  7. #17
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Vorrang hat er schon, aber dann müssen die Werte, die er verändert hat, auch ausgewertet werden, bevor er ein zweites Mal auftritt, sonst werden die Werte wieder überschrieben.

    Fleurys Funktionen (zB i2c_readXXX) enthalten Warteschleifen wie
    Code:
    	while(!(TWCR & (1<<TWINT)));
    die eine Verzögerung verursachen, für die du keine Obergrenze angeben kannst (ein I2C-Sklave kann die Übertragung beliebig verzögern).

    Eine nicht-blockierende I2C-Implementierung wäre daher IRQ-getrieben oder man müsste sich eine State-Machine bauen (wäre ne IRQ-getriebene im Endeffekt auch).

    Ein sehr einfaches Beispiel einer nicht-blockierenden Hauptschleife ist auf meiner HP zkizziert. Dort werden 2 LED geblinkt. Eine im Takt von 1s und eine im Takt von 1.1s, was mit Warteschleifen eh net zu machen wäre.

    http://www.gjlay.de/pub/c-code/countdown.html

    In deinem Fall käme man ohne extra Timer aus. Die Hauptschleife läuft nichtblockierend über alle Aufgaben und falls an der Aufgabe erledigt werden muss, wird es erledigt. Beispiel: Daten über TWI senden.

    Irgendwo in Programm (also innderhalb der Hauptschleife) schreibt was Daten in den Ausgabepuffer. Im TWI-Teil wird geschaut, ob Daten da sind. Wenn ja, wird das Datum gesendet, falls nicht schon eine Übertragung im Gange ist. Dazu wird ein Start geschickt, falls es nicht schon geschickt wurde, etc.

    Man muss sich also Zusatände merken (daher der Name /State-Machine/). Wenn man nicht weiterkommt, weil eine Bedingung nicht erfüllt ist (zB weil Daten auf die man wartet noch nicht eingetroffen sind), macht man mit der nächsten Aufgabe (z.B Frequezauswertung) weiter und schaut beim nächsten Durchlauf der Hauptschleife, was geht.

    Das ist natürlich aufwändiger zu programmieren als ein blockierender Ansatz, aber eben auch leistungsfähiger und Module bremsen sich net gegenseitig aus.
    Disclaimer: none. Sue me.

  8. #18
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22
    Vorrang hat er schon, aber dann müssen die Werte, die er verändert hat, auch ausgewertet werden, bevor er ein zweites Mal auftritt, sonst werden die Werte wieder überschrieben.
    Was ich daran noch nicht verstehe: Die Messung, die nicht ausgewertet werden kann, wird überschrieben. Nagut, dann fehlt eine Messung. Aber die nächste Messung überschreibt die Werte und wird ausgewertet. Und dieses Ergebnis muss doch dann stimmen. Es können Messungen aus Zeitgründen verloren gehen. Aber wenn ausgewertet wird, dann stimmt das Ergebnis.

    Ich verstehe deine Programmierung ohne Warteschleifen und habe das auch schonmal angewendet. Damit habe ich eine Animation auf einer 7-Segment Anzeige laufen lassen, während die Messungen liefen. Das funktionierte auch wie gewünscht. Nur weiß ich jetzt nicht so richtig, wie ich das auf die I2C Bibliothek anwende.

    Als Beispiel nehme ich mal die TWIM_Stop Funktion:

    Code:
    void TWIM_Stop (void)
    	{
    
            // Send stop condition
    
    	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
    
            //Wait until stop condition is executed and bus released
    
    	while (TWCR & (1<<TWINT));
    	}
    Ich müsste also natürlich das while entfernen und mit " if ( Zähler == 10 ) " dafür sorgen, dass z.B. alle 10ms diese TWINT-Bedingung überprüft wird. Da die Bedingung aber nicht zu jeder Zeit überprüft werden soll, sondern nur in bestimmten Situationen, muss ich noch eine Variable setzten, die den Zustand speichert und alle anderen Funktionen müssen durch die Zustandsvariable verriegelt sein?

    Das würde dann so aussehen:

    Code:
    void TWIM_Stop (int Zähler)
    	{
    
            // Send stop condition
    
            if ( Zähler == 5 && Zustand == 6 ) 
               {
    	     TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
                 Zustand++; 
                }
    
            //Wait until stop condition is executed and bus released
       
    	if (Zähler == 10 && Zustand == 7 && (TWCR & (1<<TWINT) )
                Zustand++;
    	}

  9. #19
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Ja, mit den Zuständen kommt das prinzipiell hin. Dar Code wird dadurch natürlich länglicher, und die Bib-Funktionen kann man kaum verwenden, sondern man muss sebst codieren.

    Übrigens ist es besser sprechende Bezeichner zu verwenden als magische Zahlen wie 7, also zB
    Code:
    enum
    {
       ZUSTAND_1,
       ZUSTAND_2,
       ...
       ZUSTAND_N
    }
    
    // oder 
    
    #define STATE_A 0
    #define STATE_B 1
    #define STATE_C 2
    ...
    
       if (STATE_A)
       ...
       else if (STATE_B)
       ...
    
    // oder
       switch (state)
       {
          case ZUSTAND_1:
              ...
              break;
          case ZUSTAND_2:
              ...
       }
    Zu Deiner Messung: Du brauchst doch immer 2 Werte, die in eine Differenzbildung eingehen. Wenn einer davon nicht gemessen wird, dann wird die Differenz falsch. Oder ich steh aufm Schlauch...

    Wenn die Berechnung wie gesagt in der ISR gemacht, wird dann kannst Du nix verpassen (ausser die zeitgerechte Verwendung der Drehzahl/Speed/was-auch-immer falls Du in ner TWI-Schleife gondelst, aber immerhin ist die Berechnung dann OK). Das würde Dir die Implementierung eigener TWI-Routinen sparen.
    Disclaimer: none. Sue me.

  10. #20
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22
    Warum sollte denn einer der Werte nicht gemessen werden? Die Interrupts haben ja Vorang. Also gehe ich sicher, dass beide Werte gemessen werden. Und erst dann wird die Berechnung freigeschaltet, während gleichzeitig die Interrupt-Routine keine neuen Werte mehr einlesen kann.

    Ich bin weiter der Meinung, dass die Messung nicht gestört werden dürfte. Selbst wenn tausend waits() im Quelletext sind.

    Ich versuche mich seit einiger Zeit an der nicht blockierenden I2C-Übertragung, aber das ist nicht so leicht wie gedacht.

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress