PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hilfe bei Steuerung durch Zufallsentscheidung



akjra
28.01.2015, 21:13
Hi,

Ich habe einen kleinen Robo mit Ultraschallsensor gebastelt.

Ich hätte gerne ein Zufallsentscheidung eingefügt die dafür sorgt das die Drehung zu beiden Seiten erfolgen kann.



int trigger=12;
int echo=13;
long dauer=0;
long entfernung=0;
int motor1_A=11;
int motor1_B=10;
int motor2_A=6;
int motor2_B=5;

void setup()
{
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);
}

void loop()
{
digitalWrite(trigger, LOW);
delay(5);
digitalWrite(trigger, HIGH);
delay(10);
digitalWrite(trigger, LOW);
dauer = pulseIn(echo, HIGH);
entfernung = (dauer/2) / 29.1;

if (entfernung <= 35)
{
digitalWrite(motor1_A,LOW); // Stop
digitalWrite(motor2_A,LOW);
digitalWrite(motor1_B,LOW);
digitalWrite(motor2_B,LOW);
delay(500);
digitalWrite(motor1_A,LOW); // Rückwärts
digitalWrite(motor2_A,HIGH);
digitalWrite(motor1_B,HIGH);
digitalWrite(motor2_B,LOW);
delay(400);
digitalWrite(motor1_A,HIGH); //Drehung links
digitalWrite(motor2_A,HIGH);
digitalWrite(motor1_B,LOW);
digitalWrite(motor2_B,LOW);
delay(500);
}
else
{
digitalWrite(motor1_A,HIGH); // Fahren
digitalWrite(motor2_A,LOW);
digitalWrite(motor1_B,LOW);
digitalWrite(motor2_B,HIGH);
}
}

Die Drehung rechst wäre dann,


digitalWrite(motor1_A,LOW); //Drehung rechts
digitalWrite(motor2_A,LOW);
digitalWrite(motor1_B,HIGH);
digitalWrite(motor2_B,HIGH);
delay(500);


Hat jemand eine idee?

cdk
29.01.2015, 00:38
Pseudo-Zufälle kannst Du über die Arduino-Funktion random() (http://arduino.cc/en/Reference/Random) erzeugen. Mit random(100) und anschließender Abfrage auf >49 erzeugst Du eine 50/50 Entscheidung.

akjra
29.01.2015, 09:23
Danke cdk,

das war dann doch einfach. :)

int trigger=12;
int echo=13;
long dauer=0;
long entfernung=0;
int motor1_A=11;
int motor1_B=10;
int motor2_A=6;
int motor2_B=5;
long randNumber;

void setup()
{
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);

}

void loop()
{
digitalWrite(trigger, LOW);
delay(2);
digitalWrite(trigger, HIGH);
delay(8);
digitalWrite(trigger, LOW);
dauer = pulseIn(echo, HIGH);
entfernung = (dauer/2) / 29.1;



if (entfernung <= 35)
{
digitalWrite(motor1_A,LOW); // Stop
digitalWrite(motor2_A,LOW);
digitalWrite(motor1_B,LOW);
digitalWrite(motor2_B,LOW);
delay(500);

digitalWrite(motor1_A,LOW); // Rückwärts
digitalWrite(motor2_A,HIGH);
digitalWrite(motor1_B,HIGH);
digitalWrite(motor2_B,LOW);
delay(500);


if (random(100)>49)
{
digitalWrite(motor1_A,LOW); //Drehung rechts
digitalWrite(motor2_A,LOW);
digitalWrite(motor1_B,HIGH);
digitalWrite(motor2_B,HIGH);
delay(500);
}
else
{
digitalWrite(motor1_A,HIGH); //Drehung links
digitalWrite(motor2_A,HIGH);
digitalWrite(motor1_B,LOW);
digitalWrite(motor2_B,LOW);
delay(500);
}

}
else
{
digitalWrite(motor1_A,HIGH); // Fahren
digitalWrite(motor2_A,LOW);
digitalWrite(motor1_B,LOW);
digitalWrite(motor2_B,HIGH);
}
}

PICture
29.01.2015, 09:44
Hallo!

