Ardumower Control Center

Super. Ich kann derzeit nicht weitermachen, da der Speaker permanent wegen der fehlenden Batterie piept - gibt Ärger mit der Regierung :-D

Das mit /dev/ttyS0 finde ich ja spannend, bei mir (RPi 3, Raspian 8 ) gibt es kein ttyS0, lediglich tty0 - tty63 sowie ttyAMA0, ttyprintk und ttyUSB0. Hast du den angelegt?

Als welcher Nutzer läuft denn node red?

Code:
$ sudo ps aux | grep node
pi        2035  0.0  0.2   4272  2016 pts/0    S+   21:15   0:00 grep --color=auto node
pi       12370  0.0  7.5 120812 71528 ?        SNsl 04:26   0:22 node-red

$ ls -la /dev/ttyAMA0 
crw-rw---- 1 root dialout 204, 64 May 17 05:17 /dev/ttyAMA0

$ groups pi
pi : pi adm tty dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio

$ sudo usermod -a -G dialout pi


Erster Befehl: Die erste Spalte ist der Nutzer. Node Red läuft also als User Pi.
Zweiter Befehl: zeigt, dass AMA0 root gehört, aber die Gruppe dialout auch darauf lesen und schreiben (rw) darf
Dritter Befehl: zeigt an, in welchen Gruppen der Nutzer Pi ist... dialout ist dabei
Vierter Befehl: würde pi in die Gruppe dialout schieben - wenn es nicht schon so wäre (logout, login ist notwendig)

Falls du einen anderen Account als pi für node red hast, kannst du mit sudo su nodereduser versuchen zu wechseln. Und dann als diesen User mal screen zu starten. Wird das verweigert, liegt da der Grund.

Falls es nicht die Rechte sind: ggf. ist die Ausgabe vom TCP Server an serial nicht korrekt: mal mit "Stream of Strings, seperated by n" testen. Habe mit einem Debug-Modul die Ausgabe mal umgeleitet, da kam Murks raus. Mit String sieht es nach PFOD aus:

debug.png

Attachment: https://forum.ardumower.de/data/media/kunena/attachments/3922/debug.png/
 
Zuletzt bearbeitet von einem Moderator:
Also bei mir sieht das debug auch so aus, also alles okay, aber er schickt den string nicht zur app bzw dem Port

*edit*

hab grade mal einen usb uart drann gemacht und mit dem Serial Monitor in der Arduino IDE angeschaut, die app schickt das durch bis zum Mower, aber der String vom Mower geht nicht zurück zur app

*edit 2*
Der request von der App geht zum Mower und er antwortet auch, nur der String wird einfach nicht weitergeleitet zum Port.... da steckt jetzt also der Fehler.... siehe den Screenshot ;-)
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/3725/Screen1.PNG/
 
Zuletzt bearbeitet von einem Moderator:
Ich habs am laufen... bei alle dem haben wir vergessen, das er auch wieder vom uart zum TCP Port antworten muss... klingt irgendwie logisch oder? :whistle:

Habe einnen Serial IN und einen Serial OUT erstellt, den Serial IN mit dem TCP in verbunden und den Serial Out mit dem TCP Out verbunden, den TCP Out unter Type auf Reply to TCP gestellt. Soweit ich weiß ist der onboard uart am Raspberry unter /dev/ttyS0 zu erreichen, vorrausgesetzt du hast vorher unter raspy-config die Konsolenausgabe (das Erste) auf nein und den Hardware uart (das Zweite) auf an geschaltet, dann sollte automatisch ein /dev/ttyS0 angelegt werden.

Anbei wieder einmal ein paar Bilder zur erklärung.

Falls es noch jemanden interessiert, ich arbeite im Moment an einem Python Script um den Ardumower über einen Playstaion 3 oder Playstaion 4 Controller zu steuern... funktioniert bis jetzt schon etwas, komme aber an der einen oder anderen Stelle nicht so wirklich weiter... das ganze funktioniert über die selben Befehle ( RMCS), die auch vom Joystik unter Manual controll genutzt werden. Da es ja nur mit dem Raspberry funktioniert, denke ich, das dieses nette feature hier mit zu gehört.

Gruß
Benni
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/3725/Screen1_2018-07-06.PNG/
 
Zuletzt bearbeitet von einem Moderator:
Das ist ja sehr geil. Klasse!

Damit kann man solange noch die PfodApp nutzen, bis Paddy dann auch die anderen Commands über das Dashboard realisiert hat. Oder einfach, weil man weder auf das eine noch das andere verzichten möchte. Man erhält die Wifi-Steuerung ohne den ESP8266 flashen* zu müssen. Finde das eine schön saubere Lösung.

* Anmerkungen zum ESP8266: Entgegen einiger Meldungen hier im Forum hatte ich keine Probleme damit. Mit Linux und einem USB-UART von Amazon war es eine Sache von 5 Minuten.
 
