Home > Technologie > 4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

0
Advertisement

4 Servoantrieb CellBot, der ferngesteuert werden kann.

Ich begann mit einer Idee, was ich von Anfang an machen wollte, aber einen Versuch nach dem anderen kam ich endlich dorthin, wo ich jetzt bin. Dieser Roboter kann ferngesteuert werden von überall in der Welt und um das Haus gefahren. Ich kann durch seine Augen sehen. Hier ist ein kurzer Abfluss. Ich komme später weiter.

* Ich habe eine 3,5 Diskette Fall als Körper genommen und 4 Servos in kontinuierlichen Betrieb für die Fortbewegung umgewandelt.

* Das Hintergehirn, wenn Sie wollen, ist ein Arduino Uno Micro Controller mit einem Sensor-Schild. Dies wird verwendet, um die Sensoren zu hören und fahren die Servos, um es zu bewegen.

* Ich bin mit einem Android-Telefon, speziell die Nexus One als das große Gehirn, das über Wifi verbindet, um mein Heimnetzwerk zu handeln. Es beherbergt eine Webseite, die durch sie kann ich fernsteuern den Bot und sehen, was es sieht durch die Telefone Kamera. Die Software dazu kommt aus einem Projekt namens Cellbots. Die unterstützende Seite für sie ist cellbots.com. Ich verwende die Android-App namens Zellebots. Spüren Sie hier ein Muster?

* Ich verwende Bluetooth, um das Handy mit dem Arduino zu verbinden.

* Ich bin mit Spannungsregler, um genug Strom zum Laden des Telefons und liefern Strom für die Servos.

* Ich bin powering es alle aus einer 6,6 Volt LiFePO4 Batterie. Das ist eine dieser neuen Lithium-Eisen-Batterien, die eine Menge Strafe.

* Ich lade es mit einem Deltran 6 Volt Batterie Tender Ladegerät, die ich beabsichtige, für eine automatisierte Ladestation.

* Ich bin mit einem zwei Router-System-Port an den Bot für die Web-Seite und einen zweiten Router für alle meine Heimat Zeug, um es zu schützen.

Während es nicht wirklich fertig ist, habe ich genug Arbeit zu beweisen, es funktioniert als ein Konzept. Ich kann es fernfahren um das Haus. Es gibt eine Menge von Teilen dieses Puzzles, die wahrscheinlich verdienen ihre eigenen Instructable und ich habe von mindestens einem anderen Instructable auf dieser Website, die ich geben zu geben.

Schritt 1: Servos und das Arduino verwendet, um zu kalibrieren

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

Der arduino Mikrocontroller, Modell uno, ist ein ziemlich einfacher Mikrocontroller zu verwenden. Ich werde nicht bekommen, wie es zu programmieren, aber ich werde ein wenig über die Verwendung in dieser Anwendung diskutieren.

Die Servos, die ich verwendete, sind EXI Modell B1226 sourced von:
http://www.hobbypartz.com/12exiseb1.html

Sie benötigen ein Servo "Horn", um sie mit einem Rad einer Art zu verbinden. Dieses Servo benötigt ein spezielles Horn für das Modell B1228.
http://www.hobbypartz.com/sehosetforap.html

Das Servo ist technisch nicht ein kontinuierlicher Servo, sondern so unglaublich einfach zu konvertieren. Siehe Bilder ...
1. Abdeckung abnehmen
2. Entriegelung und zwei Gänge entfernen.
3. entfernen Sie kleine weiße runde Klammer mit Ihren Fingernägeln.
4. Kalibrieren Sie das Potentiometer, um es die gleiche Geschwindigkeit in beide Richtungen drehen und zu stoppen, wenn Sie ihm den Befehl schicken, um sich zu zentrieren.
5. Benutzen Sie Nagellack, um Potentiameter an Ort und Stelle zu kleben.
6. wieder zusammenbauen, außer dem kleinen weißen Clip, den Sie mit Ihren Fingernägeln entfernt haben.

Warum dieses spezielle Servo?
1. Extrem hohe Drehmoment und genau die richtige Geschwindigkeit für 3 bis 4 Zoll-Räder läuft bei 6 Volt.
2. Es ist $ 14 je.
3. Es hat bereits die Anschläge entfernt, die ihn daran hindern, sich ständig zu drehen.
4. Um es ununterbrochen laufen zu lassen, entfernen Sie einfach den Clip. Ursprünglich war es entworfen, um 8.5 mal von einem Ende zum anderen zu drehen. Nachdem Sie den Clip entfernt wird es kontinuierlich ausgeführt.
5. so kein Schneiden, kein Löten. Wenn Sie das Kalibrierungsprogramm auf Ihrem arduino haben, können Sie es in weniger als 5 Minuten leicht gemacht haben.

Der Quellcode zum Kalibrieren des Servos ist unten. Es dreht nach rechts für 3 Sekunden bleibt noch für 15 Sekunden, links für 3 Sekunden, dann noch für 15 Sekunden. Sie drehen den Potentiameter hin und her, bis das Ding aufhört zu drehen während der 15 Sekunden Perioden für mehrere Zyklen des Programms ...

#einschließen

Servoverstärker;