Ich denke, dass am einfachsten wäre benötigte Anzahl von niedrigstwertigen Bits aus freilaufendem Timer, falls noch freien gibt, in zufälligen Zeitabständen ablesen. ;)

akjra
29.01.2015, 10:15
Das verstehe ich jetzt nicht wirklich. Kannst du das kurz erklären oder mit einen Linke geben?

PICture
29.01.2015, 10:18
Sorry, aber das ist meine "verrückte Idee" und deshalb bitte um konkrete Fragen, aber ich k.A. über "Cäh" habe. ;)

akjra
29.01.2015, 10:23
Meine Lösung Funktioniert ja zufriedenstellend. Also Danke für den Beitrage mit dem freilaufenden Timer

cdk
29.01.2015, 12:10
Hallo!

Ich denke, dass am einfachsten wäre benötigte Anzahl von niedrigstwertigen Bits aus freilaufendem Timer, falls noch freien gibt, in zufälligen Zeitabständen ablesen. ;)

Ich denke sowas in der Art wird die random Funktion intern auch machen. Der Arduino startet ja nach Reset freiwillig einen Zähler im us Takt (läßt sich per micros() (http://arduino.cc/en/Reference/Micros) abfragen), der dann nach 70min überläuft und von vorne beginnt. Ich denke dessen untere Bits wären für unkritische Zufallsfunktionen ganz gut brauchbar.

@akjra
Stell dir einen solchen Zähler mal binär vor und frage z.B. die unteren 4 Bit, welche ständig durchrotieren, spontan ab. Da wirst Du dann auch scheinbar zufällige Zahlenwerte von 0..15 erhalten.

PICture
29.01.2015, 12:15
@ cdk

Besten Dank für perfekte Erklärung meiner Idee, weil ich Arduino gar nicht kenne. :D

Sisor
29.01.2015, 23:16
Also frei nach CDK:
Random True oder False:

#define ZUFALL (micros() & 1)

if (ZUFALL) links();
else rechts();

akjra
30.01.2015, 06:57
Wenn ich das richtig verstehe wird der Wert ZUFALL erzeugt +1. Folgt daraus nicht das immer links gedreht wird?

Mit der Funktion habe ich noch keine Erfahrung.

Sisor
30.01.2015, 08:54
ZUFALL ist hier ein Makro. D.h. der Compiler setzt überall wo ZUFALL steht, die Klammer ein.
'micros() & 1' vergleicht die Zahl der vergangenen Mikrosekunden mit der Maske 1.
Somit wird nur das niedrigste Bit ausgewertet. Man könnte auch fragen: Ist der Momentanwert von micros() gerade oder ungerade?
Das ist natürlich nur Pseudo-Zufall, in einfachen Programmen kann es sein, dass immer ein definierter Wert rauskommt.

cdk
30.01.2015, 12:33
Du bringst es auf den Punkt. Für 50/50 Entscheidung genügt ein Bit. Und solange sichergestellt ist daß man nicht-periodisch, sondern nur "spontan" abfragt sollte das funktionieren.

Allerdings hab ich den Text zur micros Funktion *hust* inzwischen sogar mal durchgelesen und da steht daß beim Standard-Arduino im 4us-Takt aktualisiert wird, sodaß sich die letzten beiden Bits dann doch wieder disqualifizieren weil sie vermutlich immer den gleichen Inhalt haben werden. Also muß man mindestens Bit 2 bemühen
#define ZUFALL (micros() & 4)
- oder doch einfach random nehmen und gut... :)

Sisor
30.01.2015, 16:03
Ja, klar, Dokumentation lesen hilft natürlich. ;)

akjra
30.01.2015, 18:27
Das einfügen der Funktion dient ja nur dazu dem Robo eine Varianz zu eben damit ein Betrachter sicher ein wenig das Gefühl bekommt hier findet eine qualitative und nicht eine quantitative Entscheidung statt. Genauso mache ich es mit der Drehweite im ms.

randTurn = random(200,800);

Die random Funktion ist vollkommen ausreichend. Aber schön zu lernen das es auch andere Wege gibt. ;)