Hallo Dennis
Es ist wahrscheinlich eine einfache Frage:
pi@homecon01
Muss ich da was ändern?
homecon01 ist das das Passwort zum anmelden oder für was steht das?

Man merkt wahrscheinlich das das eine Anfängerfrage ist.

Gruß
Uwe
 
Hallo Uwe,

du hast mir schon so oft geholfen, da freut es mich sehr, wenn ich dir mal helfen kann :cheer:

Das ist der sogenannte Prompt. Beispiel:
pi@homecon01:/var/log/$

Das heißt, dass du als Nutzer pi am Server homecon01 (mein Hausautomations-Pi) angemeldet bist, dich im Verzeichnis /var/log befindest und ohne Admin-Rechte ($) unterwegs bist.

Bei dir steht statt homecon01 sicherlich was anderes, z.B. raspberry als Servername. Eine Tilde (~) als Verzeichnis ist die Abkürzung für dein Home-Verzeichnis (/home/pi).

Der Prompt hat eigentlich nur informativen Charakter. Er hilft, Befehle vergleichbar zu machen (aus welchem Verzeichnis ausgerufen, mit welchem Nutzer, mit oder ohne Root-Rechte).

Vor allem wenn man mehrere Linux-Systeme hat, macht es Sinn, seine Systeme durchzubenamsen. Wenn du 3 Fenster mit pi@raspberry offen hast, dann kann das nur zu Fehlern führen :)

Du kannst den Hostname ändern, in dem du die Datei /etc/hostname editiert. Also sudo nano /etc/hostname. Dann speichern und neustarten.

Gruß, Dennis
 
Hallo zusammen,

kurzes Update meinerseits. Im Wiki habe ich beschrieben, wie der PI an dem PCB 1.3 angeschlossen werden kann.

Außerdem habe ich die manuelle Steuerung überarbeitet. Die ist immer noch stark verzögert, die Latenz beträgt bis zu 2 Sekunden. Dennoch ist es stabiler und vor allem zuverlässiger. Bitte nach wie vor nur verwenden, wenn ihr zuhause seit und eingreifen könnt. Benutzt das niemals über das Internet.

Es gibt noch ein paar Neuerungen. Nachdem mein GPS Modul eingetroffen ist (Danke an Markus für den schnellen Versand), habe ich es endlich angeschlossen und die RMCS Nachricht für GPS ergänzt. Im CC gibt es nun eine Seite "Geography", welche auf einer Satellitenkarte die Position des Mowers anzeigt. Außerdem gibt es nun ein Kompass Control.

Am einfachsten ist es natürlich, das CC neu von Github herunterzuladen. Ihr habt aber teils erhebliche Anpassungen gemacht und daher möchte ich beschreiben, wie ihr das bei euch einbauen könnt.

Manuelle Steuerung:
In der Node-RED Entwicklungsseite gibt es den Flow "Manual". Hier gibt es den Node "calculate motor speed". Diesen müsst ihr ersetzen. Am einfachsten geht das, indem ihr folgenden Code in Node-RED importiert (Erst markieren und STRG + C, dann in Node-RED Menü -> Import -> Clipboard)


Code:
[{"id":"fbdf3963.9c2858","type":"function","z":"cf477024.84de6","name":"calculate motor speed","func":"nnvar speed = msg.payload.centery - msg.payload.y;nvar steer =msg.payload.centerx - msg.payload.x;nnvar speed_left = speed + steer *-1;nvar speed_right = speed + steer;nnvar manual = {payload:{speed_left:speed_left,n                       speed_right : speed_right}};nnflow.set("manual_speed_left", speed_left);nflow.set("manual_speed_right", speed_right);nreturn manual;","outputs":1,"noerr":0,"x":539,"y":369,"wires":[[]]},{"id":"f863a374.3078d","type":"inject","z":"cf477024.84de6","name":"Manual Control every second","topic":"","payload":"","payloadType":"date","repeat":"2","crontab":"","once":true,"onceDelay":0.1,"x":372,"y":436,"wires":[["869750.020948b"]]},{"id":"93f5fc65.ce666","type":"delay","z":"cf477024.84de6","name":"","pauseType":"delay","timeout":"100","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":398,"y":476,"wires":[[]]},{"id":"869750.020948b","type":"function","z":"cf477024.84de6","name":"create RMMOV message","func":"if (flow.get("state") === "manual"){nnvar manual_mow = flow.get("manual_mow")||0;nif (manual_mow != 1){n    manual_mow = 0;n}nnvar speed_left = flow.get("manual_speed_left");nvar speed_right = flow.get("manual_speed_right");nnvar command = "$RMMOV," + manual_mow + "," +n     parseInt(speed_left) +n   "," + parseInt(speed_right)+",0,0,0";nnmsg.payload = command;nn    return msg;n}n","outputs":1,"noerr":0,"x":455,"y":511,"wires":[["f00f0fdc.449ca","10c5c02e.aba8e"]]}]


