PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AVR Butterfly PKW-Verbrauchsmessung mittels Durchflusssensor



Beginner85
05.05.2008, 21:41
Hallo Leute!

Da das mein erster Beitrag im Forum ist, bitte ich Gnade vor Recht walten zu lassen ;)
Ich stehe vor folgender Aufgabenstellung für meine Studienarbeit: Ich soll eine Verbrauchsmessung für PKW entwickeln, indem ich einen Durchflussmesser (insgesamt braucht man 2) in den Kraftstoffkreislauf einbringe, das Tachosignal auslese und so den Verbrauch pro 100km berechne. Das Ganze soll mit einem AVR Butterfly gelöst werden. Nun habe ich mich für einen Durchflussmesser entschieden (Conrad Art.-Nr. 150392), die Rechnungen habe ich mir auch mal zusammengeschrieben, das Tachosignal ist auch ein Rechtecksignal... Jetzt stehe ich vor folgendem Problem: Ich weiß inzwischen, welche Ports des AVR PortB noch frei sind und kann diese auch als Eingang und Ausgang deklarieren. Nur jetzt bin ich mit meinem Latein am Ende. Wie schaffe ich es, z.B. die steigenden Flanken innerhalb von z.B. 10s zu zählen? Die 10s kann ich mit einem Timer realisieren, das bekomme ich denke ich auch noch hin. Aber ich schaffe es nicht einer Variable zu sagen, dass sie sich bei einer Flanke inkrementieren soll. Leider habe ich auch mit Hilfe der Suchfunktion keine Antwort gefunden. Zumindest keine, die ich verstanden hätte (bin blutiger Anfänger).

Um die Diskussion über den Sinn der Messung von vornherein zu unterbinden: Ich weiß, dass man normalerweise den Einspritzdruck sowie die Einspritzzeit benutzt, um den Verbrauch zu ermitteln ;) Aber so ist nunmal die Aufgabenstellung. Natürlich werden alle Hilfen, die ich hier erhalte in der Studienarbeit angegeben. Ich will mich nicht mit fremden Federn schmücken.
Ich hoffe, ich habe alle wichtigen Informationen in die Fragestellung reingepackt. Falls nicht bitte nachhaken ;) Ich verwende übrigens AVR Studio 4 mit gcc und programmiere den Butterfly direkt über die RS232-Schnittstelle.
Danke für eure Hilfe!

rideyourstyle
05.05.2008, 22:40
ich kenne den Butterfly nicht. Aber wenn du noch einen (bzw zwei) freien Interupteingang frei hast, kannst du bei jedem Impuls eine Vsriable um eins erhöhen.
Wenn nur einer vorhanden ist, kannst du die Signale der beiden Sensoren über ein Transistor (oder Logik IC) zusammennehmen und diesen an den Interupteingang. Dann muss die Interuptroutine schauen welchen der beiden Sensoren (Jeweils separat an einem Eingang) diesen Interrupt ausgelöst hat und die richtige Variable hochzählen...

Was studierst du eigentlich?

wkrug
06.05.2008, 06:43
Mögliche Interruptquellen sind der INT0, der INT1, der INT2.
Ausserdem könnte man noch den ICP Pin verwenden, sowie den Analog Komperator. Auch diese beiden Quellen können Interrups auslösen.

EDIT! Jeder Sensor sollte natürlich seinen eigenen Interrupteingang kriegen.

Da es hierbei um, für einen Controller relativ niedriege Frequenzen der Geber geht, würd ich die Erfassungsroutine anders gestalten.
Ich selber hab dazu, bei einem Drehzahlmesser, den Timer 1 frei laufen lassen.
Bei einem Interrupt wird der Wert des Timers ( der auch ein Überlaufregister haben sollte, das im Timer Overflow Interrupt hochgezählt wird ) abgespeichert und der Zählerstand des vorausgehenden Interrupts der gleichen Quelle abgezogen.
Die Zählerstände werden dann über eine selbst zu entwickelnde Formel in die entsprechenden Werte umgerechnet.
Man kann so bei jedem Impuls eine Aussage über die momentanen Werte machen. Das bedeutet die Sache ist sehr schnell.

Ich hab ausserdem im Interrupt nur die Zählerstände ausgelesen, subtrahiert und ein Bit Flag gesetzt. Die eigentliche Berechnung hab ich dann im Hauptprogramm ausführen lassen.

Ob man dann per Software noch irgendwelche Dämpfungsfaktoren mit einrechnet ( unrund laufende Sensoren ?! ) kann man immer noch entscheiden.

