PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Roomba gezielt saugen lassen



Chris266
16.05.2007, 12:49
Hallo zusammen,

ich tüftele seit Oktober 06 an einem Gedanken der mich nicht mehr los lässt.

Ich plane einen Roomba Staubsaugerroboter gezielt saugen zu lassen. Damit meine ich dass er keine zufälligen Drehungen mehr durchführt wenn er irgendwo aneckt sondern nach "Plan" saugt. D.h. er merkt sich wo er schon war und berechnet den Weg zu den noch nicht gereinigten Stellen.

Ich erhoffe mir dadurch eine schnellere und effizientere Reinigungszeit.

An Hardware habe ich inzwischen alles was ich brauche.

Ich werde den Roomba um einen IR Sharp Sensor ergänzen und um einen AtMega8.

Dieser soll über die SCI Schnittstelle mit dem Roomba kommunizieren und wird "OnBoard" sein.

Aufgrund des geringen Speichers des AtMega 8 wird er nur Flächen bis MAXIMAL 144qm in seiner Karte speichern können.

Bisher habe ich in Borland C++ einige Simulationen laufen lassen um prüfen zu können ob die Routinen auch tatsächlich funktionieren.

Problematisch wird es aber dann wenn diese Algorithmen die Sharp Sensorwerte erhalten statt meiner ideal simulierten Sharp Sensorwerte.

Erste Tests zeigten zwar dass der Sharp recht zuverlässige Signale liefert, aber ich schätze der Teufel steckt wie immer im Detail. Entsprechend werden sich wohl die Odometriesensoren des Roombas verhalten. #-o

Für die Karte habe ich mir einen Algo ausdenken müssen der ähnlich wie der A Algo arbeitet, jedoch ohne Rekursive Funktionsaufrufe (wg. Stack) und mit möglichst sehr wenig Speicher auskommt (da insgesamt nur 1024 Bytes an RAM existiert).

Grob erklärt habe ich 900 Bytes für die Karte reserviert bzw. 30x30 Felder mit je einem Byte verwendet. Wird für jedes Feld eine Fläche von 40cm Höhe/Breite angenommen (entspricht dem Durchmesser des Roomba) so entsteht hierbei eine Fläche von 30x0,4mx30x0,4m=144qm

In diesem einem Byte befinden sich zwei Bits die den Zustand eines Feldes beschreiben:

a) dieses Feld ist bereits gereinigt/überfahren worden
b) in diesem Feld befindet sich ein Hinderniss

Die restlichen sechs Bits verwende ich für einen entfernungsmerker und wird von meinem modifizierten A Algo benötigt.

Nachtrag: Im AVR Studio 4 hat die Simulation des Pathfinding bei 4 Mhz den Weg nach spätestens 754ms gefunden (ohne Compileroptimierungen). Ich denke dies ist mehr als akzeptabel.

Grüße!

BlueNature
16.05.2007, 19:25
Nettes Projekt, daran dachte ich auch einmal in kommenden Monaten einfach just for Fun einfach mal die Schnittstelle zu adaptieren. Ich besitze auch einen Roomba SE. Nur zur Zeit steht noch ein Umzug im Weg für derartige Projekte, so das ich da erst sppäter dazukommen werde. Bis dahin wird er so seinen Dienst verrichten müssen, was er eigentlich auch wirklich gut kann. Bei Interesse kann ich dir Bilder vom Innenleben zukommen lassen. Ich habe seine "Innereien" relativ genau angesehen da ich damals dachte einfach eine neue Hauptplatine zu entwerfen die dann Open-Source ist, nicht wie der orginale ein maskenprogrammierten µC der nur noch Sensordaten nach außen liefert und Steuerdaten an die Antriebe. Aber denke meine Variante wird ohne Einrgiff ablaufen. Eine Funkschnittstelle die den eh laufenden Server konnektiert und dort die richtige Navi schreiben. Einen µC nur als besseres Interface nutzen.

Grüße Wolfgang

