RoπLawnMow

Hallo heute war ich mal wieder ein wenig bei meinem roπLawnMow aktiv und habe eine Funktion geschaffen die ich mir beim PiMowBot abgeschaut habe. Die kann Dateien ähnlich wie für CNC Maschinen oder 3D Drucker erstellen und diese dann einfach aufrufen, damit sie abgefahren werden. Das ist aus meiner Sicht für Drehungen oder Spurwechsel interessant. Also für alle wieder kehrende Manöver / Fahrten / Trips. Im Moment ist der Dateiname im Code noch hard codiert, aber in Python lässt er sich ja auch einfach als sys.argv übergeben. Das wird dann vielleicht morgen fertig. Hier aber erst einmal schon ein Video vom aktuellen Stand.
Viel Spaß beim schauen & einen schönen 1. Advend
 

Attachments

Wenn der INA3221 die 3 Motoren bewältigen kann, könnte man den für die PowerPCB benutzen, dann braucht man nur noch einen INA226 für den Akku. Das würde die PCB noch ein bisschen kleiner und einfacher machen und es würde ein I2C Bus reichen. Für die Perimeter Sachen, könnte man auch noch den Arduino Mini nehmen, dann muss sich der Raspberry nicht damit beschäftigen, so wie es beim Ardumower am Anfang auch war.

If the INA3221 can handle the 3 motors, you could use it for the PowerPCB, then you only need an INA226 for the battery. This would make the PCB a bit smaller and simpler and an I2C bus would be sufficient.
For the perimeter things, you could also use the Arduino Mini, then the Raspberry doesn't have to deal with it, as it did with the Ardumower at the beginning.
 
Wenn der INA3221 die 3 Motoren bewältigen kann, könnte man den für die PowerPCB benutzen, dann braucht man nur noch einen INA226 für den Akku. Das würde die PCB noch ein bisschen kleiner und einfacher machen und es würde ein I2C Bus reichen. Für die Perimeter Sachen, könnte man auch noch den Arduino Mini nehmen, dann muss sich der Raspberry nicht damit beschäftigen, so wie es beim Ardumower am Anfang auch war.

If the INA3221 can handle the 3 motors, you could use it for the PowerPCB, then you only need an INA226 for the battery. This would make the PCB a bit smaller and simpler and an I2C bus would be sufficient.
For the perimeter things, you could also use the Arduino Mini, then the Raspberry doesn't have to deal with it, as it did with the Ardumower at the beginning.
Yes I also thought about that, in order to save space, but the INA 3221 has a voltage limitation. But Bernard made the experience, that the INA 3221 also run with higher voltage.
My next step is now to combine the MPU 6050 with the replay of trips. This should help to hold the direction.
 
Heute habe ich das MPU6050, das ich für die Spurkorrektur benötige, in Betrieb genommen.
Da ich keinen Python Beispiel Code für eine ordentliche YAW Ermittlung gefunden habe, habe ich das MPU auf ein ESP D1 Mini Board montiert. Somit ist die HW kleiner als ein GPS Empfänger und liefert nun seine Ergebnisse auf Basis eines Arduino Sketches. Auf dem ESP habe ich noch zusätzlich die Webserial Library installiert. Mit ihr kann ich dann - falls erforderlich - remote Änderungen am Code vornehmen. Dazu muss ich noch einen Taster einbauen, damit das D1 Board sich entweder in meinem WLAN einbucht, oder seinen AP startet.
Die Werte Roll, Pitch und YAW werden über serielle Schnittstelle dem Pi zur Verfügung gestellt und können dann ausgerwertet werden. Vielleicht habe ich diese Woche noch Zeit ein Script zu erstellen, dass die aktuellen Werte vor einer Drehung speichert und mit den Werten nach der Drehung vergleicht.
Gyro.png
Gestern habe ich noch ein paar Beipiel Dateien für ein gezieltes Fahren, Drehen und Wenden auf github abgelegt.
Ich stelle mir das so vor, dass aus dem Haupt-Mäh-Programm dann bei Bedarf eine jeweilige Konserve aufgerufen wird. Nach erfolgreicher Abarbeitung kann dann das Haupt-Mäh-Programm seinen Job weiter machen.
Aber bis dahin vergeht noch ein wenig Zeit.
 
Sowas?
Es wird die Micropython-Bibliothek für den MPU6050 benötigt.