Ihr seht dann schon, wie es zu verbinden ist.

GPS und Kompass
Zunächst müsst ihr in Node-RED die Erweiterung node-red-contrib-web-worldmap installieren.

Außerdem müsst ihr aus dem Github Repository den Ordner Public/Images auf euer node-RED Verzeichnis kopieren. Hier ist das Hintergrundbild vom Kompass drin.

Nun importiert ihr diese Zeilen in Node-RED. Das erzeugt die neue Seite "Geography" mit den Inhalten und UI Gruppen

Code:
[{"id":"f65812f2.ecbd5","type":"tab","label":"Geography","disabled":false,"info":""},{"id":"3c7c6b48.6c9e44","type":"ui_template","z":"f65812f2.ecbd5","group":"f594fe6b.96793","name":"Map","order":0,"width":0,"height":0,"format":"<iframe src="/worldmap" width="500px"  height="400px" ></iframe>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":337.5,"y":66,"wires":[[]]},{"id":"93c482b1.d31f4","type":"ui_template","z":"f65812f2.ecbd5","group":"28837999.cb9716","name":"camera","order":1,"width":"6","height":"6","format":"n<script language="javascript" type="text/javascript">n           (function(scope){ n                scope.$watch('msg', function(msg) {n    n    window.ifr = document.getElementById("camera");n    window.ifr.src=msg.payload;n                });n            })(scope);nn</script>n<iframe id="camera" seamless width="100%" height="100%"></iframe>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":141.84191513061523,"y":225.6473731994629,"wires":[[]]},{"id":"115be876.d73078","type":"function","z":"f65812f2.ecbd5","name":"get_camera_url","func":"msg.payload = global.get("camera_url");nreturn msg;","outputs":1,"noerr":0,"x":121.01334381103516,"y":163.9900360107422,"wires":[["93c482b1.d31f4"]]},{"id":"95587f0c.d4ac5","type":"inject","z":"f65812f2.ecbd5","name":"Trigger UI Templates","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":107.75835418701172,"y":114.73483562469482,"wires":[["115be876.d73078"]]},{"id":"f594fe6b.96793","type":"ui_group","z":"","name":"Map","tab":"d9c6f8bf.f72878","disp":false,"width":"10","collapse":false},{"id":"28837999.cb9716","type":"ui_group","z":"","name":"Camera","tab":"d9c6f8bf.f72878","disp":true,"width":"6","collapse":false},{"id":"d9c6f8bf.f72878","type":"ui_tab","z":"","name":"Geography","icon":"dashboard","order":4}]


Zum Schluss müssen wir noch das Kompass-Control erstellen. Dazu in den Flow "Ardumower Control Center" wechseln und an dem RMIMU Knoten, an den Ausgang Yaw, folgende Nodes anfügen


Code:
[{"id":"c3474a57.6ae658","type":"function","z":"996353eb.92f4e","name":"Compass degree","func":"if (msg.payload < 0 )n{n    msg.payload = msg.payload * -1 +180;n}nnnreturn msg;","outputs":1,"noerr":0,"x":464,"y":1472,"wires":[["72eb92fd.b9ff5c","4afa87fd.ff33b8"]]},{"id":"72eb92fd.b9ff5c","type":"ui_template","z":"996353eb.92f4e","group":"72301ec0.49b6d","name":"Compass","order":1,"width":"6","height":"6","format":"<script src="/myjs/RGraph/libraries/RGraph.drawing.image.js"></script>n<script src="/myjs/RGraph/libraries/RGraph.odo.js"></script>n<script language="javascript" type="text/javascript">nn           (function(scope){ n                  scope.$watch('msg', function(msg) {n                    compass.value = msg.payload;n                  compass.grow();n                  n                });n            })(scope);n            n           var img = new RGraph.Drawing.Image({n            id: 'cvs_compass',n            x: -4,n            y: 0,n            src: '/Images/compass.png'n        }).draw()nvar compass = new RGraph.Odometer({n            id: 'cvs_compass',n            min: 0,n            max: 360,n            value: 0,n            options: {n                greenColor: 'rgba(0,0,0,0)',n                yellowColor: 'rgba(0,0,0,0)',n                redColor: 'rgba(0,0,0,0)',n                backgroundColor: 'rgba(0,0,0,0)',n                backgroundBorder: 'rgba(0,0,0,0)',n                backgroundLinesColor: 'rgba(0,0,0,0)',n                tickmarks: false,n                tickmarksBigColor: 'rgba(0,0,0,0)',n                textColor: 'rgba(0,0,0,0)',n                needleColor: '#ddd',n                needleTail: false,n                needleHead: false,n                needleThickness: 5n            }n        }).draw();n            n    </script>nn    <canvas id="cvs_compass" width="300" height="300">n    [No canvas support]n</canvas>n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":674,"y":1470,"wires":[[]]},{"id":"72301ec0.49b6d","type":"ui_group","z":"","name":"Compass","tab":"d9c6f8bf.f72878","disp":true,"width":"6","collapse":false},{"id":"d9c6f8bf.f72878","type":"ui_tab","z":"","name":"Geography","icon":"dashboard","order":4}]