Chris266
17.05.2007, 21:29
Ohne Eingriff habe ich auch vor, d.h. die Roomba Elektronik nicht modifizieren. Dementsprechend brauche ich nichts vom Innenleben wissen.
Eine Funkschnittstelle wäre super, er fährt mir sonst öfters über das derzeitige Kommunikationskabel zwischen Roomba und Laptop.

Kam heute dazu etwas zu testen, hier meine Resultate:

habe meinen AtMega 8 falsch gefused, nun isser nix mehr wert. :-(

Ich war jedoch in der Lage ein kleines Controll-Center zu programmieren (in Borland C++) mit dessen Hilfe ich den Roomba vom Laptop aus steuern kann:

- gerade aus fahren
- rückwärts fahren
- auf der Stelle drehen
- Geschwindigkeit regeln
- Bürste, Sauger und Eckfängermotor ein/ausschalten

Hierzu habe ich einen USB->seriell Adapter verwendet. D.h. mein 5m langes USB Kabel ist nun mit dem Roomba und dem Laptop verbunden.

Eine echte gerade aus Fahrt kann er nicht, er fährt eine leichte Kurve. Ist aber nicht weiter schlimm da ich vom Roomba dies mitgeteilt bekomme um wieviel Grad er sich bei der gerade aus Fahrt gedreht hat.

Bevor ich nun den Sharp Sensor anschließen kann muss ich mir erst wieder einen neuen AtMega8 bestellen.

Habe noch eine Internetseite gefunden wo ein fertiger AtMega168 angeboten wird der direkt in die SCI Schnittstelle des Roomba passt und sich auch programmieren lässt:

http://www.elementdirect.com/wiki/tiki-index.php?page=Mind+Control+Documentation

Leider kann ich dort meinen Sharp nicht anschließen.

BlueNature
18.05.2007, 05:49
Wie wäre es mit einem Pollin Funkmodul RFM12 Sende-/Empfangsmodul? Das wäre sicher genau die Kragenweite die man da benötigen wird.

http://www.pollin.de/shop/images/article/small/K810049.JPG

Grüße Wolfgang

Chris266
19.05.2007, 14:59
Danke für den Tip. Das Funkmodul ist ja richtig günstig (knapp 8 Euro). Ich bevorzuge jedoch ein Funkmodul dass ausreichend dokumentiert ist und hier im Forum Menschen sind die ich Fragen kann falls ich Probleme haben sollte. Also eher etwas von Robotikhardware oder so.

Habe mir heute einen neuen AtMega 8 bestellt, zusammen mit einem neuen Stk500 Programmer. Ich musste feststellen dass das AvrStudio 4 keinen Stk200 Programmer unterstützt.

Bis der AtMega 8 kommt, werde ich, sofern ich heute Abend dazu komme, meinen Mega32 auf den Roomba setzen mit einem Bascom Programm und dem Sharp Sensor. Ziel wird es sein den Roomba mit dem Sharp Sensor mal eine 360 Grad drehung durchführen zu lassen. Als echtes Kartenmaterial werden die Messergebnisse noch nichts taugen da die Analoge Ausgangsspannung leider nicht linear zur Entfernung ist. Wird noch eine Menge Arbeit werden. Ich plane die Messwerte später im EEProm zu hinterlegen welcher Messwert welcher Entfernung entspricht, ggf mit einer Interpolation.

Habe gestern noch meinen A Algo etwas optimiert, das dachte ich zumindest: die Dauer bis ein Weg zum Ziel gefunden wird hat sich nicht verkürzt, lediglich die Codelänge.

Was mit ebenfalls Sorgen bereitet:

Ich kann den Roomba nicht gezielt eine Strecke fahren lassen da entgegen meiner Annahme die zurück zu legende Wegstrecke nicht dem Roomba über die SCI Schnittstelle mitgeteilt werden kann. Ich kann lediglich mitteilen in welchem Winkel (Radius) und mit welcher Geschwindigkeit.
Da ich die zurück gelegte Wegstrecke ständig abfragen muss (Polling Verfahren) kann es demnach durchaus sein dass er über das Ziel hinaus schießt.
Beispielsweise auch wenn ein Bumper ein Hinderniss erkennt.
Bei einer Baudrate von 57600 Baud könnte ich im Idealfall alle 4ms neue Informationen vom Roomba erhalten.
Bei einer Geschwindigkeit von 500mm/sekunde kann es also sein dass die 4ms nicht ausreichen um bei einem Hinderniss die Motoren noch schnell genug abschalten zu lassen (auch das KOmmando STOP muss schließlich gesendet werden). Im Augenblick habe ich keinen Nerv das auszurechnen.

Heute gilt meine Aufmerksamkeit nur dem Sharp Sensor und dem ollen Bascom Programm.

Chris266
20.05.2007, 13:37
Nachdem mein AtMega 8 sich verabschiedet hat, musste ich nun umdenken bis der neue kommt.

Hier mein bisheriger Prototyp mit AtMega32:

Ein Kühlkörper für die 5V Spannungsversorgung war notwendig da der Roomba bis zu 16V liefert. D.h. dieses Board bezieht seine Spannung aus der SCI Schnittstelle.
Der Sharp Sensor ist noch nicht angeschlossen da der Uhu noch trocknen muss (ganz oben).

Ganz unten ein serielles Kabel zum Laptop. Ist inzwischen kein USB Kabel mehr sondern kommuniziere nun über ein herkömmliches serielles Kabel (RS232).

Auf dem AtMega ist eine zweite serielle Schnittstelle zum Roomba softwaretechnisch realisiert worden. Nur so war es möglich das SCI Protokoll zu ergänzen.
Wenn ich nun Sensorwerte vom Laptop aus anfrage, so wird vor dem eigentlichen Datenpaket des Roombas der Sharp Sensorwert vorangestellt (siehe Bascom programm weiter unten).

Hier das bisherige PC Steuerprogramm:

http://punkt-software.de/Roomba/RoomaPCSteuerung.jpg

Wie unschwer zu erkennen zieht alles zusammen bisher etwa 260mA, ohne dass sich der Roomba bewegt!

Hier nun das Bascom Programm:


$regfile = "m32def.dat" ' ATMega 8
$framesize = 42
$swstack = 42
$hwstack = 42
$crystal = 16000000 ' Quarzfrequenz
$baud = 57600

' Dieses Programm wird zwischen Laptop und Roomba auf einem AtMega32
' installiert.
' Es kommuniziert mit dem Laptop als auch mit dem Roomba über zwei
' serielle Schnittstellen.
' Die echte serielle Schnittstelle kommuniziert mit dem PC,
' die software Schnittstelle mit dem Roomba ohne Pegelwandler!
'
' Das Programm macht dabei nichts anderes als die Daten einfach
' durch zu reichen.
' Eine Ausnahme bildet die Abfrage der Roomba Sensoren. Fordert
' der PC die Roomba Sensoren an, so wird zunächst der Sharp
' Wert ermittelt und an den PC gesendet, erst danach kommen die
' eigentlichen Sensordaten vom Roomba.
'
' Die Kommunikation mit dem Roomba geschieht hierbei über D3 und D2:

Open "comD.2:57600,8,n,1" For Output As #1
Open "comD.3:57600,8,n,1" For Input As #2

On Int1 Int0_int
Enable Int1
Config Int1 = Falling
Enable Interrupts

Config Adc = Single , Prescaler = Auto
Start Adc

Dim A As Byte
Dim Ws1 As Word
Dim Ws2 As Word
Dim Ws3 As Word
Dim Ws As Word
Dim Char As Byte
Dim Bsensor1 As Byte
Dim Cw As Byte

Bsensor1 = 0

Do

Cw = Ischarwaiting()
If Cw = 1 Then

Inputbin Char

If Bsensor1 = 1 Then
If Char = 0 Then
' Sensorwert ermitteln und senden:
Ws3 = 0
For Ws1 = 1 To 100
Ws2 = Getadc(7)
Ws3 = Ws3 + Ws2
Next Ws1
Ws = Ws3 / 100
Printbin Ws
End If
Bsensor1 = 0
End If

If Char = 142 Then
Bsensor1 = 1
End If

Printbin #1 , Char
End If

Loop


End

Int0_int:
A = Inkey(#2)
Printbin A
Gifr = Gifr Or &H40
Return

Hoffe heute Abend, wenn der Uhu getrocknet ist, den Sharp Sensor in Betrieb nehmen zu können.

BlueNature
20.05.2007, 14:22
Servus,

kannst ja um Stromverbraterei zu reduziern bei Pollin das Spannungsreglerplatinchen kaufen mit dem MC34063 (Step-Down-Regler). Dann hast auch bessere Akkulaufleistungen. 16V = 5V ist schlechte Effizienz bei gerade mal 30%...

zu deinem Sharp... ich denke das ist keine gute Lösung, zu Punktgenau udn damit zu anfällig auf das Übersehen von Objekten udn damit Kollisionen, nimm besser dafür einen US-Sensor.

Grüße Wolfgang

Chris266
20.05.2007, 19:12
Danke für den MC34063 Tip. Leider bin ich Löt-technisch nicht gerade der begabteste. Wenn ich dass was im Datenblatt des MC34063 steht wirklich basteln müsste wäre die Schaltung der Spannungsregelung größer als später die AtMega 8 Schaltung (gibts fix und fertig) und meine Finger längst abgesenkt.
Selbst mit Steckverbindungen habe ich so meine Probleme. Bin halt Programmierer und kein Techniker. So, genug der negativen Selbstdarstellung.

Einen US Sensor hätte ich noch da - zur Not. Doch meine Versuche möchte ich zunächst mit dem Sharp durchführen. Meine Erfahrungen mit dem US Modul sind nicht gerade positiv. Abgesehen davon darf - bzw. SOLL der Roomba ja anecken. Zumindest wenn er reinigt, auch an der Wand entlang :)

Ich habe den Sharp derzeit noch zu weit vorne platziert, ich kann derzeit noch nicht zwischen 4cm und 1,x Meter unterscheiden da hier die Analogwerte identisch sind. Doch dieses Problem will ich später angehen.

Wichtig ist mir zunächst das Erstellen einer Map. Hierzu soll der Roomba eine 360 Grad Drehung vollführen und daraufhin von seiner nächsten Umgebung eine MAP erstellen in der er dann so gut wie blind (da der Sharp eben "Punktgenau" ist) umherfahren.

Da ich nach einigen cm sowie so wieder die Position in der MAP neu eichen muss, wird er wieder eine 360 Grad Drehung durchführen müssen. Hier wäre das US Modul leider nicht so gut geeignet.

Auch beim Ausrichten an einer Wand wird sich der Sharp sicher besser eignen als ein US Modul.

So, nun ist es Zeit für ein Bier und ein paar Messwerte vom Sharp erfassen (Analogwerte den cm Entfernungen zuordnen) - der Uhu dürfte jetzt getrocknet sein.

Chris266
20.05.2007, 19:51
Für alle die selbst einen Roboter oder vergleichbares bauen wollen: Plant besser als ich!

Wer sich folgende Tabelle antut und das Bild vom Roomba mit dem Sharp Sensor betrachtet wird auf Anhieb bestimmt feststellen: so wird das nix:


Ein Blick in das Datenblatt des Sharp Sensors und - Mist!

Ich müsste den Sharp Sensor 20cm weiter hinten anbringen um dann 1,3m weit sehen zu können. Ich bekomme das Kotzen, nachdem der Uhu so lange gebraucht hat zum trocknen.

Also liebe Bastler: nehmt Euch kein Beispiel an mir!
Theorie und Praxis sind nicht immer ideal. Wobei ich sagen muss dass die Analogwerte vom Sharp ab etwa 20cm durchaus sehr konstant sind (gemessen auf eine weiße Wand).

BlueNature
20.05.2007, 23:47
Servus,

wegen deinen Problemen, das mit dem "toten Bereich" ist eigentlich bekannte Matherie beiden Robotikern. Das haben soweit alle Sharps. Also mußt eben soweit hinter der maximalen möglichen Messfläche anbringen das du nach dem Höcker bist oder softtechnisch zurückfahren um zu sehen welches Delta die Kennlinie hat um den relevanten Punkt (1 oder 2) zu bestimmen. Auch in Ecken wirst du Probleme bekomen mit dem Sharp-Sensor, da gehen dir die Werte weit höher in die Distanz als real vorhanden, also aufpassen bei Ecken und korreturrechnen durch mehrere Messungen.

Grüße Wolfgang

Chris266
28.05.2007, 15:08
So, nach einigen Tagen und vielen Rückschlägen meine bisherigen Ergebnisse:

AtMega 8 Modul (Link: http://www.chip45.com/index.pl?page=Crumb8-USB&lang=de) endlich da und kann nun in AvrStudio entwickeln.

Das AtMega8 Modul kommuniziert inzwischen selbstständig mit dem Roomba und akkumuliert wichtige Daten:

- aktuelle X/Y Position (+/- 32767mm) in der Wohnung
diese Daten kommen von den Odometrie-Sensoren die im Roomba enthalten sind.
- aktuelle Ausrichtung (statt 0..359° hier 0..811)

Er ist inzwischen in der Lage gezielt selbständig Punkte in der Wohnung anzufahren.
Da die MAP im AtMega 8 noch nicht enthalten sendet derzeit noch der PC die Kommandos "Fahre nach X/Y". Ziel wird es sein dass der PC später nicht mehr benötigt wird.

Der Roomba dreht sich in die korrekte Richtung und fährt dann los. Anschließend wird, falls die Abweichung zu groß ist, die Fahrt nochmals korrigiert.

Eine Hindernisserkennung ist zwar enthalten, bin aber noch nicht dazu gekommen dem Robi den Code zum "Ausweichen" zu implementieren.

Der Speicher des AtMega8 ist inzwischen zu 50% voll (Flash-RAM). Es wird inzwischen sehr eng im Flash, der Code der MAP wird ca. 2000 Worte benötigen. Dann ist der Speicher voll.

Die Odometriedaten des Roombas sind derzeit ausreichend. Ich muss dazu sagen dass er derzeit noch am Kabel hängt und sich bisher nur auf einer Fläche von 1qm bewegen kann (wg dem Kabel).

Ich musste einen Software-UART implementieren. Als Vorlage habe ich dies (Link: https://www.roboternetz.de/wissen/index.php/Software-UART_mit_avr-gcc) verwendet und feststellen müssen dass ich zu viele Übertragungsfehler hatte. Musste den Code geringfügig ändern damit ich tatsächlich 100% fehlerfreie Kommunikation hatte.

Ebenfalls Probleme machen noch die Signale "Motor hängt". Gerade beim Anfahren signalisiert der Roomba eine Überlastung der Motoren. Hiermit beschäftige ich mich später.

Der AtMega 8 aktualisiert seine Daten mit dem Roomba inzwischen knapp 60mal pro Sekunde, gerade noch ausreichend um bei einer Kollision mit einem Stuhlbein den Robi zum stehen zu bringen.

Als nächstes folgt die MAP und die eigentliche Intelligenz des AtMega 8.

Chris266
30.05.2007, 17:05
Die Logic und die MAP ist inzwischen implementiert. Das Programm wurde mittlerweile zu groß.
Es passt nur noch in den Roomba wenn ich das Programm von AVR Studio optimieren lasse (Code-Größe verkleinern).
Ich bin leider noch nicht dazu gekommen das Programm zu testen. Ich musste den Speicherplatz (RAM) für die MAP etwas verkleinern da es auch hier eng wurde.
Mittlerweile passen "nur" noch etwa 80qm in die MAP.
Konnte den AtMega 8 schon diverse Routen in der MAP suchen lassen (wo wurde noch nicht gereinigt, wie komme ich dort hin?) und musste feststellen dass er diese Aufgaben sehr viel schneller berechnet als in der Simulation von AVR Studio.
Mag mit daran liegen dass der "echte" ATMega 8 mit 14Mhz getaktet ist und nicht zu letzt die Code-Optimierung von AVR Studio.

Chris266
31.05.2007, 21:31
Hatte gehofft heute dazu zu kommen den Roomba mal tatsächlich laufen zu lassen - mit seiner internen Intelligenz.

Leider zeigte sich dass der Compiler, dank der Code-Optimierung zur Speicherplatz Reduzierung, mist gebaut hat. Die gestrigen Routen waren falsch, das habe ich inzwischen heraus gefunden.

Man möge es nicht glauben oder ich habe heute Tomaten auf den Augen.

Kann mir jemand erklären was der Unterschied zwischen diesen zwei Varianten ist?

Variant 1 (funktioniert):


unsigned char PATH_CheckField (unsigned char x, unsigned char y, unsigned char Type) // Prüfen ob das Feld X/Y näher am aktuellen Standort des Robis liegt
// Prüft ob das angegebene Feld ein Hinderniss enthält
// und falls nicht ob der Aufwand dort hin zu gelangen
// kleiner ist als bisher bekannt.
{
if ((x>=PATH_SizeX)||
(y>=PATH_SizeY)) return 0;
if (!Type)
{ // Nach Hindernissen suchen:
if (PATH_Field[x][y].bWall==0) // Es darf kein Hinderniss sein
{
if (PATH_NewDistance>PATH_Field[x][y].b6Distance) // Ist es näher?
{
PATH_Field[x][y].b6Distance = PATH_NewDistance;
}
}
return 0;
}
else
{ // Nach ungereinigten (noch unbefahrene Stelle) suchen
if (PATH_Field[x][y].bClean==0) // noch ungereinigt?
{
if (PATH_NewDistance>PATH_Field[x][y].b6Distance) // Ist es näher?
{
PATH_Field[x][y].b6Distance = PATH_NewDistance;
PATH_DestinationX = x;
PATH_DestinationY = y;
return 1; // ungereinigte Stelle gefunden
}
}
else
{ // Es ist schon gereinigt, wenn kein Hinderniss dann ggf. neue
// Entfernung speichern
if (PATH_Field[x][y].bWall==0) // Es darf kein Hinderniss sein
{
if (PATH_NewDistance>PATH_Field[x][y].b6Distance) // Ist es näher?
{
PATH_Field[x][y].b6Distance = PATH_NewDistance;
}
}
}
}
return 0;
}

Variante 2 (funktioniert nicht):


unsigned char PATH_CheckField (unsigned char x, unsigned char y, unsigned char Type) // Prüfen ob das Feld X/Y näher am aktuellen Standort des Robis liegt
// Prüft ob das angegebene Feld ein Hinderniss enthält
// und falls nicht ob der Aufwand dort hin zu gelangen
// kleiner ist als bisher bekannt.
{
if ((x>=PATH_SizeX)||
(y>=PATH_SizeY)) return 0;
if (!Type)
{ // Nach Hindernissen suchen:
if (PATH_Field[x][y].bWall==0) // Es darf kein Hinderniss sein
if (PATH_NewDistance>PATH_Field[x][y].b6Distance) // Ist es näher?
PATH_Field[x][y].b6Distance = PATH_NewDistance;
}
else
{ // Nach ungereinigten (noch unbefahrene Stelle) suchen
if (PATH_Field[x][y].bClean==0) // noch ungereinigt?
{
if (PATH_NewDistance>PATH_Field[x][y].b6Distance) // Ist es näher?
{
PATH_Field[x][y].b6Distance = PATH_NewDistance;
PATH_DestinationX = x;
PATH_DestinationY = y;
return 1; // ungereinigte Stelle gefunden
}
}
else
{ // Es ist schon gereinigt, wenn kein Hinderniss dann ggf. neue
// Entfernung speichern
if (PATH_Field[x][y].bWall==0) // Es darf kein Hinderniss sein
if (PATH_NewDistance>PATH_Field[x][y].b6Distance) // Ist es näher?
PATH_Field[x][y].b6Distance = PATH_NewDistance;
}
}
return 0;
}

Inhaltlich sollten beide das selbe durchführen.

Egal, hat lange gedauert das heraus zu finden.

Er findet jetzt übrigens den Weg in maximal 60ms, hatte nochmals Simulationen laufen lassen (in AVR Studio).