Code:
from mpu6050 import MPU6050

# Erstellen Sie eine MPU6050-Instanz mit den entsprechenden I2C-Pins
mpu = MPU6050(sda=21, scl=22)

# Funktion zur Konvertierung von Rohdaten in Neigung, Rotation und Seitenneigung
def get_pitch_yaw_roll():
    accel_data = mpu.acceleration
    gyro_data = mpu.gyroscope

    # Neigung (Pitch) und Seitenneigung (Roll) aus den Beschleunigungsdaten berechnen
    pitch = atan2(accel_data[0], sqrt(accel_data[1]**2 + accel_data[2]**2))
    roll = atan2(accel_data[1], sqrt(accel_data[0]**2 + accel_data[2]**2))

    # Yaw aus den Gyroskopdaten berechnen
    gyro_yaw = gyro_data[2] / 131.0  # Empfindlichkeit des Gyroskops

    return degrees(pitch), degrees(roll), gyro_yaw

# Hauptprogramm
while True:
    pitch, roll, yaw = get_pitch_yaw_roll()
    print("Pitch: {:.2f} degrees, Roll: {:.2f} degrees, Yaw: {:.2f} degrees".format(pitch, roll, yaw))
    time.sleep(1)  # Kurze Pause zwischen den Messungen
 
Sowas?
Es wird die Micropython-Bibliothek für den MPU6050 benötigt.

Code:
from mpu6050 import MPU6050

# Erstellen Sie eine MPU6050-Instanz mit den entsprechenden I2C-Pins
mpu = MPU6050(sda=21, scl=22)

# Funktion zur Konvertierung von Rohdaten in Neigung, Rotation und Seitenneigung
def get_pitch_yaw_roll():
    accel_data = mpu.acceleration
    gyro_data = mpu.gyroscope

    # Neigung (Pitch) und Seitenneigung (Roll) aus den Beschleunigungsdaten berechnen
    pitch = atan2(accel_data[0], sqrt(accel_data[1]**2 + accel_data[2]**2))
    roll = atan2(accel_data[1], sqrt(accel_data[0]**2 + accel_data[2]**2))

    # Yaw aus den Gyroskopdaten berechnen
    gyro_yaw = gyro_data[2] / 131.0  # Empfindlichkeit des Gyroskops

    return degrees(pitch), degrees(roll), gyro_yaw

# Hauptprogramm
while True:
    pitch, roll, yaw = get_pitch_yaw_roll()
    print("Pitch: {:.2f} degrees, Roll: {:.2f} degrees, Yaw: {:.2f} degrees".format(pitch, roll, yaw))
    time.sleep(1)  # Kurze Pause zwischen den Messungen
Bitte ein wenig konkretisieren.
Auf welchem System läuft dann das Script?
 
Sorry, ist Python Code.
Ich durchforste mal meine Code Schnippsel.

Für einen Raspberry mit Python sollte der Code gehen?
Beachte, dass die smbus-Bibliothek auf Python 3 bereits vorinstalliert ist. Falls nicht, kannst du sie mit sudo apt-get install python3-smbus installieren und die MPU6050-Bibliothek wird benötigt

Python:
import smbus
import math
import time

# I2C-Adresse des MPU6050
MPU6050_ADDR = 0x68

# Register-Adressen des MPU6050
MPU6050_REG_PWR_MGMT_1 = 0x6B
MPU6050_REG_ACCEL_XOUT_H = 0x3B
MPU6050_REG_TEMP_OUT_H = 0x41
MPU6050_REG_GYRO_XOUT_H = 0x43

# Konstanten für die Berechnung der Beschleunigung und des Gyroskop-Signals
ACCEL_SCALE = 16384.0
GYRO_SCALE = 131.0

def read_word(reg):
    high = bus.read_byte_data(MPU6050_ADDR, reg)
    low = bus.read_byte_data(MPU6050_ADDR, reg + 1)
    value = (high << 8) + low
    return value

def read_word_2c(reg):
    val = read_word(reg)
    if val >= 0x8000:
        return -((65535 - val) + 1)
    else:
        return val

def read_acceleration():
    x = read_word_2c(MPU6050_REG_ACCEL_XOUT_H)
    y = read_word_2c(MPU6050_REG_ACCEL_XOUT_H + 2)
    z = read_word_2c(MPU6050_REG_ACCEL_XOUT_H + 4)
    
    x /= ACCEL_SCALE
    y /= ACCEL_SCALE
    z /= ACCEL_SCALE
    
    return x, y, z