Damit die Satellitenkarte auch erstellt wird, noch die Nodes RMGPS ersetzen mit diesen

Code:
[{"id":"8e98ac80.085cd","type":"function","z":"996353eb.92f4e","name":"RMGPS","func":"var rmgpsbegin = msg.payload.toString().search("\$RMGPS");nnif (rmgpsbegin == -1){n   n}nelse{n    n    var output = msg.payload.split(",");nnlat = {payload:(output[2])/100000};nlon = {payload:(output[3])/100000};nmap = {payload: {name:"Ardumower", lat:lat.payload, lon:lon.payload}};nnreturn [lat, lon,map];nnn}n","outputs":3,"noerr":0,"x":343,"y":1042,"wires":[["23aa1e2.b8bb5e2"],["8ecf2435.22df18"],["2d6563b1.89842c","28cf36b0.a2f57a"]]},{"id":"23aa1e2.b8bb5e2","type":"ui_text","z":"996353eb.92f4e","group":"f594fe6b.96793","order":0,"width":"3","height":"2","name":"","label":"Latitude","format":"{{msg.payload}}","layout":"col-center","x":541,"y":1021,"wires":[]},{"id":"8ecf2435.22df18","type":"ui_text","z":"996353eb.92f4e","group":"f594fe6b.96793","order":0,"width":"3","height":"2","name":"","label":"Longitude","format":"{{msg.payload}}","layout":"col-center","x":542,"y":1060,"wires":[]},{"id":"2d6563b1.89842c","type":"worldmap","z":"996353eb.92f4e","name":"","lat":"50.23629","lon":"6.69234","zoom":"18","layer":"Esri Satellite","cluster":"","maxage":"","usermenu":"show","layers":"show","panit":"false","x":623,"y":1096,"wires":[]},{"id":"f594fe6b.96793","type":"ui_group","z":"","name":"Map","tab":"d9c6f8bf.f72878","disp":false,"width":"10","collapse":false},{"id":"d9c6f8bf.f72878","type":"ui_tab","z":"","name":"Geography","icon":"dashboard","order":4}]


Das erzeugt einen neuen Node "Worldmap". Geht hier noch in die Einstellungen und setzt die Startkoordinaten passend uz eurer Adresse. Ohne die Anpassung startet die Karte immer an meiner Adresse und ihr müsst raus zoomen und euch suchen.

Ein Beispiel wie es aussieht findet ihr hier
https://youtu.be/0bf0vFX_Dcw
 
Hi Paddy.
I Don't understand exactly how you manage that and what is the PI job, but i think the mower need to receive the WLAN into all the mowing area.
Why you have latency with the manual mode,normaly the PI and NMEA command are real time responsive like Arduremote ?

Into this video
What kind of GPS is in use M8N or M6 and have you leave all the nmea sentence or use only the main one ?
For the Yaw : Is it the Imu GY801 or the yaw coming from GPS ?

Congratulation for the result
 
Hallo Paddy,
habe grad das CC geupdatet, klappt soweit super. Einziges Problem was ich habe ist, das meine Koordinaten falsch bzw zu kurz angezeigt werden.

Habe mal die ArdumowerSerial vom Arduino zum Raspberry mit dem Debug angeschaut und es kommen folgende Werte:

msg.payload : string[27]
"$RMGPS, 17, 52 , 9 ↵"

es sollte aber heißen:
$RMGPS, 17, 52.152391, 9.743652 ↵

Muss ich / kann ich noch irgendwas im Ardumower Code anpassen, damit er die Nachkommastellen ausgibt?

Und das Problem mit der verzögerung bei der manuellen Steuerung habe ich auch schon bemerkt, ich steuere ja meinen Ardumower mit nem Playstaion 3 Controller. Also über die PFOD Befehle hat er echt null verzögerung, über RMCS Befehle hat er 1 bis 2 Sekunden verzögerung drinnen... an der Baudrate liegt es nicht, habe beides auf 115200 laufen.

Deine Anleitung zu der Stromversorgung ist zwar gut, aber ich habs noch einfacher gelöst. Ich nutze den internen Spannungsausgang vom Ardumower. Ich habe meinen Pi Zero W nur per Micro USB Adapter am USB Port des Arduino Due, der den Strom vom 5v Regler des Boards ausgibt. Bei meinem 1.2 Board reicht es vollkommen für einen Stabilen Lauf aus.