Man muß lediglich darauf achten, das man Zählerüberläufe erkennen kann, z.B. wenn das Auto steht.

Beginner85
07.05.2008, 20:41
Erstmal Danke für die Beiträge!

Die Lösung mit dem Messen der Zeit zwischen den Interrupt gefällt mir gut. Vor allem wie bereits geschrieben sehr schnell.
@wkrug: Du hast geschrieben, du hättest das schonmal für einen Drehzahlmesser gemacht. Würdest du mir den Code zukommen lassen? Entweder hier posten oder an god@lanheaven.de ?
Danke schonmal im Voraus!

Ich hab jetzt auch noch ne weiterführende Frage: Sind Int0 und Int1 fest verdrahtet, oder kann ich z.B. definieren das ein Pin meines Port B diesen externen Interrupt auslöst?

wkrug
07.05.2008, 21:04
Ich hab jetzt auch noch ne weiterführende Frage: Sind Int0 und Int1 fest verdrahtet, oder kann ich z.B. definieren das ein Pin meines Port B diesen externen Interrupt auslöst?
Die Interrupt Pins liegen auf einem fest definierten Port und können nicht auf einen anderen Port umgeswitched werden.

Der Code ist ein Teil eines größeren Programmes für den ATMEGA8.
Du musst Dir halt die entsprechenden Softwareanteile rauspicken.

Die Mail richt ich mal her und schick sie Dir dann.

Beginner85
13.05.2008, 19:49
So, ich habe jetzt mal die Schaltpläne des Butterfly durchforstet. Nur weiß ich noch nicht, ob mich meine Erkenntnisse weiterbringen.
Die Pins Int0 und Int1 sind meine Programmierschnittstelle weshalb ich mir noch nicht ganz so sicher bin, ob ich die dann verwenden kann. Ich habe dann mal spaßerhalber nach Pin Change Interrupts geschaut, aber dann würde ich Änderungen im Display mitzählen, da in den Gruppen immer Teile des Displays, des Joysticks etc. enthalten sind. Ok, aber so weit bin ich noch gar nicht ;) Wahrscheinlich werde ich für die Frage jetzt gesteinigt, aber:

Der Timer 0:

Ich will den Timer zum besseren Verständnis 1s lang etwas machen lassen. Mit einem Takt von 2Mhz und einem Prescaler von 1024 komme ich auf 0,13s bei meinem 8bit-Timer (wenn ich mich nicht verrechnet habe). Ich dachte also, ich könnte die Überläufe zählen und dann z.B. nach dem 8. aus der Schleife springen. Leider beginnt mein Timer gar nicht erst zu laufen. Was mache ich falsch? Hier der Code:



TCNT0 = 0; //Timer startet bei 0
TCCR0A = 0x05; //Prescaler = 1024
TIMSK0 = 0x01; //TOIE0 = 1 -> Interrupt enable (bräuchte ich hier garnicht)

if(TIFR0 == 1)
{ LCD_puts("Hallo",1);}

Im Register TIFR0 steht im LSB mein TOV0 = mein Overflow Flag des Timers. Leider springt der uC nie in die If-Schleife woraus ich schließe, das der Timer nie überläuft, also wahrscheinlich gar nicht erst startet. Weiß hier jemand Rat?

Meine nächste Frage wäre dann noch, ob ich für den Fall, dass ich tatsächlich keinen externen Interrupt ausführen kann, folgende Lösung anwenden kann:



i = 0;
while(1 == 1)
if( x!= PINA)
{
x = PINA;
i++;
}


Schonmal Danke für die Hilfe!

wkrug
13.05.2008, 20:28
Sollte der Begriff if(TIFR0 == 1) nicht if((TIFR0&0b00000001)==1) lauten ?
Es wird vor dem Timer Interrupt ja der Comparematch Interrupt ausgelöst.
Somit hat das TIFR0 Register beim Comparematch den Wert 3.
Also nicht den Wert 1 und deshalb wird deine Ausgabe nicht aktiv.

Wenn Du mit Interrupts arbeiten willst musst Du auch das "I" Flag im Statusregister setzen.
#asm ("sei");
Der Timer läuft in Deiner konfiguration schon an, hast Du auch wirklich 1024 Takte simuliert damit der Timer wenigstens mal bis Zählerstand 1 kommt ?

Mit dem 8 Bit Timer musst Du schon mit der Quarzfrequenz und dem Teilungsfaktor ein wenig rumprobieren bis Du genau auf 1 Sekunde kommst.
Einfacher geht das mit einem 16Bit Timer und dem Comparematch Interrupt, in dem dann eine Variable hochgezählt wird.