def read_gyroscope():
    x = read_word_2c(MPU6050_REG_GYRO_XOUT_H)
    y = read_word_2c(MPU6050_REG_GYRO_XOUT_H + 2)
    z = read_word_2c(MPU6050_REG_GYRO_XOUT_H + 4)
    
    x /= GYRO_SCALE
    y /= GYRO_SCALE
    z /= GYRO_SCALE
    
    return x, y, z

def read_temperature():
    temp_raw = read_word_2c(MPU6050_REG_TEMP_OUT_H)
    temp = (temp_raw / 340.0) + 36.53
    return temp

def get_pitch_roll():
    accel_x, accel_y, accel_z = read_acceleration()
    roll = math.atan2(accel_y, accel_z) * (180.0 / math.pi)
    pitch = math.atan2(-accel_x, math.sqrt(accel_y ** 2 + accel_z ** 2)) * (180.0 / math.pi)
    return pitch, roll

if __name__ == "__main__":
    try:
        bus = smbus.SMBus(1)  # I2C-Bus des Raspberry Pi (1 für Raspberry Pi Version 2 und 3)

        # MPU6050 initialisieren
        bus.write_byte_data(MPU6050_ADDR, MPU6050_REG_PWR_MGMT_1, 0)

        while True:
            pitch, roll = get_pitch_roll()
            gyro_x, gyro_y, gyro_z = read_gyroscope()
            temp = read_temperature()

            print(f"Pitch: {pitch:.2f} degrees, Roll: {roll:.2f} degrees")
            print(f"Gyroscope: X={gyro_x:.2f}, Y={gyro_y:.2f}, Z={gyro_z:.2f}")
            print(f"Temperature: {temp:.2f} C")

            time.sleep(1)

    except KeyboardInterrupt:
        print("MPU6050 Reading Interrupted")

    finally:
        bus.close()
 
Vielleicht hier:
Tests habe ich jetzt eingestellt.
Nachdem ich die Fehler aus dem Script behoben habe (kam mir alles irgendwie bekannt vor) bekam ich die Fehlermeldung, dass die FIFO vom MPU vollläuft. Wie ich das verhindern könnte weiß ich nicht. In der Zeit wo die FIFO nicht voll läuft und das MPU die richtigen Offsets hat, ist die genauigkeit aber nicht zu gebrauchen. Das könnte mit dem FIFO zu tun haben, ich weiß es aber nicht. Dann habe ich noch einige andere Beispiele gesucht, aber keinen Gamechanger gefunden.
Daher habe ich jetzt wieder alles zurückgebaut und werde in den nächsten Tagen mit dem ESP weiterarbeiten
Dennoch Danke für Deine Anregung.
 
Ja kein Problem, wenn es so nicht funktioniert dann lieber das funktionierende.
Hast du den einen reinen MPU6050 oder den Gy-521?
 
Ja, und da gibt es in der Tat Unterschiede steht MPU9250 drauf, ist aber keiner drin.
gibt es sogar check funtionen in der RTIMU.lib
 
GY-521 and MPU9250 use the same MPU6050 gyro accel from inversense:
If you want to have a good accuracy you need to use the YAW result of the include DMP locate inside the chip and not compute the YAW using gyro and accel or you need to do this at a very high frequency more than 200Hz to have the same result as the DMP.
The purpose of the DMP is to offload both timing requirements and processing power from the host processor. Typically, motion processing algorithms should be run at a high rate, often around 200Hz, in order to provide accurate results with low latency. This is required even if the application updates at a much lower rate; for example, a low power user interface may update as slowly as 5Hz, but the motion processing should still run at 200Hz. The DMP can be used as a tool in order to minimize power, simplify timing, simplify thesoftware architecture, and save valuable MIPS on the host processor for use in the application.


Unfortunately i don't know if a python code exist to directly read the DMP result
 
Unfortunately i don't know if a python code exist to directly read the DMP result
..Yes there is a code, Sascha found this, but there is a bug in reading or writing in the fifo. After hours of inestigations I stopped for trying to use this and I came back to the ESP Solution. To provide the YAW Data in the motorscript, in the moment I think to start a seperate thread in the motor script. This thread should provide the MPU Datas direct in the motorscript. For other scripts it is enough the the thread writes the data every 200ms in a file and other scripts read from the file. This is my plan.
 
