Hallo liebe Forumsgemeinde,
ich bin ein ziemlicher Anfänger was AVR Programmierung anbelangt und
stehe gerade vor einem Problem, bei dem ich eure Hilfe erhoffe. Ich
verwende eine Atmega88-PU als Slave für einen Rasenroboter, dieser soll
6 verschiedene HC-SR04 Ultraschallsensoren nacheinander auswerten und
danach außerdem die Drehzhal der beiden Antriebsmotoren erfassen und
beide Infos an den Master (auch ein Atmega88-PU) via UART schicken, wenn
dieser danach fragt. Kernproblem ist hier aber die Sensorauswertung. Der
restliche Code muss erst noch geschrieben werden.
jetzt wollte ich diesen so verwenden, das jeder Triggereingang einen PIN
vom Atmega geschenkt bekommt, die Echo Leitungen aber über Dioden und
Pull Down Widerstände zusammengefasst werden. ( Da es ja nur 3 wirkliche
externe Interrupts gibt, Pin Change wollte ich Zwecks des "was ist nun
für ein Zustand?" nicht verwenden )
Randbedingung ist außerdem, dass INT0 und INT1 nicht verfügbar sind, da
an diesen die Drehzahl über Inkrementalgeber für die Motoren ermittelt
werden sollen.
Nun allgemein die Frage ob der Code so funktionieren könnte?
Und eher zwei speziellere die das alles schon scheitern lassen könnten:
1) Was passiert, wenn der Timer 1 bereits schon läuft ( um die Messung
für Sensor x nach ca 35ms zu unterbrechen und den nächsten Sensor x+1 zu
triggern ), nun aber durch den Analogkomparator ein weiterer Start des
Timer 1 ausgelöst wird? ( dieser soll die steigende Flanke und fallende
Flanke des Echos erfassen ) Beginnt dieser einfach erneut bei 0 zu
zählen oder zählt er gemütlich weiter? Oder geht das an sich nicht?
2) Kann man, so wie ich es momentan versuche, während der Ausführung der
ISR für den Analogkomparator durch Triggerung und auftreten einer
steigenden Flanke an AIN0 den Komparator während der ISR die Triggerung
auf eine fallende Flanke umstellen, sodass damit eine Zeitenmessung
möglich ist?
Entschuldigung für die doofe Darstellung, ich weiß nur leider nicht wie
ich den Code hier schöner einbinden könnte.
Ich hoffe die Pfiffigen unter euch können und wollen mir Amateur helfen.
:D Schon einmal vielen Dank an euch!
Grüße
Kevin
Hi,
es war nicht leicht deinen Ausführungen zu folgen, aber ich versuche mal
mein bestes.
Deinen Code so anzusehen ist mir nicht wirklich gelungen. Warum hast du
statt den ganzen png Dateien nicht einfach die Quellcode Datei
angehängt?
1) Interrupts sind im laufenden Interrupt gesperrt es sei denn du gibst
sie explizit frei. Tritt während eines laufenden Interrupts ein weiterer
erfasst, wird dieser sofort bearbeitet, sobald der 1. abgearbeitet ist.
2) Hab ich nicht ganz verstanden, aber ich sag mal was. Du kannst doch
wenn AIN0 auf eine steigende Flanke ausgelöst wurde einfach im Interrupt
direkt umkonfigurieren, dass nun auf fallende Flanke regiert werden
soll.
Falls du den Flankenwechsel schneller erwartest, als ihn der der 16MHz
getaktete AVR verarbeiten kann musst du den Controller wechseln.
Halte ich aber für unwahrscheinlich.
floatEntfernung=(343*Dauer*0.000004)/2;// ( 343 m/s * Timer1 * 64/16MHz )/2 , da Echo hin und zurück und wir nur Hinweg haben wollen == Ergebnis in Meter
155
156
157
if(Entfernung<=0.08)// Hindernis 8cm vor mir? Wenn ja aber Hoppa und stehenbleiben!
Hindernis=0;// Hindernis auf 0 zurücksetzen wenn in Gegenrichtung gefahren
187
188
}
189
}
Ich hoffe das hat so funktioniert!
Schneller erwarte ich den Flankenwechsel keinesfalls. Ich möchte ja die
Sensoren auf 8cm Entfernung Triggern, selbst mit Prescaler von 256 käme
ich da auf eine so kurze Entfernung, die der HC SR04 schon gar nicht
mehr erfassen kann.
Zu 1) Also söllte es wohl so funktionieren oder?
Zu 2)Sorry für die blöde Umschreibung. Also folgendes Szenario: Echo
kommt an, da der Komparator auf steigende Flanke gestellt ist und der
Timer 1 bereits läuft ( wird direkt nach der Triggerung des jeweiligen
Sensors gestartet, um nach spätestens 35ms die Messung abzubrechen ( da
kein Objekt in der Nähe ) und zum nächsten Sensor überzugehen) würde
dieser den Timer 1 erneut starten, da ja das ACIC Bit gesetzt ist. Jetzt
die Frage: startet der Timer einfach erneut von 0 an zu zählen oder
macht dieser einfach ganz normal weiter oooder will der µC am Liebsten
gar nichts von beiden tun und verweigert seine Arbeit?
Nun weiter: Da jetzt eine Flanke kam wird die ISR für den Analog
Komparator gestartet. Dieser schaut mit if(ACIS0==1), ob dieser noch auf
die steigende Flanke eingestellt ist und wenn ja, soll dieser während
der ISR auf die fallende Flanke umgestellt werden und den Timer mit
TCNT1=0 von 0 an neu zählen lassen. Jetzt geht das ECHO auf LOW wodurch
die ISR des Analog Komparators erneut ausgeführt wird, diesmal springt
er aber in den else Zweig und übergibt den aktuellen Wert des Timers und
setzt zusätzlich Hindernis=1, da sich etwas vor dem Sensor befindet.
Danach wird alles dem Hauptprogramm übergeben, welches die Entfernung
ausrechnet und bei einer Entfernung <= 8cm diese Information + die
Richtung des Objektes, also Vorn oder Hinten, via UART an den Master
schickt, welcher nun einen Bremsvorgang einleitet.
Ich hoffe diese Beschreibung war etwas ausführlicher und hilft dir das
ganze besser zu verstehen. Die Farge besteht nur noch, ob das ganze so
funktioniert, wie ich es mir denke bzw geschrieben habe.
Für weitere Hilfe würde ich mich weiter bedanken! :)
Grüße
Kevin
Zu 1)
Ja das mit den Interrupts kann so funktionieren.
Zu 2)
Eine weitere Frage. Wenn du den Analog Comparator nutzt musst du ja
beide Pins beschalten (AIN0 und AIN1). Ich denke es wäre einfacher über
PCINT irgendeinen PIN zu nehmen und über EICRA (DB Seite 73) auf
Interrupt bei "any logical change" zu konfigurieren.
ACIC zählt ja nur hoch wenn auch Ereignisse am Analog Comparator
auftreten. Wenn also die Flanke auf High wechelt zählt er einmal und das
nächste mal wenn du ihn umkonfiguriert hast und er die fallende Flanke
zählt. dein Ergebnis ist immer 2. Egal wie lange das dauert.
Ich würde es so machen:
Messung starten an SR04 - 1
Timer starten
mit einem PCINT erfassen (kann auf steigend, fallend und any gesetzt
werden)
Wert aus Timer holen
Wert speichern
Timer stoppen
Messung starten an SR04 - 2
...
...
...
Ich benutze den PCINT eigentlich sehr gerne:
ISR(PCINT0_vect)
// PC0 -> PCINT8
{
char x=0,y=0;
temp_old = temp;
test();
x = temp;
x &= 4;
y = temp_old;
y &= 4;
if (!(x == y)) {
if (x)
{
start0 = TCNT1;
}
if (!x)
{
stop0 = TCNT1;
steer = stop0 - start0;
}
}
}
char test (void) {
int_mask = PCMSK0;
temp = PINB;
temp &= int_mask;
return temp;
}
Ein kleiner Code Ausschnitt um am PCINT festzustellen welcher Pin
betätigt wurde macht die Funktion test().
Im Interrupt werte erfasse ich den Zählerstand des Timers und
subtrahiere den Startwert vom Endwert (fallende - steigende Flanke).
Ich finde das recht simpel.
Kannst du dir ja mal überlegen.
Hallo Bastelgemeinde,
Jetzt versuche ich gerade mehrere ( 6 Stück ) parallel laufen zu lassen.
Die Auswertung eines Sensors über UART mit dem Atmega88p läuft 1A ( ohne
Interrupts, nur über Pinzustände ). Nun frage ich mich aber, ob es einen
"Pinsparenden" Weg gibt die Sensoren zusammen zu schalten?
Getriggert werden muss einzeln ( oder vielleicht mit Schieberegister
möglich ), jetzt habe ich aber versucht die ECHO Ausgänge zusammen zu
schalten. Direkt zusammen kommt nur 0 cm raus, mit Dioden kommen
wiederum nur schwankende und sehr hohe Werte heraus ( ca. doppelt so
viel ). Anzumerken sei hierbei, dass beim anstecken des zweiten Sensors
bei beiden Varianten immer noch nur Sensor 1 getriggert und ausgewertet
wurde. Also nur das physische Anschließen des zweiten Sensors hat die
Werte schon so sehr verändert.
Kennt jemand einen einfachen Weg, wodurch ich die ECHO Ausgänge
zusammenschalten kann?
LG,
Kevin