INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Roborterauto
09.09.2015, 17:55
Beitrag #9
RE: Roborterauto
Hi,
mal ein paar Fragen und Hinweise...

Auf welcher Art von Terain soll das Autochen denn sich bewegen können ? - Asphalt etc. also ebene Flächen oder doch im Gelände ?
Was gibt es für Orientierungshilfen für die Sensoren ? - Linien oder andere Landmarken ?

Nur mal so als Hintergrund wie es die Großen machen:
Hindernisserkennung und Spurführung per Stereokamera und zusätzlich noch verschiedene Radare um die Umgebung zu erfassen. Differential GPS natürlich.
Optional können auch Laserscanner zum Einsatz kommen wie beim Google Car.
Aus diesen Videos könnt ihr euch ja mal Anregungen für euer Projekt holen...
lgbk

1+1 = 10 Angel ...und ich bin hier nicht der Suchmaschinen-Ersatz Dodgy...nur mal so als genereller Tipp..
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
10.09.2015, 17:23
Beitrag #10
RE: Roborterauto
@Thorsten:

Meine Befürchtung ist, dass eine Implementierung ohne Interrups in einem umfangreichen Programm für Chaos sorgt - zumal dann meine Frage ist, was genau dann mit "Zustand abfragen" gemeint ist.... Die meisten Sensoren geben ja keine absolute Information über den Stand des Rades, sondern ein Rechtecksignal. Bei Drehencodern etc könnte ich mir deinen Vorschlag vorstellen.

Der "Wheel encoder" ist ein prima Tipp, vielen Dank! Mal sehen, wo sich noch eine mechanische Maus auffinden lässt Wink Klingt jedenfalls nach einer schön umsetzbaren Methode.

"micros()" war mir noch gar nicht bekannt - danke, eine sehr nützliche Funktion! Entprellen würde man dann mit Vergleich des aktuellen micros-Wertes mit dem vorherigen? So dass zu kurze zeitliche Abstände nicht ins Inkrement mit eingeht? Oder steh ich noch auf dem Schlauch?

@Bitklopfer:

Als Terrain ist auch Gelände angedacht; das Fahrzeug selbst ist dafür geeignet, aber uns ist bewusst, dass die Hindernisvermeidung dann eine sehr große Herausforderung wird. Also ein Schrittchen nach dem anderen Wink

Meinst du die Sensoren, die dem Auto zur Orientierung dienen? Derzeit gibt es noch keine Landmarken. Der erste Schritt in Richtung Orientierung ist jetzt die diskutierte Distanzmessung, damit hat man dann ja schonmal relative Entfernungsmessung.

Von "den Großen" sind wir ja unendlich weit entfernt Big Grin Die Möglichkeiten sind beeindruckend, nur sehe ich für uns leider kaum die Chance, so etwas zu realisieren... (oder bin ich da zu pessimistisch?)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
12.09.2015, 15:02
Beitrag #11
RE: Roborterauto
(10.09.2015 17:23)Brokie schrieb:  Meine Befürchtung ist, dass eine Implementierung ohne Interrups in einem umfangreichen Programm für Chaos sorgt
Das kommt immer ganz darauf an. Ein Interrupt kann Dir halt zu einer beliebigen Zeit "dazwischenkommen". Selbst etwas, was im Programm ein einzelner Befehl ist, kann durch einen Interrupt ggf. unterbrochen werden. Auch das kann zu Problemen führen. Ich will ja nicht sagen, dass die Verwendung von Interrupts für den Fall eine schlechte Idee ist. Es gibt nur Leute, die meinen, so etwas ginge nur mit Interrupts und man müsste unbedingt Interrupts verwenden. Meiner Meinung nach sollte man das etwas differenzierter betrachten.

Zitat: - zumal dann meine Frage ist, was genau dann mit "Zustand abfragen" gemeint ist.... Die meisten Sensoren geben ja keine absolute Information über den Stand des Rades, sondern ein Rechtecksignal.
Ja genau. Ich meinte damit den Zustand des Eingangs, also den "Level" im Rechtecksignal.
Zitat:Bei Drehencodern etc könnte ich mir deinen Vorschlag vorstellen.
Naja, gerade die liefern ja ein Rechteck... Oder sogar zwei Rechtecksignale, damit man noch vorwärts und rückwärts unterscheiden kann.

Zitat:"micros()" war mir noch gar nicht bekannt - danke, eine sehr nützliche Funktion! Entprellen würde man dann mit Vergleich des aktuellen micros-Wertes mit dem vorherigen? So dass zu kurze zeitliche Abstände nicht ins Inkrement mit eingeht? Oder steh ich noch auf dem Schlauch?
Genau so war's gemeint.

Gruß,
Thorsten

