Entwicklung: RoPi - Autonomer Roboter mit RaspberryPI

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Hi,
    das

    Code
    // GRID-MAP
        eeprom_write_bytes(2, &Map, sizeof(&Map));


    wird so nicht funktionieren ...
    Da wirst Du so was

    Code
    for(i=0; i<10, i++)
    {
        eeprom_write_bytes(2, Map[i], sizeof(Map[i]));    
    }


    machen müssen. Eventuell noch mit typecast

    Code
    for(i=0; i<10, i++)
    {
        eeprom_write_bytes(2, (const byte*) Map[i], sizeof(Map[i]));    
    }


    cheers,
    -ds-

  • Entwicklung: RoPi - Autonomer Roboter mit RaspberryPI? Schau mal ob du hier fündig wirst!

  • Hm jetzt hab ich aber erst noch ein anderes Problem, und zwar beim übermitteln der Grid-Map...

    Hab ein Sketch zum testen:

    Spoiler anzeigen

    Wenn ich das nun flashe kriege ich über den Serial-Monitor von Arduino-IDE folgende Ausgabe:

    Spoiler anzeigen

    ..nicht nur am Ende sondern auch mitten drin stimmt die Übergabe nicht mit der Map die ich definiert habe :-/ =(

    :helpnew:

    //EDIT: argh! Erst jetzt beim Posten ist mir aufgefallen das ich vergessen hab GridSize auf 10 runter zu stellen dau2.gif
    pcdau.gif

    Nu passt die Ausgabe auch..

    Spoiler anzeigen

    Ich werd das aber letztlich so nutzen:


  • Nachteil wie bei allen Flash Chips ist aber auch hier das diese Teile nicht unendlich viele Schreibzyklen vertragen. Ab 100000 soll es wohl Probleme geben.

    ich weiss das will keiner wissen, aber ein Blick ins Datenblatt vom Atmel m328p oder m2560 sagt:
    Write/Erase Cycles: 10,000 Flash/100,000 EEPROM

    nur mal so am Rande ;)

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Ich hab zZt ein seltsames Problem mit meinem WebInterface und einer Tabelle die ich via CSS erzeuge ... :s

    Und zwar nutze ich für <div>'s den CSS Eintrag "display: table" usw um meine Tabellen zu erzeugen, in denen ich dann Sachen ausrichten und anordnen kann...
    Dabei wird erst eine Box um Alles, mit Schatten und Rahmen angelegt worin sich dann weitere Boxen befinden. Also zB links oben eine "Connection" in der sich Connection Status usw befindet, rechts daneben noch eine Box mit Pan/Tilt und dem RaspiCam Stream - und rechts davon das Problemkind mit einem Kompass und der Grid-Map.. Genau diese richtet sich aber nicht wie alle anderen nach oben aus sondern seltsamerweise nach unten :mad_GREEN: aber ich weiß nicht wieso :helpnew:

    Screenshot: http://www11.pic-upload.de/06.11.14/c28ulqy66je.png
    PHP Code: http://codepad.org/JAKtkViY
    CSS Code: http://codepad.org/0j90jao9

    Hoffentlich kann mir jemand helfen :huh:

    :danke_ATDE:


    //EDIT: Ach mist - denken müsste man können... pcdau.gif

    Ein Nachtrag von

    Code
    #Orientation { vertical-align: top; }

    in der style.css und schon gehts dau2.gif


    //EDIT2: Gerade ist mir aufgefallen das der RaspberryPI meinen CMPS10 Kompass stört - also vermutlich das Magnetfeld beeinflusst... Wenn ich das Module weiter hinten beim Arduino platziere passen die Werte - allerdings nicht 0 bzw 360° = Norden, sondern Süden was aber korrekt ist, dort wo er hinzeigt ist wirklich Süden und alle anderen Himmelsrichtungen passen auch ... Muss mir jetzt nur was einfallen lassen wie ich den CMPS10 weiter hinten befestige :denker:

  • Kleines Update:

    Bin derzeit noch immer am finetunen des WebInterfaces und der generellen Kommunikation zwischen Arduino und RaspberryPI.
    Habe nun alle Werte die der Arduino übermittelt ins RoPi_Socket.py eingebunden und lasse es dort hinterlegen sowie teilweise auch schon verarbeiten (Rules).

    Dabei ist mir aufgefallen das die RoPi_Socket.py mittlerweile eine CPU-Last von ca. 40% erzeugt, was ich aber zZt noch auf die Debugausgabe zurückführe - hab ich noch nicht ohne getestet, aber er gibt halt zZt alles mögliche noch auf der Konsole aus, was später aber nicht mehr sein muss (printD).. Aber insbesondere da ich im Arduino Sketch komplett auf Delay's verzichten möchte, überfluten teilweise die Messwerte den RaspberryPI wodurch dann die Auslastung rapide ansteigt (je nach Mode: AutoDrive, Explore oder Follow). Hoffentlich hält sich das in Grenzen wenn ich erst das eigentliche Brain einbaue und um weitere Rules erweitere :-/


    Mir wurde jetzt auch schon von einigen nahegelegt den Code in den nächsten Entwicklungsstufen nicht mehr offen zu legen - mit der Begründung das andere damit Geld verdienen könnten aber ich das lieber selber vermarkten solle... Das widerspricht allerdings meiner bisherigen Auffassung, schließlich hab ich auch extreme Probleme etwas passendes zu dem Thema zu finden und das bremst enorm aus. Wenn also mein Code anderen dabei hilft etwas ähnliches umzusetzen treibt das doch den Fortschritt voran? Davon profitiere ich dann später vielleicht auch :bussi2:


    Ich bin derzeit aber auch am Überlegen den derzeit verbauten RaspberryPI Model-B durch den kommenden A+ zu ersetzen, da dessen Stromverbrauch aber auch die PCB Größe geringer ist... Oder einen anderen RaspberryPI-Clone wie zB den ODROID-W

    Die RaspiCam will ich halt weiter benutzen können, damit bin ich eigentlich recht zu frieden, vorallem aber weil die so schön klein is :)


    Stellt sich allerdings die allgemeine Frage wie ich die Drahtlose Kommunikation sicherstelle :s

    Darüber habe ich auch schon aus anderen Gründen nachgedacht: Wenn das Gefährt später auch draussen herum fahren soll, hätte WiFi nur eine begrenzte Reichweite, man möchte aber ggf weiterhin auch Mobil Zugriff haben zB übers Smartphone oder ein Tablet...

    Allgemein Funk würde wegen letzterem also auch nicht passend sein, da es denk ich ein größerer Aufwand wäre zB ein RFM12B Modul an einen PC zu koppeln, als sich einfach mit einem WiFI Hotspot zu verbinden.

    Es gibt WiFI Module die sich über SPI anbinden lassen, wie zB das CC3000 WiFi module, allerdings weiß ich nicht inwiefern die kompatibel zum normalen Netzwerk sind und ob damit überhaupt Ad-hoc möglich ist :huh:

  • Odroid W wird ja leider nicht mehr produziert, ich "forsche" gerade mit dem Arietta G25 Modul rum, da hängen wir aber gerade ein bisschen beim Entfernungsmesser. Aber auch ich will die Kamera nutzen und die CSi schnittstelle fehlt da. Und die Kamera vom pcDuino ist mit 2MP unterlegen, ausserdem gibt es die nicht als "Nachtsichtkamera".
    Ich würde es auch gut finden, wenn der Code offen bleibt. Wer wirklich Geld verdienen will macht das über Zubehör. Ich habe zum Beispiel ab übernächste Woche Roboterteile im Shop und will mal versuchen eine Bausatz für ein Fahrgestell anzubieten. Erstens interessiert es mich selbst und ich hatte mich geärgert, dass ich wieder viel rumsuchen musste und zweitens kommen seit dem ich eine Motorsteuerung für den RasPi anbiete echt viele Nachfragen. Raspberry Pi sei dank :lol:

  • Ja hey ;) ...


    ...
    Mir wurde jetzt auch schon von einigen nahegelegt den Code in den nächsten Entwicklungsstufen nicht mehr offen zu legen - mit der Begründung das andere damit Geld verdienen könnten aber ich das lieber selber vermarkten solle...
    ...


    zunächst mal, denke ich, ist Open Source sicher der bessere Weg. Allein schon, wenn Du Dir vorstellst, dass alles, was Du Dir bisher im Web zusammen gesucht hast, statt dessen in irgendeiner Schublade verschlossen wäre ...
    Zum zweiten ist das mit closed Source unter Linux nicht so einfach, wie unter anderen sog. Betriebssystemen :fies: ... und das ist auch gut so.
    In dem Moment, in dem Du anderen Code oder andere Libs verwendest, bist Du an deren Nutzungsbedingungen gebunden. In der Regel heisst das, dass der Source mit ausgeliefert werden muss.
    Das heisst aber nicht zwangsläufig, dass jeder Deinen Code einfach so verwenden oder evtl. sogar kommerziell nutzen darf. Ein entsprechener Hinweis auf die Nutzungsbedingungen reicht da schon.
    Und verhindern kannst Du es i.d.R. eh nicht, dass jemand den Source kommerziell nutzt. Bestes Beispiel dafür ist das (afaik mittlerweile belegte) "Ausleihen" der BSD IP-Stacks durch eine sog. "Softwareschmiede" aus Redmond.
    Wie gesagt ... ich würde das, in Anbetracht Deines Nutzens und dem nicht zu unterschätzenden Aufwand der Absicherung - wobei die Frage ist, ob das überhaupt (noch) möglich ist - einfach so lassen ...


    ...
    Es gibt WiFI Module die sich über SPI anbinden lassen, wie zB das CC3000 WiFi module, allerdings weiß ich nicht inwiefern die kompatibel zum normalen Netzwerk sind und ob damit überhaupt Ad-hoc möglich ist :huh:


    Ich habe gestern -> so eins <- geliefert bekommen.
    Alles, was ich dazu bisher so gelesen habe, deutet darauf hin, dass das Teil recht gut funktionieren sollte. Wenn ich damit durch bin, poste ich mal einen Erfahrungsbericht.
    Fastinierend finde ich, dass bei dem Preis trotzdem die TCP/IP Stacks im Modul sind und es sich nicht um einen simplen Controller sondern ein SoC handelt.
    Wie gesagt ... ich bau mal das Breadboard auf und dann sehen wir weiter ...

    cu,
    -ds-

  • Das liest sich wirklich sehr gut, ist aber für den Arduino gedacht, oder? Allerdings ist das Module auch nicht 5V tolerant, kann also nicht direkt an den Mega2560 angeschlossen werden - aber da brauch zumindest Ich das eh nicht ;)

    Der Stromverbrauch ist auch bemerkenswert niedrig: https://nurdspace.nl/ESP8266#Power

    Auch die Eigenschaften lesen sich faszinierend: https://github.com/esp8266/esp8266-wiki/wiki

    Naja, bin mal auf Dein Erfahrungsbericht gespannt :fies:

  • Du hast ja nun Erster Eindruck: ESP8266 - WLAN-Modul mit rs232 Schnittstelle gepostet - Das WLAN-SoC Module ist wirklich sehr sehr interessant!

    Werde ich mir glatt auch mal eins bestellen und meinen Roboter etwas umbauen - dann bräuchte ich nämlich nur noch einen USB-Port um den Arduino an den PI zu koppeln (und direkt flashen zu können)

    Jetzt bin ich allerdings ernsthaft am überlegen welche Alternative ich für den RaspberryPI in Betracht ziehen kann... Generell muss ich wohl auch etwas mehr umbauen, alleine schon um meine Stromversorgung nun endlich irgendwo auf dem Gefährt unterbringen zu können und diese auch direkt zugänglich machen - also vom PowerPack (USB) auf ein Breadboard um von dort 5V für Bauteile usw zu beziehen, und von dort dann auch zum Minicomputer (derzeit dem PI) sowie Arduino.
    Ich will die Stromversorgung nämlich auch noch Messbar haben, also aktuellen Ladezustand und die gelieferte Spannung etc. Damit ich frühzeitig erkennen kann wann er wieder aufgeladen werden muss usw

    Der ODROID-W sah auf den ersten Blick eigentlich perfekt dafür aus, klein und genug Features... Da ich aber noch nicht genau weiß inwiefern die Auslastung aussehen wird wenn alle Rules fertig implementiert sind, könnte evtl. der SoC des PI's generell zu lahm sein :denker:

    Der Edison sah auf den ersten Blick auch gut aus, hat aber leider zu wenig Digital I/O's um PI&Arduino zu ersetzen. Zusätzlich zum Arduino is der mir wiederum zu overkilled und teuer :-/ (also wenn sowas wie Edison dann nur beides Ersetzen)

    Tja und weitere geeignete Alternativen hab ich noch nicht gefunden :(


    Bin aber derzeit auch nebenbei noch am bereinigen des Codes: viele Leichen raus schmeißen, aufräumen und sortieren, teilweise optimieren und bisschen kommentieren.
    Zum Wochenende werde ich dann mal eine Vorläufige Anleitung sowie den Code versuchen zu posten - hoffentlich krieg ich das verständlich hin :rolleyes:

  • Ich hab mir am 12.11.2014 bei Sparkfun ein paar Teile bestellt um meinen RoPi über Sprache zu steuern sowie Töne/Musik abspielen zu können. Am gleichen Tag bestellte ich dafür auch etwas in China... Heute kam alles an:

    Von Sparkfun:

    • COM-09151 Speaker - 0.5W (8 ohm) $1.95
    • BOB-09964 Electret Microphone Breakout $7.95
    • BOB-11044 Mono Audio Amp Breakout - TPA2005D1 $7.95
    • COM-09939 Rotary Potentiometer - 10k Ohm, Linear $0.95

    Über eBay:


    * Alle Teile sehen sehr gut aus - auch das aus China.

    * Das Mikrophone ist ziemlich klein, bin gespannt ob das auch empfindlich genug ist. Erst später hab ich das möglicherweise besseren (und günstigere) Electret Microphone Amplifier - MAX4466 with Adjustable Gain von Adafruit gefunden, aber naja...

    * Der Audio AMP (Verstärker) ist ebenfalls sehr klein - und muss soweit ich das gelesen habe so nah wie möglich an den Lautsprecher angebracht werden, also möglichst kurze Kabel. Da weiß ich nocht nicht inwiefern der Magnet vom Lautsprecher stören könnte... Es gibt auch Module zum abspielen von MP3's aber die sind ziemlich teuer. Deshalb hab ich mich für eines entschieden welches nur (uncompressed) WAV (8bit 16Khz mono) Dateien abspielen kann (bzw nicht das Module kann das sondern der Arduino bzw siehe dazu >hier<), schön billig und für mein Vorhaben ausreichend ;)
    Ausserdem hat das Module einen Shutdown Pin, über den man die Power des Modules abschalten kann um Strom zu sparen. Ich kann das Module also nur dann ein schalten wenn ichs auch wirklich benötige :)
    Eigentlich sollte man Lautsprecher mit mehr Watt Leistung nehmen als der AMP liefern kann, um sowohl eine bessere Klangqualität zu haben aber auch keine Gefahr ihn zu überlasten.. Hab aber auf die schnelle keinen passenden kleinen gefunden.

    * Das AMP Module benötigt bei voller Lautstärke 280mA, da sollte man halt drauf achten wenn mans mit 3V3 oder 5V betreiben möchte (der PI kann auf 3V3 bei weitem nicht so viel ausgeben, auch der Arduino kann auf 3V3 nur 50mA ausgeben)

    * Die SD Karte muss mit FAT16 formatiert werden damit der Arduino darauf zugreifen kann.


    Ich bin jetzt erst mal dabei alles anzuschließen und Kabels dran zu löten etc. Dabei werde ich mich nach >> dieser << Anleitung richten.

    Melde mich später noch mal wenn ich den Code zurecht bastle :daumendreh2:

    //EDIT: Zum testen habe ich die wav Dateien von hier verwendet: https://github.com/FellowRobotici…rExamples/piwav
    Diese muss man aber noch umwandeln - habe ich mit WinAMP gemacht - auf:
    PCM ; 16,000 kHz ; 8 Bit ; Mono

    Zum testen habe ich zudem erst mal einen Arduino Nano v3 genutzt. Die Verkabelung sieht wie folgt aus:

    Code
    Arduino    SD-Card
    --------|-----------
    D13        SCK
    D12        MISO
    D11        MOSI
    D4         SDCS
    5V         5V
    GND        GND
    Code
    Arduino    AMP
    --------|--------
    D9         IN +
    D6         SDN
    5V         5V
    GND        GND
    Code
    AMP     Speaker
    -------|-------
    OUT +      +
    OUT -      -

    Wie ihr seht hab ich kein " IN - " belegt da es ansonsten kratzt/rauscht/Störgeräusche gibt.
    Die SD wie gesagt mit FAT16 formatieren und die umgewandelten WAV Dateien direkt auf die SD kopieren.

    Dann benötigt man noch eine Lib: https://github.com/TMRh20/TMRpcm/

    Den Nano hab ich dann mit folgendem Sketch geflasht:
    [code=php]
    /*
    http://arduino.cc/en/pmwiki.php?n=Reference/SDCardNotes

    Filenames on SD must be 8.3
    To play it use uppercase Filenames.
    Quality must be PCM ; 16,000 kHz ; 8 Bit ; Mono

    SD card attached to SPI bus as follows:
    MOSI - pin 11
    MISO - pin 12
    CLK - pin 13
    CS - pin 4
    */

    #include <SD.h> // need to include the SD library
    #define SD_ChipSelectPin 4 // using digital pin 4 on arduino Nano
    File root;

    #include <TMRpcm.h> // also need to include this library...
    #define SpeakerPin 9 //11 on Mega, 9 on Uno, Nano, etc
    TMRpcm tmrpcm; // create an object for use in this sketch

    #define PowerAMP 6 // digital pin 6 to control AMPs power
    #define TurnOfAfterPlay 0 // 0 to disable


    // this handy function will return the number of bytes currently free in RAM, great for debugging!
    int freeRam(void) {
    extern int __bss_end;
    extern int *__brkval;
    int free_memory;
    if ((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
    } else {
    free_memory = ((int)&free_memory) - ((int)__brkval);
    }
    return free_memory;
    }

    void setup() {
    tmrpcm.speakerPin = SpeakerPin;
    Serial.begin(9600);
    if (!SD.begin(SD_ChipSelectPin)) { // see if the card is present and can be initialized:
    // Using F("...") to avoid wasting RAM
    Serial.println(F("SD fail"));
    return; // don't do anything more if not
    }
    Serial.println("Listing Files on SD:");
    root = SD.open("/");
    printDirectory(root, 0);
    Serial.println("done!");

    pinMode(PowerAMP, OUTPUT);
    if (TurnOfAfterPlay == 0) {
    digitalWrite(PowerAMP, 1); // turn AMP on
    }

    PlayWave("STAR_W~1.WAV");

    Serial.print("FreeRAM: "); Serial.println(freeRam());
    }

    void printDirectory(File dir, int numTabs) {
    while(true) {
    File entry = dir.openNextFile();
    if (! entry) {
    // no more files
    break;
    }
    for (uint8_t i=0; i<numTabs; i++) {
    Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
    Serial.println("/");
    printDirectory(entry, numTabs+1);
    } else {
    // files have sizes, directories do not
    Serial.print("\t\t");
    Serial.println(entry.size(), DEC);
    }
    entry.close();
    }
    }

    void PlayWave(char *file) {
    if (tmrpcm.isPlaying()) { // already playing something, so stop it!
    Serial.println("A wav file is being played, stopping it!");
    tmrpcm.stopPlayback();
    }
    Serial.print("Playing: "); Serial.println(file);
    if (TurnOfAfterPlay == 1) {
    digitalWrite(PowerAMP, 1); // turn AMP on
    }
    tmrpcm.play(file);
    if (TurnOfAfterPlay == 1) {
    delay(500);
    digitalWrite(PowerAMP, 0); // turn AMP off
    }
    }

    void serialReceive() {
    if (Serial.available() > 0) {
    char InputString = Serial.read();
    Serial.flush();
    int Valid = 0;

    if (InputString == '2') {
    PlayWave("2.WAV");

    } else if (InputString == '3') {
    PlayWave("3.WAV");

    } else if (InputString == '.') {
    PlayWave("P.WAV");

    } else if (InputString == 'a') {
    PlayWave("ANVIL_~1.WAV");

    } else if (InputString == 'b') {
    PlayWave("PINKY_~1.WAV");

    } else if (InputString == 'z') {
    PlayWave("ZAK_MC~1.WAV");

    } else if (InputString == 'i') {
    PlayWave("STAR_W~1.WAV");

    } else if (InputString == 'o') {
    Serial.println("Turning AMP OFF");
    digitalWrite(PowerAMP, 0); // turn AMP off
    } else if (InputString == 'O') {
    Serial.println("Turning AMP ON");
    digitalWrite(PowerAMP, 1); // turn AMP on

    } else if (InputString == 'p') {
    Serial.println("Pause");
    tmrpcm.pause();
    } else if (InputString == '?') {
    if (tmrpcm.isPlaying()) {
    Serial.println("A wav file is being played");
    } else {
    Serial.println("Nothing is played");
    }
    } else if (InputString == 'S') {
    Serial.println("Stop");
    tmrpcm.stopPlayback();
    } else if (InputString == '+') {
    Serial.println("Valume UP");
    tmrpcm.volume(1);
    } else if (InputString == '-') {
    Serial.println("Valume DOWN");
    tmrpcm.volume(0);
    } else if (InputString == '0') {
    Serial.println("Quality DOWN");
    tmrpcm.quality(0);
    } else if (InputString == '1') {
    Serial.println("Quality UP");
    tmrpcm.quality(1);
    }
    }
    }

    // the loop routine runs over and over again forever:
    void loop() {
    if (Serial.available() > 0) { serialReceive(); }

    }
    [/php]
    Die von mir verwendeten WAV Dateien könnt ihr >> hier << laden.

    Wirklich lauter machen kann ich das aber leider nicht ohne das es anfängt zu schrabbeln - da ist vermutlich der Lautsprecher doch schon zu schwach für. Aber ansonsten funktioniert das schon wirklich sehr gut, ist auch laut genug :)
    Als nächstes mach ich mich an die Mikrophone Steuerung (Voice Control) :fies:

  • Ich muss leider noch mal wegen der Grid-Map Geschichte nerven =(

    Momentan mache ich das so:

    Spoiler anzeigen

    Im Arduino Sketch hinterlege ich zZt. ein statisches Koordinaten-Array:

    Dieses wird wie folgt an das 'the Brain' Script auf dem PI übermittelt:

    Die Ausgabe sieht dann so aus:

    Im Python Script verarbeite ich das dann wie folgt:

    (in einer Zeile)

    Die Verarbeitung im Javascript wiederum sieht dann so aus:
    [code=php]parseResponse(message.split("\n"));

    function parseResponse(requestlist) {
    for (var i=0; i<requestlist.length; i++) {
    var requestsplit = requestlist[i].strip().split(':')
    requestsplit[requestsplit.length] = "dummy";
    command = requestsplit[0];
    value = requestsplit[1];
    value2 = requestsplit[2];

    if( command == "get.Map" ) {
    if (value == "NONE" && value2 == "NONE") {
    mylog("..Currently no Grid Map Data available!..");
    } else {
    if (value == "END" && value2 == "END") {
    drawMap(GridMapArray);
    } else {
    //add to array..
    GridMapArray[value] = value2;
    }
    }
    }

    }
    }
    [/php]

    Und zu guter letzt die Darstellung dieser Daten:
    [code=php]
    var lightgrey = "rgb(184,184,184)"; // background/unknown
    var black = "rgb(0,0,0)"; // wall/barrier
    var red = "rgb(255,0,0)"; // barrier
    var green = "rgb(0,255,0)"; // goal
    var blue = "rgb(0,0,255)"; // robot
    var white = "rgb(255,255,255)"; // nothing/free
    var grid = "rgb(255,250,205)"; // grid lines

    function Init_Map() {
    var canvas = document.getElementById('map');
    //Canvas supported?
    if (canvas.getContext){
    var context = canvas.getContext('2d');
    context.fillStyle = lightgrey;
    context.fillRect( 0, 0, canvas.width, canvas.height );
    }
    }

    function drawMap(GridMapArray) {
    var canvas = document.getElementById('map');
    //Y is vertical, X is horizontal
    for (var Y = 0; Y < GridMapArray.length; Y++) {
    var Coords = GridMapArray[Y].strip().split(",");
    for (var X = 0; X < Coords.length; X++) {
    if (Coords[X] == "") { continue; }
    if (Coords[X] == ",") { continue; }
    if (Coords[X] == 0) { // nothing, white
    var r = 255;
    var g = 255;
    var b = 255;
    } else if (Coords[X] == 1) { // goal, green
    var r = 0;
    var g = 255;
    var b = 0;
    } else if (Coords[X] == 254) { // robot, blue
    var r = 0;
    var g = 0;
    var b = 255;
    } else if (Coords[X] == 255) { // wall, black
    var r = 0;
    var g = 0;
    var b = 0;
    }
    drawPixel(canvas, X, Y, r, g, b);
    }
    }
    }

    function drawPixel(canvas, x, y, r, g, b) {
    if (canvas.getContext){
    var context = canvas.getContext('2d');
    var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);
    var PixelSize = 4;
    x *= PixelSize;
    y *= PixelSize;
    var index;
    for (var i = 0; i < PixelSize; i++) {
    for (var j = 0; j < PixelSize; j++) {
    index = (x + (y + j) * canvas.width) * 4;
    canvasData.data[index + 0] = r;
    canvasData.data[index + 1] = g;
    canvasData.data[index + 2] = b;
    canvasData.data[index + 3] = 255; //Alpha Channel
    }
    ++x;
    }
    context.putImageData(canvasData, 0, 0);
    }
    }
    [/php]

    Ergebnis:

    ...Das funktioniert soweit auch sehr gut... Nur gefällt mir das eben noch nicht :fies:

    Zum einen glaub ich ist das zu viel Aufwand - der Arduino brauch glaub ich gar keine Map im Speicher haben. Und zum anderen sieht mir das zu banal aus, ich möchte das eigentlich so haben wie hier zu sehen:

    Spoiler anzeigen

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne deine Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklärst du dich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne deine Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklärst du dich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne deine Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklärst du dich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.

    Screen+Shot+2012-11-04+at+9.43.33+AM.png


    Dabei stelle ich mir das so vor, dass der Roboter sich in der Mitte der Map befindet.
    Also angenommen die Karte ist 100 x 100 Pixel groß, dann befindet sich der Roboter auf den Koordinaten 50 x 50.
    Die Karte ist standardmäßig grau. Hindernisse sollen Schwarz dargestellt werden und der Roboter selbst blau.

    Durch den Kompass kenne ich die Richtung in die der Ultraschall zielt, was z.B. Oben (Norden) wäre.

    Nun verschickt der Roboter einen Ping und empfängt in einem Meter Entfernung etwas.
    Da ich aber keinen Meter auf der Karte darstellen kann nehme ich einfach an das 1m = 1cm ist und auf der Karte 10 Pixel entsprechen würde.

    Jetzt muss ich mit canvas eine Weiße Linie zeichnen die von den Koordinaten 50x50 nach oben bis 50 x 41 geht und 50 x 40 einen Schwarzen Pixel setzen...


    Hab ich das soweit richtig verstanden :huh:

    Woran ich jetzt allerdings zu knabbern habe ist der CODE.... Wie müsste der canvas Code dafür aussehen :s


    :helpnew:

  • Und was soll mir dieser Post jetzt sagen? Darf ich von vorherigen Meinungen, die durch andere Forenmitglieder beeinflusst wurde, nicht abweichen? :wallbash:

    Es gab im Chat als auch hier unzählige Diskussionen dazu, in denen mir geraten wurde ein MAP array auf dem Arduino anzulegen usw - auch andere Projekte dieser Art stützen sich darauf... Aber da ich hieran bereits seit einigen Monaten knabbere will ich was anderes ausprobieren.

    Wenn du aber sonst nix weiter dazu zu sagen hast, dann verkneif dir bitte einen solchen Kommentar wie gerade

  • Kann ich vielleicht den, auch in canvas dargestellten, Kompass als Vorlage verwenden :huh:
    Da sieht es wie folgt aus:

    Es wird alle 500ms der bearing Wert abgefragt. Beim erhalten des Wertes wird folgendes aufgerufen:

    Spoiler anzeigen

    [code=php]
    if( command == "get.bearing" ) {
    document.getElementById("DriveAnglenum").innerHTML = value+"&deg;";
    document.getElementById("DriveAngleperc").value=50+parseFloat(value)/2;
    drawCompass(value);
    }
    [/php]

    Zum erstellen des Kompass gehören folgende Javascript Anweisungen:

    Spoiler anzeigen

    [code=php]function Init_Compass() {
    var canvas = document.getElementById('compass');
    if (canvas.getContext){
    var context = canvas.getContext('2d');
    var w = canvas.width;
    var h = canvas.height;
    var FontSize = 15;
    var NorthPos = w / 2 - FontSize; // when w = 200 and FontSize = 15 -> NorthPos = 85
    var OstPos = h / 2 - FontSize;
    var SouthPos = w / 2 - FontSize;
    var WestPos = h / 2 - FontSize;
    context.font = FontSize+"px Georgia";
    context.fillStyle = 'black';
    // "text", horizontal, vertical
    context.fillText("N", NorthPos, FontSize);
    context.fillText("O", (w - FontSize), OstPos);
    context.fillText("S", SouthPos, h);
    context.fillText("W", 0, WestPos);
    }
    }

    function resetCompass() {
    // clear canvas
    var canvas = document.getElementById('compass');
    if (canvas.getContext){
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    Init_Compass();
    }
    }

    // http://www.dhtmlgoodies.com/tutorials/canvas-clock/
    function drawCompass(degrees) {
    var canvas = document.getElementById('compass');
    if (canvas.getContext){
    resetCompass();
    var context = canvas.getContext('2d');
    var w = canvas.width;
    var h = canvas.height;
    var FontSize = 15;
    var HandSize = w / 2 - FontSize;
    context.save();
    context.fillStyle = 'green';
    context.strokeStyle = '#555';
    // Move registration point to the center of the canvas
    context.translate(w/2-FontSize, h/2-FontSize);
    // Rotate degrees
    context.rotate(degreesToRadians(degrees));
    context.beginPath();
    context.moveTo(0, 0) // this will actually be (85,85) in relation to the upper left corner
    context.lineTo(0, HandSize) // (250,250)
    context.stroke();
    // Move registration point back to the top left corner of canvas
    //context.translate(-w/2, -h/2);
    context.restore();
    }
    }

    function degreesToRadians(degrees) {
    return (Math.PI / 180) * degrees
    }[/php]


    Stehe leider weiterhin etwas auf dem Schlauch :(

  • Hm mit der Kartenerstellung bin ich jetzt zwar noch nicht viel weiter - habe aber freundlicherweise einen (ziemlich professionellen) Code von > diesem Projekt < (Vorname: Will) erhalten der auch den Rover5+PCB verwendet und der mich dazu veranlasst hat meinen bisherigen Code noch mal komplett zu überarbeiten, da die Prozessorauslastung inkl. WebServer doch irgendwie zu hoch ist :(

    Werde jetzt also daher gehen und das eigentlich Optionale aber trotzdem benötigte Web-Interface auf meinen anderen PI auslagern um zumindest die 20-40% Auslastung, die hauptsächlich durch den WebSocket und dessen Requests verursacht werden, nicht mehr direkt auf dem Roboter zu haben. Leider muss ich dann auch den Stream der RaspiCam übers Netzwerk schicken - das Script ist aber zum Glück schon dafür vorgesehen..

    Besagtes Projekt ist beeindruckend umgesetzt:
    Der macht alles über den PI, selbst die Pinbelegung bzw Funktion der Pins des Arduino's wird vom PI gesteuert bzw initialisiert. Ansprechen der Sachen etc macht auch alles der PI.
    Auch die Kartenerstellung und Navigation geschieht in Python, wobei er nicht canvas nutzt sondern einfach eine Bilddatei über Python erzeugt und dann auf den Webserver hochläd.
    Ersteres kommt mir etwas zu komisch vor, kann mir nicht vorstellen dass das schnell genug läuft (der PI weißt den Arduino an den einen Ping zu senden und anschließend sagt der PI das der Echo-Pin ausgelesen werden soll...).
    Ist aber trotzdem beeindruckend zu sehen was man so alles machen kann :D

    Allerdings habe ich nicht vor das auch so zu machen - möchte schon an meinem Konzept festhalten, nur muss ich Aufgrund von Befehls-Abarbeitung sowie "was passiert wenn die Verbindung zwischen den Scripts verloren geht" mehr auf ein Queue Verfahren setzen und deshalb den Kern meines Codes umschreiben... 'Will' macht das ähnlich, nutzt aber eine 3 Jahre alte Classe die mittlerweile discontinued ist.

    Auch werde ich vermutlich dazu übergehen zumindest die Pan/Tilt Servos (und den einen Ultraschall Sensor) direkt über den PI zu steueren, um dem Arduino etwas Arbeit und somit Verzögerung abzunehmen...
    Denn um so mehr der zu tun hat um so langsamer kann er andere Sachen ausführen und die Pan/Tilt Geschichte knallt mir einiges an Delay in den Ablauf rein :(
    Da ich kleine Servo's sowie einen neuen Raspberry A+ verwende, sollte die Stromversorgung eigentlich kein Problem darstellen - wenn jemand anderes große Servos nutzt muss derjenige halt seine Spannung von einer anderen Quelle herholen da die Servos recht viel Ziehen können, aber das soll nicht mein Problem sein :fies:

    Nochmal eine Übersicht der zZt. benötigten I/O's, um zu verdeutlichen wieso ich den Mega2560 weiterhin benötige:

    &quot;IO_pins.h&quot;


    Ich werde also 5 Digitale Pins vom RaspberryPI verwenden, vermutlich aber auch noch den Speaker..

    In der Liste fehlen aber auch noch 3 andere Ultraschall Sensoren, wobei die einen gemeinsamen Trigger-Pin verwenden sollen.

    Dh. das erstellen der Karte ist jetzt erst mal in den Hintergrund gerückt - das neu organisieren des Codes wird erst mal genug Nerven kosten :X


    So langsam komme ich auch an die Grenzen des Arduino's in Punkto Stromversorgung - viel mehr als das da oben kann der nicht versorgen. Dh ich muss auch hierfür noch eine externe 5V Stromversorgung anzapfen, also meine PowerBank, sodass nur noch 3V3 Sachen direkt über den Arduino laufen würden aber das sind zZt eh nur LEDs ;)

  • Hallo Meigrafd,
    interessante Studien, die du da treibst. Bin pensioniert und fange wieder an mit basteln und programmieren in PYTHON.
    Ich habe mir auch schon Gedanken gemacht zu einem beweglichen Roboter. ich würde es vorziehen wenn die Programmierung in PYTHON erfolgen könnte, bin nicht so vertraut mit C oder Java.

    Wie ist denn der Stand heute bei dir?

    Softwarefehler suchen ist wie Pilze suchen. Wenn man erst einen gefunden hat, findet man meist mehrere.

    Bei Hardware ist es schlimmer, da findet man bereits Fehler wenn man gar keine sucht!

  • Du beschreibst in deiner Installation des Pi zwei Webserver: nginx und Tornado. Warum 2 Webserver?

    Softwarefehler suchen ist wie Pilze suchen. Wenn man erst einen gefunden hat, findet man meist mehrere.

    Bei Hardware ist es schlimmer, da findet man bereits Fehler wenn man gar keine sucht!

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!