Void setup () {
Serial.begin (9600);
Eine Verzögerung (5000);
Serial.println ( "Start");
MyservoR.attach (11);
aufrechtzuerhalten.

Void Schleife ()
{
MyservoR.write (180);
Serial.println ( 'Senden 180');
Verzögerung (3000);
MyservoR.write (90);
Serial.println ( 'sending 90');
Verzögerung (15000);
MyservoR.write (0);
Serial.println ( 'sending 0');
Verzögerung (3000);
MyservoR.write (90);
Serial.println ( 'sending 90');
Verzögerung (15000);
aufrechtzuerhalten.

Schritt 2: Servohalterungen und Räder

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

Ich benutzte 1,5 Zoll x 1,5 Zoll L Klammer aus dem lokalen Baumarkt in meinem Fall war es Lowes. Ich benutzte eine Hack Säge, um 90 Grad Schnitte und dann schob den Bereich, wo das Servo geht flach mit meinen Fingern (fühlen sich frei, Werkzeuge zu verwenden).

Die Servo Horn wird gedrückt und dann die Schraube durch die Eingabe, um es zu halten.

Dann befestige ich die Räder mit den Schrauben am Servohorn.

Die Räder sind 80mm Räder von pololu.com
http://www.pololu.com/catalog/product/1430

Schritt 3: Anbringen der Servos und des Telefons an die Stromversorgung

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

Die Servos könnten direkt an die Batterie angeschlossen werden, weil ich eine 6,6 Volt Stromquelle verwendet, aber immer noch über die Stromversorgung sie um rund 20% und ich war nicht glücklich darüber, so dass ich einen Spannungsregler, der die 6,6 Volt in und es umgewandelt Es auf eine feste 5 Volt.

Der Regler könnte eine breite Spanne von Spannung in und aus der 5 Volt. Dies ist die, die ich verwendet von:
http://www.pololu.com/catalog/product/2111/specs

Dieses erfordert lite Löten, um zusammenzubauen, nahm mich ungefähr 2 Minuten. Grundsätzlich haben Sie zwei Drähte (Batterieleistung) und zwei Drähte heraus 5 Volt heraus, um die Servos und das Handy zu versorgen.

Die Verteilerblock nehmen die Stromversorgung aus dem Regler und steckt es auf die 4 Servos und dann einen zusätzlichen Satz von Drähten, um die weiße Steckdose zu verbinden.

Jeder der Sätze der Anschlüsse für die Servos hat 4 Pins.
1 positiv (auf Servokabel ist es das rote Kabel)
1 negativ (auf Servokabel ist es das braune Kabel)
1 Signal von Karte zu Servo (auf Servokabel ist es der orange Draht)
1 Signal von Arduino an Board (gelber Draht)

Grundsätzlich sind die beiden Signalstifte (orange und gelb) auf der Unterseite der Platine zusammengelötet, so dass ich einen Draht vom Arduino zum Board laufen kann. Macht für neater sichere Verdrahtung.

Ich bin die Stromversorgung des Telefons aus diesem Spannungsregler zu. Grundsätzlich, wenn Sie ein USB-Kabel, das an das Telefon anschließen kann schneiden Sie es in der Hälfte sehen Sie 4 Drähte. Sie brauchen nur die roten und schwarzen. Sie erwarten 5 Volt.

Schritt 4: Warum das Telefon über Bluetooth verbinden?

4 Servoantrieb CellBot, der ferngesteuert werden kann.

Die einzige Möglichkeit, ein Android-Telefon kann eine Verbindung zum arduino über den seriellen (USB) -Anschluss des Telefons ist, wenn das Telefon verwurzelt ist. Ich wollte nicht das Risiko eingehen oder mit den Folgen des Einbruchs in mein eigenes Telefon leben. Die Alternative ist, über Bluetooth zu verbinden.

Bei der Auswahl eines Bluetooth Modems wähle ich einen erweiterten Bereich, damit ich ihn für andere Projekte nutzen könnte. Sie brauchen keine Klasse 1 (350 Fuß). Für diese Anwendung eine Klasse 2 (33 Fuß) wird gut funktionieren. Ich habe das USB-Modem hier gefunden ...

http://www.sparkfun.com/products/582

Ich habe die folgenden instructable, wie man es ...
http://www.instructables.com/id/how-to-Control-arduino-by-bluetooth-from-PC-pock/

Hinweis: Wann immer Sie Ihren Code in das Arduino hochladen müssen, müssen Sie zuerst die positive Leitung des Bluetooth Modems von der Stromversorgung trennen. Wenn Sie nicht der Uploader wird Fehler. Das Bluetooth-Modem verwendet dieselben Pins, die von der USB-Verbindung des Arduino verwendet werden.

OK, das kümmert sich um die Verkabelung, aber es sagt Ihnen nichts über tatsächlich mit dem Modem. Das werden wir in einem späteren Schritt erreichen. Das Ding zu erinnern ist, dass die Kommunikationsgeschwindigkeit (Baudrate) des Modems standardmäßig aus der Fabrik kommt als 115200. So müssen Sie Ihre Arduino zu entsprechen. Ich werde in die in einem späteren Schritt als gut.

Das Bild ist vom Hersteller geliehen, weil meine zu tief begraben ist, um zu zeigen.

Während das Modem über 6 Verdrahtungspunkte verfügt, benötigen Sie nur 4 für das Arduino - + 5V, Ground, RX (Empfang), TX (Sende). Die Arduino-Pins 1 und 2 haben auch RX und TX. Die Verdrahtung wird umgekehrt, so daß die Empfangsseite der Sendeseite RX bis TX und TX bis RX zuhört. Ich empfehle entweder mit 22 Gauge festen Kern Kupferdraht für die Leitungen, so dass sie in den Arduino gedrückt werden, oder Verdrahtung in einigen männlichen führt.

Aus Gründen der Klarheit, das Telefon und das Modem beide fahren auf dem Bot so der Abstand zwischen ihnen ist sehr kurz.

Schritt 5: Auswahl der Stromquelle

4 Servoantrieb CellBot, der ferngesteuert werden kann.

4 Servoantrieb CellBot, der ferngesteuert werden kann.

Ich entschied mich ursprünglich, eine LiFePO4 Batterie zu verwenden. Das ist einer dieser Lithium-Eisen-Batterien, die in wie 5 Minuten aufgeladen werden können. Ich wählte es, weil diese spezifische hat 2 Zellen in Serie bringen die Macht auf 6,6 Volt, die gerade hoch genug für die Arduino eingebaute Spannungsregler, die Schritte nach unten (umwandelt) auf 5 Volt, aber nicht so hoch, dass die 6 Volt- T davonlaufen. Es ist fast unmöglich, die Batterie zu laden. Es ist nicht out-Gas so keine Sorgen der Sprengung.

Während es funktionierte, bekam ich an einem Punkt einige seltsame Verhalten von den Servos, die ich nicht identifizieren konnte eine andere Quelle, so schaltete ich auf Spannungsregelung bis zu 5 Volt für die Servos. Dies stellte sich als eine gute Entscheidung, wie es mir erlaubt, die Macht zum Telefon.

Die LiFePO4 Batterien haben eine extrem flache Drain-Kurve, so dass die Batterie abgelassen wird die Spannung nicht viel fallen, bis es unter 20% Leistung ist.

Ladegeräte für diese Art von Batterien kann ein wenig schwer zu kommen, aber ich fand, dass die 6 Volt 1,25 Ampere Batterie Tender Ladegerät (für alte Motorräder oder Autos) von Deltran funktioniert gut. Es stoppt das Laden bei 7,2 Volt, was genau die richtige Stoppspannung (verglichen mit meinem anderen Ladegerät) ist. Das Ladegerät schaltet sich auch nach Kontakt ein. Es stoppt automatisch. Es hat sogar eine eingebaute Schwimmer-Ladegerät. Nur stellen Sie sicher, dass Sie kaufen diese speziell, denn wenn Sie ein mit der falschen Stop-Spannung kaufen oder kaufen ein mit Desulfatierungstechnologie Sie ruinieren Ihre Batterie. Dieser Schwimmer Ladegerät nur Tritten spec in rund 10% der Kosten, die ein wenig niedrig für meinen Geschmack, aber dann wurde es nicht für diese Batterie hergestellt.

Sie können dieses Ladegerät später für eine automatisierte Ladestation verwenden, die ich noch nicht beendet habe.

One Nice Touch, die später kam, ein 3-Position-Schalter wurde hinzugefügt. Eine Position dreht den Bot auf, in der Mitte dreht bot ab, Letzte Position verbindet die Batterie ein paar Terminals für aufladen, während keine Verbindung von Bot-Aufladung. Um einen Dreistellungsschalter mit 3 Anschlüssen auf der Unterseite zu finden, gehen Sie wie folgt vor. Verbinden Sie positive Stromversorgung mit dem mittleren Pin und dann einen äußeren Pin geht zu einem positiven Ladeanschluss und der andere Pin geht an Bot Power.

Link zur Batterie:
http://www.hobbypartz.com/a123-systems-4600mah-6-6v-2s2p.html

Link zum Batteriestecker, kaufte ich meine Deans Ultra-Anschluss von einem Hobby zu speichern, aber wenn Sie kaufen diese können Sie einfach das weiße Ende abgeschnitten und die beiden Enden mit einem Verdrahtungsblock befestigen:
http://www.amazon.com/Pro-Boat-Tamiya-Charge-Adapter/dp/B000SC6R5C/ref=sr_1_24?s=toys-and-games&ie=UTF8&qid=1310661997&sr=1-24

Link zum Ladegerät:
http://www.amazon.com/Deltran-Battery-Tender-Plus-Volt/dp/B004V9FD58/ref=sr_1_29?ie=UTF8&qid=1310660649&sr=8-29

Schritt 6: Die CellBots App und das Setup

Ich verwende eine Android-App namens Cellbots von Cellbots.com, die über den Android-Marktplatz erhältlich sind. Es bietet mehrere Konfigurationen. Hier finden Sie Anfahrtsskizze ...

Schalten Sie Ihr Bluetooth-Modem ein. (Bieten Macht unabhängig davon ist es an nichts zu verbinden).
1. öffnen Sie app.
2. Klicken Sie zum Fortfahren auf die Schaltfläche Weiter.
3. Klicken Sie auf cellbot.
4. select new cellbot wählen
5. a. Geben bot Namen
B. Cellbot-Typ ist Standardcontroller
C. Cellbot Bluetooth ist FireFly (wenn Sie das BlueSmirf Modem verwendet haben).
D. Klicken Sie auf Fertig
6. Klicken Sie auf die Schaltfläche Zurück, um zur Liste der Bots zu gelangen.
7. Klicken und halten Sie die Taste für den neuen Bot.
8. Wenn das Menü erscheint, klicken Sie auf Teilen
9. Scrollen Sie nach unten zu Kommunikationsmethode und wählen Sie im Menü Custom HTTP.
10. Blättern Sie nach unten zur Cellbot-URL, und suchen Sie nach einem Kontrollkästchen Use Local Server, überprüfen Sie es auf die on-Position.
11. Beachten Sie, dass, wenn das Telefon über 3G oder 4G Zelldaten verbunden ist, wird es mit Ihnen die IP-Adresse des Zellnetzes. Ich habe nur getestet, mit wifi eingeschaltet und Zell-Service ausgeschaltet (sim ist eigentlich aus dem Telefon). Kopieren Sie die HTTP-Adresse. Dies ist, was Sie durchsuchen, um Ihren Bot zu kontrollieren.

Wenn Sie Ihre Zellverbindung verwenden, sind Sie fertig.

Wenn Sie mit wifi dann haben Sie mehr zu tun.
1. Sie müssen in Ihren Router anmelden, und gehen Sie in Ihren Port-Forwarding Abschnitt und nach vorn Port 8080 Besucher auf die IP-Adresse, die auf dem Telefon aufgeführt wurde. (Beachten Sie jede Port-Forwarding ein Netzwerk möglicherweise anfälliger macht auf eigene Gefahr zu werden gehackt, so zu tun. Um mir dieses Risiko zu verringern, verbunden ich mein wifi Telefon zu mir nach Hause Fios (Internet-Provider) Router / Modem-Combo und fügte dann einen zweiten Router hinter dem ersten, den Rest meines Heimnetzwerk zu verbinden, so, wenn das Telefon gehackt wird, müssen sie noch über den zweiten Router bekommen in das Netzwerk zu erhalten.)
2. Gehen Sie zu http://www.whatismyip.com/, um Ihre Router-IP-Adresse zu erhalten.
3. Fügen Sie die Portnummer von 8080 zu dieser Adresse hinzu und kopieren Sie die HTTP-Adresse nach unten. Dies ist, was Sie verwenden, um zu gehen, um Ihren Bot zu kontrollieren. Beispiel nehmen 50.99.99.99 und konvertieren zu http://50.99.99.99:8080/ Verwenden Sie diese, um Ihren Bot zu besuchen.

Weitere Anweisungen werden in einem späteren Schritt gegeben, um tatsächlich einzurichten und zu verwenden.

Schritt 7: Der Arduino-Code (nicht modifiziert)

aufrechtzuerhalten.
Servogetriebener Roboter mit serieller Eingabe

Sucht einen Satz ASCII-Zeichen in dem zu sendenden Signal
Befehle an einen Satz von Servos, um einen kleinen Roboter anzutreiben. LED-Stift # 13
Leuchtet während der Servobewegung und blinkt für Drehzahländerungen.

Die minimale Schaltung:
* LED an Pin 13 an Masse (oder verwenden Sie eingebaute LED auf den meisten Arduino's)
* Servos mit Signaldrähten, die an Pins 3 und 5 angeschlossen sind (5V Strom und Masse für
Servos können auch in Arduino verdrahtet werden, oder Strom kann von externen Quelle kommen)
* Serieller Eingang an RX Pin 0 angeschlossen
* Serieller Ausgang an TX Pin 1 angeschlossen

Zusätzliche Schaltungen (optional):
* Vorwärts gerichtete Ultraschallentfernungsmesser auf digitalem Stift 7
* Nach unten gerichtete Ultraschall-Entfernungsmesser auf Digital Pin 8

Hinweis: Wenn Sie noch kein serielles Gerät zur Verbindung mit haben, können Sie die
Eingebaute serielle Monitor in der Arduino-Software, wenn die Verbindung über USB zum Testen.
Achten Sie auch darauf, RX & TX Pins von anderen Geräten zu trennen, wenn Sie versuchen zu programmieren
Das Arduino über USB.

erstellt 2010
Von Tim Heath, Ryan Hickman und Glen Arrowsmith
Besuchen Sie http://www.cellbots.com für weitere Informationen
* /

#include <Servo.h>
#include <EEPROM.h>

#define BUFFERSIZE 20
#define EEPROM_servoCenterLeft 1
#define EEPROM_servoCenterRight 2
#define EEPROM_speedMultiplier 3
#define EEPROM_servosForcedActive 4
#define EEPROM_lastNeckValue 5

#define DEFAULT_servoCenterLeft 90
#define DEFAULT_servoCenterRight 90
#define DEFAULT_speedMultiplier 5
#define DEFAULT_servosForcedActive false
#define DEFAULT_servosForcedActive false
#define DEFAULT_lastNeckValue 255

// ** ALLGEMEINE EINSTELLUNGEN ** - Allgemeine Einstellungen
Boolean DEBUGGING = false; // Gibt an, ob das Debuggen der Ausgabe über die serielle Schnittstelle defauly aktiviert ist (kann mit dem Befehl 'h' umgedreht werden)
Const int führtePin = 13; // LED leuchtet, während Servos laufen
Char * driveType = "servo"; // Verwenden Sie "Motor", wenn Bots einen DC-Motortreiber oder "Servo" für Servos, die die Räder versorgen, haben

// ** SERVO-EINSTELLUNGEN ** - Konfigurierbare Werte basierend auf Pins und Servo Richtung
Const int servoPinLeft = 9;
Const int servoPinRight = 10;
Const int servoPinHead = 12; // Servo steuert den Winkel des Telefons
Const int servoDirectionLeft = 1; // Für Rückwärtsgang 1 oder -1 verwenden
Const int servoDirectionRight = -1; // Für Rückwärtsgang 1 oder -1 verwenden
Int servoCenterLeft = DEFAULT_servoCenterLeft; // PWM-Einstellung für keine Bewegung am linken Servo
Int servoCenterRight = DEFAULT_servoCenterLeft; // PWM-Einstellung für keine Bewegung auf dem rechten Servo
Int servoPowerRange = 30; // PWM Bereich von der Mitte, auf die Servos am besten reagieren (auf 30 eingestellt, um im 60-120 Bereich außerhalb der Mitte von 90 zu arbeiten)
Const long maxRunTime = 2000; // Maximale Laufzeit für Servos ohne zusätzlichen Befehl. * Verwenden Sie einen Befehl, um dies zu setzen. aufrechtzuerhalten.
Int speedMultiplier = DEFAULT_speedMultiplier; // Standard-Geschwindigkeitseinstellung. Verwendet einen Bereich von 1-10
Int lastNeckValue = DEFAULT_lastNeckValue;

// ** MOTOR-TREIBER-EINSTELLUNGEN ** - Für die Verwendung mit Brettern wie dem Pololu-Motortreiber (verwendet auch die linken / rechten Servo-Pin-Einstellungen oben)
Int leftMotorPin_1 = 9;
Int leftMotorPin_2 = 8;
Int leftMotorPin_1 = 10;
Int rightMotorPin_2 = 11;
Int motor_stby = 12;

// ** RANGE FINDING *** - Die folgenden Einstellungen gelten für Ultraschall-Entfernungsmesser. OK zu lave wie-ist, wenn Sie sie nicht auf Ihrem Roboter haben
Lange Dist, Mikrosekunden, cm, Zoll; // Wird vom Entfernungsmesser zur Berechnung von Entfernungen verwendet
Const int rangePinForward = 7; // Digitaler Pin für den vorwärts gerichteten Entfernungsmesser (für Objektabstand vor Bot)
Const int rangeToObjectMargin = 0; // Bereich in cm, um Objekt weiterzuleiten (bot stoppt, wenn Entfernung näher als diese - auf 0 gesetzt, wenn kein Sensor)
Const int rangePinForwardGround = 8; // Digitale Stift für nach unten gerichtete Entfernungsmesser auf der Vorderseite (für Rand der Tisch-Erkennung)
Const int rangeToGroundMargin = 0; // Bereich in cm zur Tabelle (bot stoppt, wenn der Abstand größer ist als dieser auf 0 gesetzt wird, wenn kein Sensor vorhanden ist)
Const int rangeSampleCount = 3; // Anzahl der zu messenden Messbereiche und Mittelwert für einen stabileren Wert

// Erstellen von Servoobjekten zur Steuerung der Servos
Servo myservoLeft;
Servo myservoRight;
Servo myservoHead;

// Für diese Parameter ist keine Konfiguration erforderlich
Boolean servosActive = false; // Nehmen Sie an, dass Servos sich nicht bewegen, wenn wir anfangen
Boolean servosForcedActive = DEFAULT_servosForcedActive; // hört nur auf, wenn es gefährlich ist
Unsigned long stopTime = millis (); // wird für die Berechnung der Laufzeit für Servos verwendet
Char incomingByte; // Zeigt eingehende serielle Werte an
Char msg [8]; // Zur Rückgabe von seriellen Nachrichten
Char inBytes [BUFFERSIZE]; // Puffer für serielle Nachrichten
Int serialIndex = 0;
Int serialAvail = 0;

Void setup () {
PinMode (servoPinLeft, OUTPUT);
PinMode (servoPinRight, OUTPUT);
PinMode (servoPinHead, OUTPUT);
PinMode (leftMotorPin_1, OUTPUT);
PinMode (leftMotorPin_2, OUTPUT);
PinMode (rightMotorPin_1, OUTPUT);
PinMode (rechtsMotorPin_2, OUTPUT);
PinMode (ledPin, OUTPUT);
DigitalWrite (servoPinLeft, 0);
DigitalWrite (servoPinRight, 0);
DigitalWrite (servoPinHead, 0);
DigitalWrite (motor_stby, HIGH);
Serial.begin (115200);
ServoCenterLeft = readSetting (EEPROM_servoCenterLeft, servoCenterLeft);
ServoCenterRight = readSetting (EEPROM_servoCenterRight, servoCenterRight);
SpeedMultiplier = readSetting (EEPROM_speedMultiplier, speedMultiplier);
ServosForcedActive = readSetting (EEPROM_servosForcedActive, servosForcedActive);
LastNeckValue = readSetting (EEPROM_lastNeckValue, lastNeckValue);
If (lastNeckValue! = DEFAULT_lastNeckValue) {
MyservoHead.attach (servoPinHead);
MyservoHead.write (lastNeckValue);
aufrechtzuerhalten.
aufrechtzuerhalten.

// Sicher lesen EEPROM
Int readSetting (int memoryLocation, int defaultValue) {
Int value = EEPROM.read (memoryLocation);
Wenn (Wert == 255) {
EEPROM.write (memoryLocation, defaultValue);
aufrechtzuerhalten.
Rückgabewert;
aufrechtzuerhalten.

// Setzt die EEPROM-Einstellungen auf die Standardwerte
Void SetEepromsToDefault () {
ServosForcedActive = DEFAULT_servosForcedActive;
SpeedMultiplier = DEFAULT_speedMultiplier;
ServoCenterRight = DEFAULT_servoCenterRight;
ServoCenterLeft = DEFAULT_servoCenterLeft;
LastNeckValue = DEFAULT_lastNeckValue;
EEPROM.write (EEPROM_servosForcedActive, DEFAULT_servosForcedActive);
EEPROM.write (EEPROM_speedMultiplier, DEFAULT_speedMultiplier);
EEPROM.write (EEPROM_servoCenterRight, DEFAULT_servoCenterRight);
EEPROM.write (EEPROM_servoCenterLeft, DEFAULT_servoCenterLeft);
EEPROM.write (EEPROM_lastNeckValue, DEFAULT_lastNeckValue);
Wenn (DEBUGGING) {
Serial.println ( "Alle EEPROM-Werte auf Standardwerte gesetzt.");
aufrechtzuerhalten.
aufrechtzuerhalten.

// Direktionale Textbefehle ( "vorwärts" / "rückwärts") in die berechnete Servogeschwindigkeit umwandeln
Int directionValue (char * directionCommand, int servoDirection) {
If (directionCommand == "forward") {
Rückgabe (10 * speedMultiplier * servoDirection);
aufrechtzuerhalten.
Sonst if (directionCommand == "rückwärts") {
Return (-10 * speedMultiplier * servoDirection);
aufrechtzuerhalten.
sonst {
If (DEBUGGING) {Serial.println ( "Houston, wir haben ein Problem!"); aufrechtzuerhalten.
Return 0; // Versuch, den Wert auf Mitte zu setzen - das sollte nicht benötigt werden
aufrechtzuerhalten.
aufrechtzuerhalten.

// Textbefehle in PWM-Werte für den zu verschiebenden Bot umsetzen (linker Servobefehl, rechter Servobefehl)
Unsigned long moveBot (char * commandLeft, char * commandRight) {
Int valueLeft = directionValue (commandLeft, servoDirectionLeft) + servoCenterLeft;
Int valueRight = directionValue (commandRight, servoDirectionRight) + servoCenterRight;
Antriebsräder (valueLeft, valueRight);
aufrechtzuerhalten.

// Antriebsservo oder Gleichstrommotoren zum Bewegen des Roboters mit Werten im Bereich -100 bis 100 für links und rechts
Unsigned long driveWheels (int valueLeft, int valueRight) {
// Lösen Sie die beiden Servo-Pins, die das Weinen stoppen und die Motoren abschalten, damit sie die Kompasswerte nicht töten
If (valueLeft == 0 und valueRight == 0) {
MyservoLeft.detach ();
MyservoRight.detach ();
aufrechtzuerhalten.
// Fahren Sie die Räder auf der Grundlage von "Servo" driveType
If (driveType == "servo") {
ValueLeft = valueLeft * servoDirectionLeft; // Flip positiv auf negativ, falls erforderlich, basierend auf der Einstellung der Servo-Richtungswerte
ValueRight = valueRight * servoDirectionRight;
// Karte "w" Werte auf den engen Bereich, auf den die Servos reagieren
ValueLeft = map (valueLeft, -100, 100, (servoCenterLeft - servoPowerRange), (servoCenterLeft + servoPowerRange));
ValueRight = map (valueRight, -100, 100, (servoCenterRight - servoPowerRange), (servoCenterRight + servoPowerRange));
DigitalWrite (ledPin, HIGH); // LED einstellen
// Starten Sie das Servo-PWM neu und senden Sie die Befehle
MyservoLeft.attach (servoPinLeft);
MyservoRight.attach (servoPinRight);
MyservoLeft.write (valueLeft);
MyservoRight.write (valueRight);
// Einige Diagnoseinformationen über seriell ausspucken
Wenn (DEBUGGING) {
Serial.print ( "Verschieben des linken Servos");
Serial.print (valueLeft, DEC);
Serial.print ( "und rechter Servo");
Serial.println (valueRight, DEC);
aufrechtzuerhalten.
aufrechtzuerhalten.
// Fahren Sie die Räder auf der Grundlage von "motor" driveType
sonst{
// Stellen Sie die linken Motorstifte in die gewünschte Richtung ein
Wenn (WertLeft <0) {
DigitalWrite (linksMotorPin_1, LOW);
DigitalWrite (leftMotorPin_2, HIGH);
aufrechtzuerhalten.
sonst {
DigitalWrite (leftMotorPin_1, HIGH);
DigitalWrite (leftMotorPin_2, LOW);
aufrechtzuerhalten.
// Drehen Sie die Motorpins in die gewünschte Richtung
Wenn (WertRight <0) {
DigitalWrite (rechtsMotorPin_1, LOW);
DigitalWrite (rechtsMotorPin_2, HIGH);
aufrechtzuerhalten.
sonst {
DigitalWrite (rechtsMotorPin_1, HIGH);
DigitalWrite (rechtsMotorPin_2, LOW);
aufrechtzuerhalten.
// Maps "w" -Werte auf den größeren Bereich, auf den der Motor reagiert
ValueLeft = map (abs (valueLeft), 0, 100, 0, 255);
ValueRight = map (abs (valueRight), 0, 100, 0, 255);
AnalogWrite (servoPinLeft, valueLeft);
AnalogWrite (servoPinRight, valueRight);
aufrechtzuerhalten.

StopTime = millis () + maxRunTime; // Zeit, den Betrieb aufgrund der zulässigen Laufzeit zu beenden
Rückkehr stopTime;
aufrechtzuerhalten.

// Stoppen Sie den Bot
Void stopBot () {
Antriebsräder (0,0);
DigitalWrite (ledPin, LOW); // Schalten Sie die LED aus
If (DEBUGGING) {Serial.println ( "Stoppen beider Räder"); aufrechtzuerhalten.
SerialReply ( "i", "st"); // Sagen Sie dem Telefon, dass der Roboter gestoppt hat
aufrechtzuerhalten.

// Lesen und verarbeiten Sie die Werte von einem Ultraschall-Entfernungsmesser (Sie können diesen Code auch dann verlassen, wenn Sie keinen haben)
Long getDistanceSensor (int ultrasonicPin) {
// Nehmen Sie mehrere Messwerte vor, und geben Sie sie durchschnittlich an
Mikrosekunden = 0;
Für (int sample = 1; sample <= rangeSampleCount; sample ++) {
// Der Parallax PING))) wird durch einen HIGH-Impuls von 2 oder mehr Mikrosekunden ausgelöst.
// Vorab einen kurzen LOW-Impuls geben, um einen sauberen HIGH-Impuls zu gewährleisten:
// Der Maxsonar scheint dieses Teil nicht zu brauchen, aber es tut auch nicht weh
PinMode (UltraschallPin, AUSGANG);
DigitalWrite (UltraschallPin, LOW);
DelayMicroseconds (2);
DigitalWrite (UltraschallPin, HIGH);
DelayMicroseconds (5);
DigitalWrite (UltraschallPin, LOW);

// Der gleiche Pin wird verwendet, um das Signal vom Ultraschall-Detektor zu lesen: a HIGH
// Impuls, dessen Dauer die Zeit (in Mikrosekunden) vom Senden ist
// des Pings an den Empfang des Echos eines Objekts.
PinMode (UltraschallPin, INPUT);
Mikrosekunden + = pulseIn (UltraschallPin, HIGH);
DelayMicroseconds (5); // Sehr kurze Pause zwischen den Messwerten
aufrechtzuerhalten.
Microseconds = microseconds / rangeSampleCount;
// Den gemittelten Sensorwert in Zentimeter umrechnen und zurückgeben
Cm = MikrosekundenToCentimeter (Mikrosekunden);
Inches = microsecondsToInches (Mikrosekunden);
Wenn (DEBUGGING) {
Serial.print ( "Micro:"); Serial.print (Mikrosekunden);
Serial.print ( "Zoll:"); Serial.print (Zoll);
Serial.print (cm:); Serial.println (cm);
aufrechtzuerhalten.
Rückkehr cm;
aufrechtzuerhalten.

Lange MikrosekundenToCentimeter (lange Mikrosekunden) {
// Die Schallgeschwindigkeit beträgt 340 m / s oder 29 Mikrosekunden pro Zentimeter.
// Der Ping fährt hin und zurück, so dass die Strecke zu finden
// Objekt nehmen wir die Hälfte der zurückgelegten Strecke.
Rückkehr Mikrosekunden / 29/2;
aufrechtzuerhalten.

Lange MikrosekundenToInches (lange Mikrosekunden) {
// Laut Parallax-Datenblatt für den PING))), gibt es
// 73,746 Mikrosekunden pro Inch (dh der Schall bewegt sich bei 1130 Fuß pro Sekunde)
// zweite). Das ergibt die zurückgelegte Wegstrecke
// und zurück, so dass wir durch 2 teilen, um den Abstand des Hindernisses zu erhalten.
// Siehe: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
// Gleiches gilt für MaxSonar von MaxBotix
Rückkehr Mikrosekunden / 74/2;
aufrechtzuerhalten.

// Antworten auf serielle und Handles Pause und Spülen der Daten, um mit Android serielle comms
Void serialReply (char * sensorname, char * tmpmsg) {
Serial.print (sensorname);
Serial.print ( ":");
Serial.println (tmpmsg); // Senden Sie die Nachricht wieder aus der seriellen Zeile
// Warten Sie, bis der serielle Debugger heruntergefahren wird
Verzögerung (200); // Das ist eine magische Zahl
Serial.flush (); // löscht alle eingehenden Daten
aufrechtzuerhalten.

// Prüft die Entfernungsmesser, um zu sehen, ob es sicher ist, weiterzumachen (* Notwendigkeit, Weg hinzuzufügen, um zu wissen, welche Richtung wir bewegen *)
Boolean safeToProceed () {
Boolean safe = false; // Angenommen, es ist nicht sicher, um fortzufahren
// Überprüfen Sie den Abstand zum nächsten Objekt vor dem Bot und stoppen, wenn zu nah
If (rangeToObjectMargin! = 0) {// Versuche nicht, wenn Margin auf null gesetzt wird, weil es hängt, wenn kein Sensor vorhanden ist
Dist = getDistanceSensor (rangePinForward);
If (dist> rangeToObjectMargin) {
Safe = true;
aufrechtzuerhalten.
Sonst if (DEBUGGING) {Serial.print ( "Objekt zu dicht vor -");}
aufrechtzuerhalten.
// Überprüfen Sie den Abstand zum Boden vor dem Bot, um sicherzustellen, dass der Tisch noch da ist
If (rangeToGroundMargin! = 0) {// Versuche nicht, wenn Margin auf null gesetzt wird, weil es hängt, wenn kein Sensor vorhanden ist
Dist = getDistanceSensor (BereichPinForwardGround);
If (dist> rangeToGroundMargin) {
Safe = true;
aufrechtzuerhalten.
Sonst if (DEBUGGING) {Serial.print ( "Ende der Oberfläche erreicht -");}
aufrechtzuerhalten.
If (rangeToGroundMargin == 0 && rangeToObjectMargin == 0) {return true;}
Rückkehr sicher;
aufrechtzuerhalten.

// Prüfen Sie, ob genügend Zeit vergangen ist, um den Bot zu stoppen und wenn es sicher ist, fortzufahren
Void checkIfStopBot () {
If (nicht servosForcedActive und servosActive und (stopTime <millis () oder nicht safeToProceed ())) {
StopBot ();
ServosActive = false;
} Else if (nicht safeToProceed ()) {
StopBot ();
ServosActive = false;
aufrechtzuerhalten.
aufrechtzuerhalten.

// Senden des Befehls an das angeschlossene Bluetooth-Gerät, um die Kopplung einzuleiten
Void pairBluetooth () {
Serial.print ( "\ r \ n + INQ = 1 \ r \ n"); // Dies ist für die Master / Slave-Einheit von Seeedstudio (je nach Bedarf für Ihr Modell)
aufrechtzuerhalten.

// Liest die serielle Eingabe, falls verfügbar, und analysiert den Befehl, wenn der vollständige Befehl gesendet wurde.
Void readSerialInput () {
SerialAvail = Serial.available ();
// Lesen Sie, was verfügbar ist
Für (int i = 0; i <serialAvail; i ++) {
// In Puffer aufbewahren.
InBytes [i + serialIndex] = Serial.read ();
// Auf Befehlsende prüfen.

IfBytes [i + serialIndex] == '\ n' || inBytes [i + serialIndex] == ';' || inBytes [i + serialIndex] == '>') {// Verwendung; Wenn Sie Serial Monitor verwenden
InBytes [i + serialIndex] = '\ 0'; // Ende der Zeichenfolge char
ParseCommand (inBytes);
SerialIndex = 0;
aufrechtzuerhalten.
sonst {
// erwarten mehr von dem Befehl, um später zu kommen.
SerialIndex + = serialAvail;
aufrechtzuerhalten.
aufrechtzuerhalten.
aufrechtzuerhalten.

// Reinigt und analysiert den Befehl
Void parseCommand (char * com) {
Wenn (com [0] == '\ 0') {return; } // Bit der Fehlerprüfung
Int start = 0;
// start des Befehls
Während (com [start]! = '<') {
Start ++;
Wenn (com [start] == ​​'\ 0') {
//es ist nicht da. Muss alte Version sein
Start = -1;
Unterbrechung;
aufrechtzuerhalten.
aufrechtzuerhalten.
Start ++;
// Zu Beginn wechseln
Int i = 0;
Während (com [i + start - 1]! = '\ 0') {
Com [i] = com [start + i];
I ++;
aufrechtzuerhalten.
ExecCommand (com);
aufrechtzuerhalten.

Void performCommand (char * com) {
If (strcmp (com, "f") == 0) {// Weiterleiten
StopTime = Antriebsräder (speedMultiplier * 10, speedMultiplier * 10);
ServosActive = true;
} Else if (strcmp (com, "r") == 0) {// Richtig
StopTime = Antriebsräder (speedMultiplier * 10, speedMultiplier * -10);
ServosActive = true;
} Else if (strcmp (com, "l") == 0) {// Links
StopTime = Antriebsräder (speedMultiplier * -10, speedMultiplier * 10);
ServosActive = true;
} Else if (strcmp (com, "b") == 0) {// Rückwärts
StopTime = Antriebsräder (speedMultiplier * -10, speedMultiplier * -10);
ServosActive = true;
} Else if (strcmp (com, "s") == 0) {// Stop
StopBot ();
ServosActive = false;
} Else if (strcmp (com, "fr") == 0 || strcmp (com, "fz") == 0 || strcmp (com, "x") == 0) {// Lesen und drucken nach vorn Abstandssensor
Dist = getDistanceSensor (rangePinForward);
Itoa (dist, msg, 10); // Schalte den dist int in einen char
SerialReply ( "x", msg); // Abstand zur seriellen Leitung senden
} Else if (strcmp (com, "z") == 0) {// Lesen und Bedrucken von Distanzsensoren
Dist = getDistanceSensor (BereichPinForwardGround);
Itoa (dist, msg, 10); // Schalte den dist int in einen char
SerialReply ( "z", msg); // Abstand zur seriellen Leitung senden
} Else if (strcmp (com, "h") == 0) {// Hilfemodus - Debugging-Umschalten
// Drucken Sie einige grundlegende Anweisungen aus, wenn Sie das Debuggen einschalten
Wenn (nicht DEBUGGING) {
Serial.println ( "Bereit, Befehle zu hören!");
Serial.println ( "F (vorwärts), B (rückwärts), L (links), R (rechts), S (Stopp), D (Demo).");
Serial.println ( "Verwenden Sie auch die Nummern 1-9, um die Geschwindigkeit einzustellen (0 = langsam, 9 = schnell).");
aufrechtzuerhalten.
DEBUGGING =! DEBUGGING;
} Strcmp (com, "2") == 0 || strcmp (com, "3") == 0 || strcmp (com, "4" ) == 0 || strcmp (com, "5") == 0 || strcmp (com, "6") == 0 || strcmp (com, "7") == 0 || strcmp (com, 8 ") == 0 || strcmp (com," 9 ") == 0 || strcmp (com," 0 ") == 0) {
// Ich weiß, dass die vorhergehende Bedingung zweifelhaft ist, aber sie wird sich bald ändern
If (DEBUGGING) {Serial.print ( "Geschwindigkeit ändern"); aufrechtzuerhalten.
Int i = com [0];
SpeedMultiplier = i - 48; // Stellen Sie den Geschwindigkeitsvervielfacher auf einen Bereich 1-10 von den ASCII-Eingängen 0-9 ein
EEPROM.write (EEPROM_speedMultiplier, speedMultiplier);
If (DEBUGGING) {Serial.println (speedMultiplier); aufrechtzuerhalten.
// Blinken Sie die LED, um die neue Geschwindigkeitseinstellung zu bestätigen
Für (int speedBlink = 1; speedBlink <= speedMultiplier; speedBlink ++) {
DigitalWrite (ledPin, HIGH); // LED einstellen
Verzögerung (100);
DigitalWrite (ledPin, LOW); // LED ausschalten
Verzögerung (100);
aufrechtzuerhalten.
} Else if (com [0] == 'c') {// Zentrale PWM-Einstellungen für beide Servos ex: "c 90 90"
Int valueLeft = 90, valueRight = 90;
Sscanf (com, "c% d% d", & valueLeft, & valueRight); // Analysieren Sie die Eingabe in mehrere Werte
ServoCenterLeft = valueLeft;
ServoCenterRight = valueRight;
StopTime = Antriebsräder (0,0); // Servos mit 0-Wert ansteuern, der bei korrekter Kalibrierung keine Bewegung auslösen soll
ServosActive = true;
EEPROM.write (EEPROM_servoCenterLeft, servoCenterLeft);
EEPROM.write (EEPROM_servoCenterRight, servoCenterRight);
Wenn (DEBUGGING) {
Serial.print ( "Kalibrierte Servozentren bis");
Serial.print (servoCenterLeft);
Serial.print ( "und");
Serial.println (servoCenterRight);
aufrechtzuerhalten.
} Else if (strcmp (com, "i") == 0) {// Schaltet Servo in den unendlichen aktiven Modus, damit es nicht automatisch ausläuft
ServosForcedActive =! ServosForcedActive; // Stoppen Sie nur, wenn gefährlich
EEPROM.write (EEPROM_servosForcedActive, servosForcedActive);
Wenn (DEBUGGING) {
Serial.print ( "Unendliche Drehung auf");
If (servosForcedActive) {Serial.println ( "on");}
Else {Serial.println ( "off");}
aufrechtzuerhalten.
} Else if (com [0] == 'w') {// Handle "wheel" -Befehl und übersetzen in PWM-Werte ex: "w -100 100" [Bereich von -100 bis 100]
Int valueLeft = 90, valueRight = 90;
Sscanf (com, "w% d% d", & valueLeft, & valueRight); // Analysieren Sie die Eingabe in mehrere Werte
StopTime = driveWheels (WertLeft, valueRight);
ServosActive = true;
} Else if (strcmp (com, "reset") == 0) {// Setzt die eeprom-Einstellungen zurück
SetEepromsToDefault ();
} Else if (com [0] == 'n') {// Bewege den Kopf nach oben
Sscanf (com, "n% d", & lastNeckValue); // Analysieren Sie die Eingabe in mehrere Werte
MyservoHead.attach (servoPinHead);
MyservoHead.write (lastNeckValue);
EEPROM.write (EEPROM_lastNeckValue, lastNeckValue);
Wenn (DEBUGGING) {
Serial.print ( "Hals bewegt nach");
Serial.println (lastNeckValue);
aufrechtzuerhalten.
} else if (com[0] == 'p') { // Initiates Bluetooth pairing so another device can connect
pairBluetooth();
} Else {
serialReply("e", com);// Echo unknown command back
if (DEBUGGING) {
Serial.print("Unknown command: ");
Serial.println(com);
aufrechtzuerhalten.
aufrechtzuerhalten.
aufrechtzuerhalten.

// Main loop running at all times
Void Schleife ()
{
readSerialInput();
checkIfStopBot();
aufrechtzuerhalten.

Step 8: The Arduino Code adapted to my use.

//Cellbots code base rewritten.

#include <Servo.h>
#include <EEPROM.h>

Servo myservoFR;
Servo myservoFL;
Servo myservoRR;
Servo myservoRL;
Servo myservoHead;

#define BUFFERSIZE 20
#define InferFPin 0 //Front Inferred Sensor analog pin
#define InferBPin 1 //Back Inferred Sensor analog pin
#define SonarPin 2 //sonar analog pin
#define LeftEarPin 3 //left ear analog pin
#define RightEarPin 4 //right ear analog pin/
#define VoltPin 5 //analog pin 5 used for VoltageCheck detection.
#define LEDBlue 5
#define LEDGreen 6
#define LEDRed 7
#define servoPinHead 8 // Servo controlling the angle of the phone
#define FLpin 9
#define FRpin 10
#define RLpin 11
#define RRpin 12
#define ledPin 13 // LED turns on while running servos
#define regulator 20

//#define OneDeg 5.65 //setting rotational delay for equal to one degree (2 wheel carpet)
#define OneDeg 9.04 //setting rotational delay for equal to one degree (2 wheel hardwood)
// Checking battery voltage turned out to be the hardest thing I attempted. Having both battery connected and USB connected...
// gives different readings then just the battery connected. In fact the analog readings were reversed somehow.
#define shutdownVoltageCheck 978 // this number is unique to every voltage divider and battery combo. It's basically 20% of mine.
#define analogvoltconstant 144.6969

int iAnVal; // sonar sensor input
int deg;
int InferF=0;
int InferB=0;
int soundRT[72];
int soundLF[72];
int distance[72];
int tempvolt;
unsigned long BatteryIndex = 0;
unsigned long BatteryIndexThreshold= 150000; // about 10 minutes.
unsigned long RegulatorIndex;
unsigned long RegulatorTimerThreshold= 150000; // interval turn on or turn off the voltage regulator. about 10 minutes.
int VoltSampleSize=1000;
char dir ='s'; // zero's the direction the bot has been told to drive - forward, backward, right, left, stop, sets it to stop.
int power =-1;
boolean ConservePower = true; //this determines if the bot uses power saving mode.
int warmup = 1000; //delay to start setup in Milliseconds.

// No config required for these parameters
boolean servosActive = false; // assume servos are not moving when we begin
// unsigned long stopRegulatorIndex=millis(); // used for calculating the run RegulatorIndex for servos
char incomingByte; // Holds incoming serial values
char msg[8]; // For passing back serial messages
char inBytes[BUFFERSIZE]; //Buffer for serial in messages
int serialIndex = 0;
int serialAvail = 0;

// ** RANGE FINDING *** - settings are for ultrasonic range finders. OK to lave as-is if you don't have them on your robot
long dist, microseconds, cm, inches; // Used by the range finder for calculating distances
const int rangePinForward = 2; // Digital pin for the forward facing range finder (for object distance in front of bot)
const int rangeToObjectMargin = 25; //(bot will stop when distance closer than this - set to 0 if no sensor)
const int rangePinForwardGround = 0; // Digital pin for downward facing range finder on the front (for edge of table detection)
const int rangeToGroundMargin = 0; // Range in cm to the table (bot will stop when distance is greater than this set to 0 if no sensor)
const int rangeSampleCount = 3; // Number of range readings to take and for a more stable value

//=============================================================================
Void setup () {

Serial.println("start setup!");
delay(warmup);

//********************** set input output mode *****************************
pinMode(LEDBlue, OUTPUT);
pinMode(LEDGreen, OUTPUT);
pinMode(LEDRed, OUTPUT);
pinMode(servoPinHead, OUTPUT);
pinMode(FLpin,OUTPUT);
pinMode(FRpin,OUTPUT);
pinMode(RLpin,OUTPUT);
pinMode(RRpin,OUTPUT);
PinMode (ledPin, OUTPUT);
pinMode(regulator, OUTPUT);

// digitalWrite(servoPinHead,0);

Serial.begin (9600);
Serial3.begin(115200);

// lastNeckValue = readSetting(EEPROM_lastNeckValue, lastNeckValue);
// if (lastNeckValue != DEFAULT_lastNeckValue) {
// myservoHead.attach(servoPinHead);
// myservoHead.write(lastNeckValue);
//}

//***************************** Clear Sensor Map ************************
for (deg = 0; deg < 72; deg = deg + 1) {
soundRT[deg]=0;
soundLF[deg]=0;
distance[deg]=0;
aufrechtzuerhalten.

//***************************** default to servos turned off *************
myservoFR.detach();
myservoFL.detach();
myservoRR.detach();
myservoRL.detach();

LEDOff();

pinMode(regulator, OUTPUT); // set pin 20 to output mode so the VoltageCheck regulator can be turned on and off.
digitalWrite(regulator, LOW); // start the VoltageCheck regulator in the off position.

Serial.println("end setup!");

aufrechtzuerhalten.
//====================================================================================

// Replies out over serial and handles pausing and flushing the data to deal with Android serial comms
void serialReply(char* sensorname, char* tmpmsg) {
Serial3.print(sensorname);
Serial3.print(":");
Serial3.println(tmpmsg); // Send the message back out the serial line
//Wait for the serial debugger to shut up
Verzögerung (200); //this is a magic number
Serial3.flush(); //clears all incoming data
aufrechtzuerhalten.

// Check if enough RegulatorIndex has elapsed to stop the bot and if it is safe to proceed
boolean checkIfStopBot() {
int tempfrontsonar = Averagefive(SonarPin);
//Serial.print("front sonar: ");
//Serial.println(tempfrontsonar);
int tempfrontinfer = Averagefive(InferFPin);
//Serial.print("front infer: ");
//Serial.println(tempfrontinfer);
int tempbackinfer = Averagefive(InferBPin);
//Serial.print("back infer: ");
//Serial.println(tempbackinfer);
//Serial.println();

if ((dir=='f') && ((tempfrontsonar < rangeToObjectMargin) || (tempfrontinfer < 200))) {
Stop();
servosActive = false;
Return true;
} else if (dir=='b') {
if (!((tempbackinfer < 650) && (tempbackinfer > 450))) {
Stop();
servosActive = false;
Return true;
aufrechtzuerhalten.
aufrechtzuerhalten.
Return false;
aufrechtzuerhalten.

// Send command to attached Bluetooth device to initiate pairing
void pairBluetooth() {
Serial3.print("\r\n+INQ=1\r\n"); // This is for Seeedstudio master/slave unit (change as needed for your model)
aufrechtzuerhalten.

// Reads serial input if available and parses command when full command has been sent.
void readSerialInput() {
serialAvail = Serial3.available();
//Read what is available
for (int i = 0; i < serialAvail; i++) {
//Store into buffer.
inBytes[i + serialIndex] = Serial3.read();
//Check for command end.

if (inBytes[i + serialIndex] == '\n' || inBytes[i + serialIndex] == ';' || inBytes[i + serialIndex] == '>') { //Use ; when using Serial Monitor
inBytes[i + serialIndex] = ''; //end of string char
parseCommand(inBytes);
serialIndex = 0;
aufrechtzuerhalten.
sonst {
//expecting more of the command to come later.
serialIndex += serialAvail;
aufrechtzuerhalten.
aufrechtzuerhalten.
aufrechtzuerhalten.

// Cleans and parses the command
void parseCommand(char* com) {
if (com[0] == '') { return; } //bit of error checking
int start = 0;
//get start of command
while (com[start] != '<'){
start++;
if (com[start] == '') {
//its not there. Must be old version
start = -1;
Unterbrechung;
aufrechtzuerhalten.
aufrechtzuerhalten.
start++;
//Shift to beginning
Int i = 0;
while (com[i + start - 1] != '') {
com[i] = com[start + i];
I ++;
aufrechtzuerhalten.
performCommand(com);
aufrechtzuerhalten.

void LEDWhite() {
DigitalWrite (7, LOW);
DigitalWrite (6, LOW);
DigitalWrite (5, LOW);
aufrechtzuerhalten.

void LEDOff() {
DigitalWrite (7, HIGH);
DigitalWrite (6, HIGH);
DigitalWrite (5, HIGH);
aufrechtzuerhalten.

void Detach() {
//Serial.println("detach servos!");
myservoFR.detach();
myservoFL.detach();
myservoRR.detach();
myservoRL.detach();
// delay(150);
aufrechtzuerhalten.

void Attach() {
//Serial.println("Attach servos!");
myservoFR.attach(FRpin);
myservoFL.attach(FLpin);
myservoRR.attach(RRpin);
myservoRL.attach(RLpin);
digitalWrite(regulator, HIGH);
aufrechtzuerhalten.

void Forew() {
//Serial.println("*** Forward!");
dir='f';
if (not checkIfStopBot()) {
Attach();
myservoFR.write(180);
myservoFL.write(0);
myservoRR.write(180);
myservoRL.write(0);
RegulatorIndex=0;
servosActive = true;
aufrechtzuerhalten.
aufrechtzuerhalten.

void Backw () {
//int Tempdist = Averagefive(InferFPin);
//Serial.print("backward distance: ");
//Serial.println(Tempdist);
//Serial.println();
dir='b';
if (not checkIfStopBot()){
//Serial.println("*** Backward!");
Attach();
myservoFR.write(0);
myservoFL.write(180);
myservoRR.write(0);
myservoRL.write(180);
RegulatorIndex=0;
servosActive = true;
aufrechtzuerhalten.
aufrechtzuerhalten.

void Stop () {
Serial.println("*** Stop!");
myservoFR.detach();
myservoFL.detach();
myservoRR.detach();
myservoRL.detach();
dir='s';
RegulatorIndex=0;
serialReply("i", "st"); // Tell the phone that the robot stopped ###
servosActive = false;
aufrechtzuerhalten.

void Left () {
Serial.println("*** Rotate Left!");
Attach();
myservoFR.write(180);
myservoFL.write(180);
myservoRR.write(180);
myservoRL.write(180);
dir='l';
RegulatorIndex=0;
servosActive = true;
aufrechtzuerhalten.

void Right () {
Serial.println("*** Rotate Right!");
Attach();
myservoFR.write(0);
myservoFL.write(0);
myservoRR.write(0);
myservoRL.write(0);
dir='r';
RegulatorIndex=0;
servosActive = true;
aufrechtzuerhalten.

void CircleRt () {
Serial.println("*** Circle Right!");
Attach();
myservoFR.write(95);
myservoFL.write(0);
myservoRR.write(95);
myservoRL.write(0);
RegulatorIndex=0;
aufrechtzuerhalten.

void CircleLf () {
Serial.println("*** Circle Left!");
Attach();
myservoFR.write(180);
myservoFL.write(85);
myservoRR.write(180);
myservoRL.write(85);
RegulatorIndex=0;
aufrechtzuerhalten.

void mydelay (int degress) {
//Serial.println("mydelay start");
delay (int(OneDeg * degress));
//Serial.println("mydelay end");
aufrechtzuerhalten.

int Averagefive(int listenpin) {
int average = 12;
int listen[average];
int index1;
int highindex = 0;
int high = 0;
int lowindex = 0;
int low = 1000;
int total = 0;

for (index1 = 0; index1 < average; index1 = index1 + 1) {
listen[index1]= analogRead(listenpin);
// Serial.println(listen[index1]);
aufrechtzuerhalten.

for (index1 = 0; index1 < average; index1 = index1 + 1) {
if (listen[index1] > high) {
high = listen[index1];
highindex = index1;
aufrechtzuerhalten.
aufrechtzuerhalten.

for (index1 = 0; index1 < average; index1 = index1 + 1) {
if (listen[index1] < low) {
low = listen[index1];
lowindex = index1;
aufrechtzuerhalten.
aufrechtzuerhalten.

for (index1 = 0; index1 < average; index1 = index1 + 1) {
if ((index1 != highindex) && ( index1 != lowindex)) {
total = total + listen[index1];
aufrechtzuerhalten.
aufrechtzuerhalten.

total = int(total / (average-2));
//Serial.print ("average: ");
//Serial.println(total);
return total;
aufrechtzuerhalten.

void Listen() {
Serial.println("====== Listen ======!");
for (deg = 0; deg < 71; deg = deg + 1) {
// soundRT[deg]= Averagefive(RightEarPin); // listen to right ear and assign value to array
// soundLF[deg]= Averagefive(LeftEarPin); // listen to left ear and assign value to array
distance[deg] = Averagefive(SonarPin); // read a value from the sensor
Serial.println(distance[deg]); // display value written to distance array for this direction
Right();
mydelay(5);
Stop();
aufrechtzuerhalten.
Stop();
aufrechtzuerhalten.

void Course() {
int BestDistDeg = 0;
int BestDist = 0 ;
for (deg = 0; deg < 71; deg = deg + 1) {
// soundRT[deg]= analogRead(RightEarPin); // listen to right ear and assign value to array
// soundLF[deg]= analogRead(LeftEarPin); // listen to left ear and assign value to array
if (distance[deg+1] > distance[BestDistDeg]) {
BestDistDeg = deg + 1;
aufrechtzuerhalten.
Serial.print("BestDist=");
Serial.println(distance[BestDistDeg]);
Serial.println(BestDistDeg); // display value written to distance array for this direction
aufrechtzuerhalten.
Left();
mydelay((71-BestDistDeg) * 5); //Rotate Right until course matching longest distance is attained.
Stop();
Forew();
aufrechtzuerhalten.

void ForewardBackward() {
Serial.println("*** Foreward Backward test Start!");
Forew();
Verzögerung (2000);
Stop();
Verzögerung (2000);
Backw();
Verzögerung (2000);
Stop();
Verzögerung (2000);
Serial.println("*** Foreward Backward test End!");
aufrechtzuerhalten.

void base(){
myservoFR.detach();
myservoFL.detach();
myservoRR.detach();
myservoRL.detach();
Verzögerung (2500);
myservoFR.attach(FRpin);
myservoFL.attach(FLpin);
myservoRR.attach(RRpin);
myservoRL.attach(RLpin);
Serial.println('sending 110');
myservoFR.write(180);
myservoFL.write(0);
myservoRR.write(180);
myservoRL.write(0);
Verzögerung (2500);
myservoFR.detach();
myservoFL.detach();
myservoRR.detach();
myservoRL.detach();
Verzögerung (2500);
myservoFR.attach(FRpin);
myservoFL.attach(FLpin);
myservoRR.attach(RRpin);
myservoRL.attach(RLpin);
Serial.println('sending70');
myservoFR.write(0);
myservoFL.write(180);
myservoRR.write(0);
myservoRL.write(180);
Verzögerung (2500);
aufrechtzuerhalten.

void degreetest() {
Serial.println("degreetest start");
Stop();
Eine Verzögerung (5000);
Right();
mydelay(360);
Serial.println("degreetest end");
aufrechtzuerhalten.

void Signalblink() {
LEDWhite();
Verzögerung (500);
LEDOff();
Verzögerung (500);
aufrechtzuerhalten.

void forwardinfertest() {
Verzögerung (500);
Serial.print("forward infered senor: ");
Serial.println(analogRead(InferFPin));
//danger threshold <200
aufrechtzuerhalten.

void backwardinfertest() {
Verzögerung (500);
Serial.print("backward infered senor: ");
Serial.println(analogRead(InferBPin));
//danger threshold <300
aufrechtzuerhalten.

void sonartest() {
Verzögerung (500);
Serial.print("Sonar senor: ");
Serial.println(analogRead(SonarPin));
//danger threshold <30
aufrechtzuerhalten.

int VoltageCheck(){

int index1 =0;
double voltsum = 0;
int analogvolt = 0;

for (index1 = 0; index1 < VoltSampleSize; index1 = index1 + 1) {
voltsum = voltsum + analogRead(VoltPin);
aufrechtzuerhalten.
analogvolt = int (voltsum / VoltSampleSize);
//Serial.print("VoltageCheck: ");
//Serial.print("analag volt: ");
//Serial.println(analogvolt);
//Serial.print("actual volt: ");
//Serial.println((analogvolt / analogvoltconstant));
//Serial.println();
return analogvolt;
aufrechtzuerhalten.

void BatteryCheckLED()
{
if (VoltageCheck() > shutdownVoltageCheck) {
digitalWrite(LEDRed, LOW);
digitalWrite(LEDGreen, HIGH);
} Else {
digitalWrite(LEDRed, HIGH);
digitalWrite(LEDGreen, LOW);
aufrechtzuerhalten.
BatteryIndex = 0;
aufrechtzuerhalten.

void RegulatorControlToggle()
{
power = power * -1;
if (power == 1) {
digitalWrite(regulator, HIGH);
aufrechtzuerhalten.
if (power == -1) {
digitalWrite(regulator, LOW);
aufrechtzuerhalten.
RegulatorIndex = 0;
aufrechtzuerhalten.

void Miser()
{
RegulatorIndex = RegulatorIndex + 1;
if (RegulatorIndex == RegulatorTimerThreshold) RegulatorControlToggle();
aufrechtzuerhalten.

//********************************************* end mine *******************************************

void performCommand(char* com) {
float volt=0;

if (strcmp(com, "f") == 0 ) { // Forward
Forew();
} else if (strcmp(com, "r") == 0) { // Right
Right();
} else if (strcmp(com, "l") == 0) { // Left
Left();
} else if (strcmp(com, "b") == 0) { // Backward
Backw();
} else if (strcmp(com, "s") == 0) { // Stop
Stop();
} else if (strcmp(com, "fr") == 0 || strcmp(com, "fz") == 0 || strcmp(com, "x") == 0) { // print forward facing distance sensor
dist = Averagefive(SonarPin);
itoa(dist, msg, 10); // Turn the dist int into a char
serialReply("x", msg); // Send the distance out the serial line
} else if (strcmp(com, "z") == 0) { // Read and print ground facing distance sensor
dist = Averagefive(SonarPin); // dist = getDistanceSensor(rangePinForwardGround);
itoa(dist, msg, 10); // Turn the dist int into a char
serialReply("z", msg); // Send the distance out the serial line
Serial.println(dist);
} else if (strcmp(com, "v") == 0){ // Read and print VoltageCheck
volt = VoltageCheck();
itoa(volt, msg, 10); // Turn the volt int into a char
Serial.println(volt);
serialReply("v", msg); // Send the distance out the serial line
} else if (strcmp(com, "h") == 0) { // Help mode - debugging toggle
//Signalblink();
} else if (com[0] == 'n') { // Move head up
//sscanf (com,"n %d",&lastNeckValue); // Parse the input into multiple values
//myservoHead.attach(servoPinHead);
// myservoHead.write(lastNeckValue);
//EEPROM.write(EEPROM_lastNeckValue, lastNeckValue);
// if (DEBUGGING) {
// Serial.print("Neck moved to ");
// Serial.println(lastNeckValue);
//}
} else if (com[0] == 'p') { // Initiates Bluetooth pairing so another device can connect
pairBluetooth();
} Else {
serialReply("e", com);// Echo unknown command back
// if (DEBUGGING) {
// Serial.print("Unknown command: ");
// Serial.println(com);
//}

// 0-9, w, n, w, i, c, h, d for demo,
aufrechtzuerhalten.
aufrechtzuerhalten.

// =========================== Main loop running at all RegulatorIndexs =====================================
Void Schleife ()
{
readSerialInput();
checkIfStopBot();

BatteryIndex = BatteryIndex + 1;
if (BatteryIndex == BatteryIndexThreshold) BatteryCheckLED();

if (ConservePower) Miser();
aufrechtzuerhalten.

Step 9: Firing it up and moving it about.

Related Reading