Falls ich mit einer Antwort helfen konnte, wuerde ich mich freuen, ein paar Fotos oder auch ein kleines Filmchen des zugehoerigen Projekts zu sehen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
16.09.2015, 11:39
Beitrag #12
RE: Roborterauto
Juhu, die Schrittzählung funktioniert! Nach etlichen Versuchen mit den verschiedensten Sensoren (auch die optische Maus war zwischenzeitlich am Laufen) hatte ich ein Erfolgserlebnis mit dem Infrarotsender und -Empfänger. Die Zählung läuft sehr schön und zuverlässig - also sofort in ein Test-Sketch integriert und versucht, die Zählung gemeinsam mit dem Motor laufen zu lassen.

Leider kann der Motor nur vernünftig angesteuert werden, wenn der Interrupt-Abschnitt auskommentiert wird Sad Wenn das vollständige Sketch läuft, dann hört man vom Motor nur ein leises Summen/Quietschen, es dreht sich aber nichts. Kann es wirklich sein, dass der Interrupt die Motorsteuerung zerschießt? Kann man das vermeiden? Oder habe ich nur einen dummen Fehler gemacht?

Hier das Sketch:

Code:
//Bibliotheken:
#include "TimerOne.h"
#include <Servo.h>

//Motor:
const int pinfwrd = 12; //Pin für Vorwärtsgang
const int pinbwrd = 11; //Pin für Rückwärtsgang
int motormax = 50; //Maximalwert Motor (beide Richtungen)

//Servo:
Servo servo; //Erzeugung Objekt "Servo"
int spos = 0;  //Ausgabewert für den Servo
const int pinservo = 10; //Pin für Datenübertragung zum Servo
const int servocenter = 90; //Mittelstellung Servo

//Encoder (Raddrehungen):
const int counter1 = 2; //Datenpin vom Encoder -> auf Interrupt!
volatile int pulses = 0; //Anzahl schwarz-weiß-Übergänge
volatile int state; //Status (high/low) des Datenpins zum Vergleich
const int freq = 10000; //Frequenz (in micros) des Interrupts (durch die Timer-Bibliothek)

void setup() {
  Serial.begin(9600);

  // Servo:
  servo.attach(pinservo);

  //Encoder:
  pinMode(counter1, INPUT_PULLUP);
  Timer1.initialize(freq);
  Timer1.attachInterrupt(wheelcount); //Interruptsfunktion wird alle x Mikrosekunden aufgerufen (unabhängig davon, was am Interrupt anliegt)
  state = digitalRead(counter1);
}


void loop() {
  //Visuelles Debugging:
  Serial.print(digitalRead(counter1));
  Serial.print("  ");
  Serial.println(pulses);
  delay(50);

  //Servo:
  servo.write(servocenter);

  //Motor:
  analogWrite(pinbwrd, 0); //Rückwärtsgang aus
  int i=0;
  while(i<=motormax) {
    analogWrite(pinfwrd, i); //Vorwärtsgang langsam beschleunigen
    delay(100);
    i++;
    //Visuelles Debugging:
    Serial.print(digitalRead(counter1));
    Serial.print("  ");
    Serial.print(pulses);
    Serial.print("  ");
    Serial.println(i);
    delay(50);
  }
  while(i>0) {
    analogWrite(pinfwrd, i); //Vorwärtsgang langsam abbremsen
    delay(100);
    i--;
    //Visuelles Debugging:
    Serial.print(digitalRead(counter1));
    Serial.print("  ");
    Serial.print(pulses);
    Serial.print("  ");
    Serial.println(i);
    delay(50);
  }
  while(i==0) {
    Serial.print(digitalRead(counter1));
    Serial.print("  ");
    Serial.print(pulses);
    Serial.print("  ");
    Serial.println(i);
    delay(50);
  }
}