Gestern habe ich den ersten Test zu Kurskorrektur mit einem MPU6050 durchgeführt. Das klappte fast auf Anhieb. Der Wert des Gyroscopes wird als Fehler in einen PID Regler eingelesen. Je größer der Fehler, umso größer ist der Korrekturwert des PID Reglers. Diesen Korrekturwert addiere ich auf die RPM Vorgabe des Linken Rades und substrahiere ihn von der RPM Vorgabe des rechten Rades. Somit erfolgt die Korrektur des Antriebes. Was jetzt noch aussteht, das Abfangen von Extremwerten. So darf z.B. der Korrekurwert + SollRPM des Antriebes nie größer als die Maximal Drehzahl sein, und nie so klein sein, dass der Antrieb in die falsche Richtung dreht. Das sind jetzt also nur noch Feinheiten denke ich
Das Ergebnis bisher kann sich doch schon sehen lassen finde ich, Links ohne Korrektur, rechts mit Korrektur.
Herzlichen Dank an @Bernard, der mir immer mit Rat zur Seite steht und bisher auf jede Frage eine Antwort wußte, bzw mir einige Anregungen aus seinen Erfahrungen gab.
 

Attachments

Hallo allen ein gutes Neues Jahr, möge es friedlicher Enden als es beginnt.
Da mein roπLawnMow ein wenig groß für die Wohnung ist, habe ich meinen MINI PiMowBot mit der Motorsteuerung des roπLawnMow versehen, und ein paar Anpassungen gemacht, damit ich auf Basis des Raspberry pi mit Python Code die Motorsteuerung verbessern kann. Heute habe ich es dank der Anregungen von @Bernard aus den letzten Wochen geschafft einen gyrobasierten Spurwechsel umzusetzen. Die Wendungen habe ich auf Basis der gezählten Tics umgesetzt, bei der Geradeaus Fahrt hat dann das Gyroskop die Richtung korrigiert. Das kann man auch sehr gut beobachten wie ich finde. Ich bin schon ganz zufrieden. Die Herausforderung liegt wie immer im Detail, z.B. dass man den Sprung von -179.9 auf 179.9 Grad richtig interpretiert. Es sind ja physikalisch nur 0.2 Grad Unterschied. Mathematisch ist der Unterschied größer, was mir heute einige graue Haare gekostet hat, aber nun ist ja alles gut.
Den Code würde ich erst auf Github zur Verfügung stellen wenn ich den wieder auf die brushless Motoren umgestellt habe, das dauert je nach Wetter für outdoor Fahrten noch etwas. Wer mag kann ihn aber auch von mir so wie er jetzt ist bekommen.
Der Ablauf einer Hin und Rückfahrt sieht in der Steuerdatei dann z.B. so aus.
Code:
#spurwechsel cw
40,40,110,s         # fahre mit 40 rpms links sowie rechts 110 cm straight vor (s für straight)
-18,-18,7,7          # fahre mit 18 rpms links sowie rechts 7 Tics links und rechts zurück
-18,18,12,12       # Drehung ccw fahre mit der 18rpms links zurück und 18 rpms rechts 12 Tics vor
18,18,7,7            # fahre mit 18 rpms links sowie rechts 7 Tics links und rechts vor
-18,18,12,12      # Drehung ccw fahre mit der 18rpms links zurück imd 18 rpms rechts 12 Tics vor
# nun zurück zum Spuranfang
-18,-18,18,18      # fahre mit 18 rpms links sowie rechts 7 Tics links und rechts zurück
40,40,110,s        # fahre mit 40 rpms links sowie rechts 110 cm straight vor (s für straight)
-18,-18,7,7          # fahre mit 18 rpms links sowie rechts 7 Tics links und rechts zurück
18,-18,12,12       # Drehung cw fahre mit der 18rpms links vor und 18 rpms rechts 12 Tics zurück
18,18,7,7            # fahre mit 18 rpms links sowie rechts 7 Tics links und rechts vor
18,-18,12,12      # Drehung cw fahre mit der 18rpms links vor und 18 rpms rechts 12 Tics zurück
-18,-18,18,18    # fahre mit 18 rpms links sowie rechts 18 Tics links und rechts zurück
# nun zurück zum Spuranfang
Viel Spass beim Schauen.
View attachment ChangeLawn.mp4
 
Back
Top