Trozdem ist der Ardumower durch dein CC für mich nochmal um den Faktor 100 in der Nutzbarkeit gestiegen, mach weiter so, du bringst das Projekt auf eine neue, höhere ebene.

Gruß
Benni
 
Hi Bernard,

In fact, you need WiFi connection in your yard, but this is still true to your solution? There are main reasons for latency:
1. signal strength of wifi connection.
2. Baudrate, currently, I use Ardumower common 19200 which seems to be to slow. If I send more than one message per seconds, the mower don't respond as Arduino can't separate the messages anymore. I will try to use higher baud rates.

You also have lot of latency with Arduremote and Bluetooth for sure. Try to move the mower exactly with the app and try to move it with a RC and you know what I mean.

For GPS, I use the module from shop, I think it is a Neo-M6 and it it sonnected to PCB 1.3 not to PI. Ardumowe reads the values of GPS module and I send these values to CC, nothing more. At the moment, I can only see where the mower runs.

The yaw comes from GY and not from GPS. I don't know which one is better because I don't know anything about these modules. Because Alexander uses yaw from IMU for course control, it seems to be the better one.
 
Hallo Benni,

schau mal in Github nach der Datei rmcs.h Hier hat sich eine Kleinigkeit geändert bei sendGPS, so dass die GPS Daten nun vollständig gesendet werden. Die Koordinaten werden als Ganzzahl übertragen, im CC wird dann durch 100000 (ich glaube es waren 5 Nachkommastellen) dividiert und du hast die Koordinaten mit Minuten und Sekunden.

Zur Verzögerung: Im CC ist ein Delay Node eingebaut, der verhindern soll, dass die manuelle Steuerung zu viele Kommandos sendet. Dadurch wird jede Joystick Message mit 100ms Verzögerung gesendet. Außerdem wird der Joystick nur einmal pro Sekunde ausgewertet. Dies wird von dem Inject Node gesteuert. So kommen satte 1100 ms Verzögerung zu stande.
Habe schon mal daran gedacht, die Baudrate für das CC zu erhöhen, das sollte helfen. Aktuell ist es so, dass der Mower beim lesen der seriellen Konsole aussteigt, wenn zu viele Nachrichten pro Sekunde rein kommen. Mehr wie 1 Nachricht pro Sekunde klappen nicht, er steigt dann aus. Dann hilft nur Neustart des Node-RED Servers.
Der Arduino liest über die serielle Konsole erst die gesamte Nachricht ein. Das Ende wird durch einen Zeilenumbruch erkannt. Ich vermute, wenn zu viele Nachrichten gesendet werden geht der Zeilenumbruch verloren und der Mower liest unendlich weiter. Durch Neustart des Node-RED wird die serielle Verbindung kurz getrennt und der Mower hört auf zu horchen.

Der PI Zero kann sicherlich so betrieben werden. Bernard hat bei sich auch mal einen PI Zero direkt an einen 5V Pin vom PCB angeschlossen. Ein großer PI zieht aber deutlich mehr Strom, 2A können es gerne mal werden. Da wird es schnell knapp

Ich habe mich gegen den PI Zero entschieden, weil er nur einen USB Anschluss hat, ich aber unbedingt die Kamera anschließen wollte. Wäre nur mit zusätzlichem Hub möglich gewesen. Beim nächsten mal würde ich aber eher zu einer PI Kamera greifen, dann reicht der PI Zero aus.

Gruß Patrick
 
Hallo Benni,

du hast vor ein paar Tagen beschrieben, dass du den Mower mit einem PS3 Controller steuerst. Kannst du das mal irgendwo beschreiben, wie du das gelöst hast? Verstanden habe ich, dass sich der Controller mit Bluetooth verbindet. Verbindet er sich direkt mit dem Arduino oder mit dem PI?

Gruß Patrick
 
Hi Paddy.
you need WiFi connection in your yard, but this is still true to your solution?
Not at all,remember that my solution is not at all a control center.The PI is never connected on the net or at my home box.
The PI is used as an acces point (like your Home Box) and tablet,phone or PC are connected to the PI so it's difficult to use your PC Inside your house to drive the mower.
The PI Zero and Pi3 are 10 or 15 meters range so your need to be near the mower to use it in manual mode like with arduremote.

Baudrate, currently, I use Ardumower common 19200
If it's USBSerial the minimum to use is 115200 and work perfectly (tested more than 3 months without any issue) and certainly it's possible to have 250000 and maybe more.So certainly try to change this value and you can see all the difference on the manual remote.The plot solution send one message each 50ms without any trouble at this speed.

For GPS , if i remeber a new Neoblox M6 or M8 send more than 6 messages per second but you certainly use only one or maybe two of them so to avoid transmit data for nothing (It's better for the DUE),Take a look here at 9:46 of this video: https://www.youtube.com/watch?v=TwhCX0c8Xe0 you can certainly use only the RMC and GGA by configuring the GPS board with Ucenter.

Please check all what i tell you here (i am not sure of all):p

For IMU : The GY801 send only value of accel, gyro ,and magnetic field so the due need to compute all this as fast as possible to know the YAW position and it work well but reduce a lot the rest of the process.
So maybe try to print the millis() before and after the readIMU

Code:
if ((imuUse) && (millis() >= nextTimeIMU)) {
    // IMU
    Console.println(millis())
    readSensor(SEN_IMU);
    Console.println(millis())
    
    nextTimeIMU = millis() + 200;   // 5 hz


And check if it's not too long.

I use the MPU6050 (GY88) because the difference is that there is a DMP inside and the compute are not made by the DUE (Only read each 100 or 200 ms the DMP YAW result) but nothing is perfect and sometime a drift is here.

Hope it can help you to speed up your solution.
By
 
Hello,

I tried to increase baudrate up to 115200 with no success. If I send more than one message per second, Azurit stops working until I disconnect serial cable (or restart Node-RED which also closes serial port). I think the issue is not transfer rate but the time consumed by Console.readString() and also memory. In my opinion, I fill serial input buffer much faster than Arduino is able to read from. To validate this, I will try to lower the baudrate to 9600 which should give the Arduino enought time to empty the queue.

Currently I send up to 23 Bytes for one move command. Pfod app sends only 2 Bytes. The difference is, pfod App only tells the mower to drive forward, left right etc. I tell the mower the target RPMs of the motors so I can control more exact.
 
Hey paddy,
also ich lasse as CC und den Arduino Due schon die ganze zeit über 115200 laufen, wo kann ich denn die auslesezeit vom Ardumower einstellen? würde einfach mal austesten ob er bei der höheren baudrate auch noch aussteigt.

Na klar kann ich das mal machen, vielleicht kann mir der Eine oder Andere ja mit helfen bei der Auswertung der Analog Sticks. Also über die PFOD Ausgabe ist die Steuerung wie über RC Fernbedienung, fast keine Verzögerung. Im Anhang habe ich mal beide Versionen, es ist aber alles noch im Anfangsstadion, also erwarte nicht zu viel, ich nutze das Ganze über die PFOD Ausgabe und die Digital Buttons am PS3 Controller (Pfeil hoch, Pfeil runter,Pfeil links, Pfeil rechts, X Für das Mähwerk usw...) aber über die Analog Joysticks wäre das viel cooler, da dort auch die geschwindigkeit über die RMCS angegeben werden kann.

Ich habe als Grundlage mal die Beschreibung von dieser Seite genommen:

Zum Pairen der Controller:
PlayStation 3 Controller Help Sheet

Zum auswerten und weitergeben der Befehle:
DiddyBorg v2 - Examples - Joystick Control

Dieser Code wäre sogar besser, der hat nen Failsafe drinnen:
DoodleBorg - PS3 Source Code

Generell wäre vielleicht ein Blick in das Projekt DiddyBorg v2 sehr interessant, da vieles davon übernommen werden könnte (Webserver mit Kammera und Steuerung, PS3 Steuerung usw...)
DiddyBorg V2 - Build

Gruß
Benni
Attachment: https://forum.ardumower.de/data/media/kunena/attachments/3725/PS3Versuch.zip/
 
Zuletzt bearbeitet von einem Moderator:
Ach und Paddy, ich hab da noch so einen Gedanken....
Falls das nicht klappt mit der Manuellen Steuerung (Auslesezeit) werde ich nachher mal versuchen 'Zweigleisig' zu Fahren, das heißt ich werde die Steuerungsbefehle statt über /dev/ttyACM0 an die Console über /dev/ttyS0 an die PFOD app ausgeben. Was ich damit sagen will, wie wäre es die Steuerung über PFOD und den Rest über RMCS laufen zu lassen?
 
Hallo zusammen,

ich habe das Problem gelöst. Im Ardumower Code in der consoleui.h wurde das eingehende serielle Kommando mit Console.readString() gelesen. Dies ist eine blockierende Funktion mit einem default Timeout von 1000ms. Wenn viele Nachrichten eingehen, steigt die einfach aus. Man kann zwar mit Console.setTimeout() einen anderen Timeout einstellen, besser wird es damit aber nicht. Er bricht dann zwar z.B. nach 100ms ab, kommen die Nachrichten aber schneller haben wir das gleiche Problem erneut.

Dazu habe ich die consoleui.h etwas angepasst und verwende nun waitStringConsole

void Robot::readSerial() {
// serial input
if (Console.available() > 0) {
// Console.setTimeout(20);
// String cmd = Console.readString();
String cmd = waitStringConsole();
if (cmd.startsWith("$ROS")) {
setNextState(STATE_ROS, 0);

damit läuft es wie geschmiert. Habe es mit 10 Nachrichten pro Sekunde stabil laufen gelassen. Die restlichen Kommandos, auch wenn jemand kein RMCS nutzen will, laufen ebenfalls wie gehabt.

Für die Baudrate habe ich in der mower.cpp eine optionale Definition mit 115200 baud eingetragen. Je nachdem was man verwendet, kann man entsprechend auskommentieren. Ich will ja auch das ganze mit dem Mega betreiben können und möglichst flexibel bleiben.

Im Flow muss auch etwas in dem Flow Manual angepasst werden. Kopiert das hier rein, ihr seht dann schon wo es hin gehört

Damit lässt sich der Mower stabil manuell steuern. Achtung, Sensortrigger (Bumper, Perimeter usw.) werden nach wie vor ignoriert, er kann also abhauen.


Code:
[{"id":"d1cb92a5.0e9b2","type":"inject","z":"cf477024.84de6","name":"Trigger UI Templates","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":110,"y":283,"wires":[["8b092d1b.0e2ed","e5e103e3.8bd8a"]]},{"id":"e5e103e3.8bd8a","type":"function","z":"cf477024.84de6","name":"get_camera_url","func":"msg.payload = global.get("camera_url");nreturn msg;","outputs":1,"noerr":0,"x":107.4417495727539,"y":331.37298583984375,"wires":[["86ca6499.ea6268"]]},{"id":"86ca6499.ea6268","type":"ui_template","z":"cf477024.84de6","group":"52892a0c.d9c5b4","name":"camera","order":1,"width":"6","height":"6","format":"n<script language="javascript" type="text/javascript">n           (function(scope){ n                scope.$watch('msg', function(msg) {n    n    window.ifr = document.getElementById("camera");n    window.ifr.src=msg.payload;n                });n            })(scope);nn</script>n<iframe id="camera" seamless width="100%" height="100%"></iframe>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":98.30222129821777,"y":386.0605697631836,"wires":[[]]},{"id":"8b092d1b.0e2ed","type":"ui_template","z":"cf477024.84de6","group":"d365c8e8.c714f8","name":"Joystick","order":3,"width":"6","height":"6","format":"<script src="/myjs/nippleJS/nipplejs.min.js" ></script>nn<div data-type="dynamic" id="zone_joystick" style="position:absolute; width:200px; height:200px; background-color:grey;"></div>nn<script>nnn(function(scope){ nn    function createJoystick(){n        var dynamic = nipplejs.create({n            zone: document.getElementById('zone_joystick'),n            mode: 'dynamic',n            catchDistance: 150,n            color: 'white'n        });n        dynamic.on('move', function(evt, nipple_obj) {n            setTimeout(function() {n                var posx = nipple_obj.position.x;n                var posy = nipple_obj.position.y;n                var centerx = nipple_obj.instance.position.x;n                var centery = nipple_obj.instance.position.y;n                // use scope.send to trigger a message in the runtime flown                scope.send({payload:{x: posx, y:posy, centerx:centerx, centery:centery}});n            }, 0);nn        });nndynamic.on('end', function(evt, nipple_obj) {n            setTimeout(function() {n                var posx =0;n                var posy = 0;n                var centerx = 0;n                var centery = 0;n                // use scope.send to trigger a message in the runtime flown                scope.send({payload:{x: posx, y:posy, centerx:centerx, centery:centery}});n            }, 0);nn        });        n    }nnn    scope.$watch('msg', function(msg) {n        createJoystick();nn    });n})(scope);nn</script>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":317,"y":362,"wires":[["fbdf3963.9c2858"]]},{"id":"fbdf3963.9c2858","type":"function","z":"cf477024.84de6","name":"calculate motor speed","func":"nnvar speed = msg.payload.centery - msg.payload.y;nvar steer =msg.payload.centerx - msg.payload.x;nnnif (speed >= 0){n  var speed_left = speed + steer *-1;n  var speed_right = speed + steer;n}else{n  var speed_left = speed + steer;n  var speed_right = speed + steer * -1; n}nnspeed_left = speed_left / 2;nspeed_right = speed_right / 2;nnvar manual = {payload:{speed_left:speed_left,n                       speed_right : speed_right}};nnvar last_leftspeed = flow.get("manual_speed_left");nvar last_rightspeed = flow.get("manual_speed_right");nnnflow.set("manual_speed_left", speed_left);nflow.set("manual_speed_right", speed_right);nnif (speed_left === 0 &&n    speed_right === 0)n    {n        manual.topic = "Manual_stop";n    } else {n        manual.topic = "Manual_drive";n    }n    nreturn manual;n","outputs":1,"noerr":0,"x":504,"y":364,"wires":[[]]},{"id":"f42ec9e.df46938","type":"inject","z":"cf477024.84de6","name":"Trigger Joystick data send to mower","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":true,"onceDelay":0.1,"x":172,"y":459,"wires":[["15867ec5.deab81"]]},{"id":"15867ec5.deab81","type":"trigger","z":"cf477024.84de6","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"500","extend":false,"units":"ms","reset":"","bytopic":"all","name":"send each 500ms","x":448,"y":453,"wires":[["869750.020948b"]]},{"id":"869750.020948b","type":"function","z":"cf477024.84de6","name":"create RMMOV message","func":"if (flow.get("state") === "manual"){nnvar manual_mow = flow.get("manual_mow")||0;nif (manual_mow != 1){n    manual_mow = 0;n}nnvar speed_left = flow.get("manual_speed_left")||0;nvar speed_right = flow.get("manual_speed_right")||0;nnvar command = "$RMMOV," + manual_mow + "," +n     parseInt(speed_left) +n   "," + parseInt(speed_right)+",0,0,0\n";nnmsg.payload = command;nn    return msg;n}n","outputs":1,"noerr":0,"x":448,"y":525,"wires":[["10c5c02e.aba8e","f00f0fdc.449ca"]]},{"id":"f00f0fdc.449ca","type":"debug","z":"cf477024.84de6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":824,"y":376,"wires":[]},{"id":"10c5c02e.aba8e","type":"serial out","z":"cf477024.84de6","name":"Ardumower serial out","serial":"f4409ac2.4ad268","x":823,"y":494,"wires":[]},{"id":"52892a0c.d9c5b4","type":"ui_group","z":"","name":"Camera","tab":"56c2703a.7a819","order":2,"disp":true,"width":"6","collapse":false},{"id":"d365c8e8.c714f8","type":"ui_group","z":"","name":"Joystick","tab":"56c2703a.7a819","order":3,"disp":true,"width":"6","collapse":true},{"id":"f4409ac2.4ad268","type":"serial-port","z":"","serialport":"/dev/ttyACM0","serialbaud":"19200","databits":"8","parity":"none","stopbits":"1","newline":"\n","bin":"false","out":"char","addchar":true},{"id":"56c2703a.7a819","type":"ui_tab","z":"","name":"Manual","icon":"dashboard","order":3}]


Wenn der Mower im manuellen Modus ist, wird jetzt alle 500ms eine Nachricht mit den letzten Joystick Daten erzeugt. Schneller macht keinen Sinn, da der Mower die Motoren ja langsam beschleunigt und abbremst. Man merkt keinen Unterschied zwischen 500ms und 100ms.

Hi there,

suddenly I was able to fix this. The reason was the usage of blocking readString() function in consoleui.h The default timeout of this function is 1000ms. If messages arrive faster, it will fail and your mower become a zombie. Also, if setting timeout with setTimeout lower, it will fail. Instead, I use waitStringConsole function which works great even with many messages (tested with 10 per second).

For code change of consoleui.h see german section.

Also it needs some small modifications on node-red flow Manual. Paste the code above and you will see how to place it. This will send a move message every 500ms, if manual state is active. It is fast enough to send every 0,5 sec because mower accellerate and deaccelerate slowly.

Now it is much safer to use but please bear in mind it will still not react on sensor trigger like bumper or perimeter. So your mower is still able to drive off your yard.
 
Hallo Paddy, bin echt begeistert!
Das Control Center läuft auf meinem RASPI Zero W mit RASPI Cam direkt über USB am DUE angeschlossen also ohne DC/DC Wandler.
Super Arbeit - Danke!
Gruss Michael
 
Hallo Michael,

danke für den Hinweis. Benni hat auch erwähnt, dass er den PI Zero einfach direkt per USB mit dem DUE verbunden hat und nichts weiter für die Spannungsversorgung benötigt hat. Das macht die Sache nochmal deutlich einfacher. Ich nehme das bei Gelegenheit mal mit ins Wiki auf.

Kannst du noch was zur RaspiCam sagen? Ist für die Einrichtung was besonderes zu beachten oder muss man die nur in raspi-config aktivieren? Ist die dann über video0 erreichbar? Werde mir wohl doch mal einen PI Zero W mit Kamera besorgen müssen :)

Viele Grüße
Patrick
 
Hallo Patrick, deine Anleitung passt auch für die RAPI Cam. Im raspi-config muss die Cam enabled werden...hätt ich nicht beim editieren der motion config einen Tippfehler eingebaut hätte es auf Anhieb geklappt. Ja, die Cam wird unter /dev/video0 angesprochen. Ich nutze die kleine Camera die extra für den Zero gebaut wird (erkennbar an denn Bauteilen auf den Flexkabel) mit der normalen Linse.Der Mower war gestern nicht mehr draußen, zur Bildqualität werde ich noch berichten...brauche auch erst noch ein längeres USB Kabel zwischen DUE und RASPI um die Camera bei meinem Chassi nach vorn zu bringen. Melde mich wieder.
Gruß Michael
 
Oben