void wheelcount() {
  if(state != digitalRead(counter1)) {
    pulses++;
  }
  state = digitalRead(counter1);
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
16.09.2015, 11:59
Beitrag #13
RE: Roborterauto
Hi,
PWM-Ausgänge benutzen einen Timer, um ihr Signal zu erzeugen. Ich habe jetzt nicht nachgesehen, aber ich gehe mal davon aus, dass der von Euch verwendete Timer gerade der ist, der auch für die verwendeten PWM-Pins benötigt wird. Bei Verwendung der Servo-Library könnte es übrigens zu ähnlichen Problemen kommen.
Außerdem: Was treibt Ihr da mit dem Timer überhaupt? Meiner Meinung nach solltet Ihr statt einem Timer-Interrupt direkt einen externen Interrupt verwenden (siehe https://www.arduino.cc/en/Reference/AttachInterrupt). Den kann man so einstellen, dass er nur für eine Zustandsänderung des entsprechenden Pins aufgerufen wird. Innerhalb der Handler-Funktion solltet Ihr dann entprellen. D.h. mit Hilfe der Funktion micros() prüfen, wie viel Zeit seit der letzten Änderung vergangen ist. Wenn das Ergebnis zu klein ist, dann einfach nicht zählen. Was "zu klein" bedeutet müsst Ihr Euch selbst ausrechnen, das kommt auf die maximale Geschwindigeit der Räder an.
Wenn Ihr den Timer-Kram dann rausgeworfen habt, müsste es auch mit den Motoren klappen.
Gruß,
Thorsten

Falls ich mit einer Antwort helfen konnte, wuerde ich mich freuen, ein paar Fotos oder auch ein kleines Filmchen des zugehoerigen Projekts zu sehen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
17.09.2015, 10:28
Beitrag #14
RE: Roborterauto
Der Fehler, der "den Interrupt behindert" hat, wurde gestern noch aufgestöbert Wink Die Radachse hat manchmal blockiert, es war also nur ein dummer Zufall *schäm*

Zitat:Was treibt Ihr da mit dem Timer überhaupt? Meiner Meinung nach solltet Ihr statt einem Timer-Interrupt direkt einen externen Interrupt verwenden

Der Timer war der "Rettungsanker" für die ziemlich unsauberen Signale, da es zeitweise unmöglich schien, die Flanken so zu glätten, dass man sie mit Interrupts nutzen kann. Wir haben zwei funktionierende Sketche; das zweite arbeitet genau so, wie du es beschreibst. Das erste, also das, was ich hier schon gezeigt habe, fragt in regelmäßigen Abständen den Pin ab; der Interrupt ist also nicht mehr von außen gesteuert sondern softwareseitig mit einer gewissen Frequenz - die einzige Möglichkeit, die ich sehe, nicht die Flanken, sondern high/low zu zählen.
Ich weiß, dass beide Sketche eigentlich zu rechenintensiv sind und bin mir auch nicht sicher, welches besser ist...
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
17.09.2015, 10:48
Beitrag #15
RE: Roborterauto
(17.09.2015 10:28)Brokie schrieb:  die einzige Möglichkeit, die ich sehe, nicht die Flanken, sondern high/low zu zählen.
Wie kann man HIGH/LOW zählen? Meiner Meinung nach willst Du ja gerade die Flanken zählen. Die "unsauberen" Flanken bekommt man durch entprellen rausgerechnet. Wie das geht habe ich ja beschrieben.

Zitat:Ich weiß, dass beide Sketche eigentlich zu rechenintensiv sind und bin mir auch nicht sicher, welches besser ist...
Definitiv ist der besser, der mit einem externen Interrupt arbeitet. Der andere wird irgendwann Probleme machen. Stell doch mal das Coding hier ein, dann können wir und das mit dem "rechenintensiv" mal anschauen.
Prinzipiell sollte das kein Problem sein. Da geht noch viel mehr...

Gruß,
Thorsten

Falls ich mit einer Antwort helfen konnte, wuerde ich mich freuen, ein paar Fotos oder auch ein kleines Filmchen des zugehoerigen Projekts zu sehen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
17.09.2015, 15:31
Beitrag #16
RE: Roborterauto
Okay, hier sind die beiden Sketches zum Vergleich:

ohne Timer:

Code:
const int counter1 = 2;
volatile int pulses = 0;
volatile int timediff = 0;

void setup() {
  Serial.begin(9600);
  pinMode(counter1, INPUT_PULLUP);
  attachInterrupt(0, wheelcount, CHANGE);
}

void loop() {
...
}

void wheelcount() {
  if (abs(millis()-timediff) > 500) {
    pulses++;
    timediff = millis();
  }
}

mit Timer:

Code:
#include "TimerOne.h"

const int counter1 = 2;
volatile int pulses = 0;
volatile int state;

void setup() {
  Serial.begin(9600);
  pinMode(counter1, INPUT_PULLUP);
  
  Timer1.initialize(10000);
  Timer1.attachInterrupt(wheelcount);
  state = digitalRead(counter1);
}

void loop() {
...
}

void wheelcount() {
  if(state != digitalRead(counter1)) {
    pulses++;
  }
  state = digitalRead(counter1);
}

"High/low zählen" meine ich so: Bei sehr unsauberen Signalen (wie wir sie zu Anfang hatten) waren die "Störphasen" (die eigentlich saubere Flanken sein sollten) sehr groß und das einzig halbwegs brauchbare waren etwas größere low- oder high-Phasen. Die kann man ja mit Interrupt nicht zählen, aber mit dem Timer kann in regelmäßigen Abständen überprüft werden, ob schon über längere Zeit das selbe Signal anlag -> high/low-Phase.
Ist aber mit dem jetzigen Signal eigentlich passé.

Warum wird denn der Timer-Interrupt irgendwann Probleme machen? Nur durch höheren Rechenaufwand?
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste