- Akku Tests und Balkonkraftwerk Speicher         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 23

Thema: Motorsteuerung über Sensorik

  1. #11
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Anzeige

    Praxistest und DIY Projekte
    Ein Kompaßsensor kann keine Position mitteilen sondern nur einen Winkel zwichen seiner Ausrichtung und der Nordweisung.
    Von dem was ich sehe vermute ich mal Das du keinen Kompass sondern ein 3DOF Mems oder Magnetometer Gyroskop hast.
    Da mußt Du Dich dann auch noch um Drift etc. kümmern, sonst wird es über die Laufzeit immer lustiger.

    Erst mal mußt Du unterscheiden können ob Hinderniss oder Gegenstand (wenn du nur beim Finden eines Gegenstandes so reagieren willst und nicht bei jedem Hinderniss).

    vom Rechnen her ist das einfach. Wenn du schon Winkelgrad hast, dann mußt Du ja nur 90° addieren oder subtrahieren (je nach dem ob du links oder rechts Drehen willst).
    Ist das Ergebniss gößer 360° ziehst du 360° ab.
    Ist das Ergebniss kleiner 0° addierst du 360°.
    Dann ist das Ergebniss immer im gültigen Wertebereich.

    Du nimmst also vor der Drehung dein Sensorwert, führts die Berechnung aus und übergibst das Ergebniss einer Variablen.
    Dann kannst Du den aktuellen Sensorwert mit der Variablen vergleichen und beim Drehen z.B. bei einer Differenz kleiner 10° und kleiner 3° jeweils die Geschwindigkeit senken, damit daraus kein endloses Hinundherdrehen wird, weil er nie das Ergebniss trifft.
    Geht dann auch wieder mit IF oder CASE.

  2. #12
    Benutzer Stammmitglied
    Registriert seit
    28.10.2013
    Beiträge
    34
    Sorry habe mich natürlich falsch ausgedrückt . Du hast vollkommen Recht es geht hier um den Winkel der ausgegeben wird. Und der Sensor ist ein CPMS10 mit Magnetometer Tilt Compensated und Gyro modul usw.
    Es ist auch absolut richtig was du weiterhin beschreibst das hin und herdrehen nervt und hier liegt mein Problem ...
    Wie kann ich das Codetechnisch lösen ?

    Habe absolut keine Idee wie ich das in einer if Anweisung lösen soll
    Sprich uS1 sieht etwas bei 15 cm dann Lese bearing ein, drehe solange bis du + 90° ( + Toleranz) erreicht hast, dann weiter gerade aus ?

    ich krieg das nicht hin
    Wie würdest du das Code technisch lösen ?

  3. #13
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Zitat Zitat von zerebrator Beitrag anzeigen
    Sprich uS1 sieht etwas bei 15 cm dann Lese bearing ein, drehe solange bis du + 90° ( + Toleranz) erreicht hast, dann weiter gerade aus ?
    Das wird gerinfügig komlizierter.

    In dem von mir Skizzierten Konstrukt dreht er ja bis die Bedingung des us-Sensors nicht mehr erfüllt ist.
    Jetzt hast Du ja us-Sensor Bedingung erfüllt, Entscheidung der Drehrichtung, Bedingung 90° Drehen setzen
    Drehen bis 90° Bedingung erfüllt ist unabhängig davon ob us-Sensor Bedingung weiterhin erfüllt ist.

    Der Case Abschnitt, darf also nicht mehr selbst das Dehen ausführen sondern muß variablen setzen, die den Systemzustand speichern und über die dann im nächsten Schritt verhindert wird das der us-Case Teil erneut angesprungen wird dafür aber ein 90° Case Teil.
    dort wird dann gedreht bis der Winkel entsprechend klein wird und dann mit geringerer Geschwindigkeit weitergedreht bis der Winkel 0 ist.
    Wenn die Bedingugn erfüllt dit, werden die Merker wieder gelöscht und der Teil verlassen.
    Dann kann wider normal weitergearbeitet werden.
    Das Ziel ist dabei halt so Geschickt die Logik aufzubauen, das man sich nicht in endlosen hin und her Springen verzettelt.

    Deshalb macht es Sinn sich vor dem Programmierne zu überlegen wass will man denn alles machen und welche Bedingunge nmüssen erfüllt werden.
    Asl zweites mauß man sich darüber im klaren sein, daß, damit Sensoren immer wieder eingelesen werdne können das Programm ständig weiterlaufen muß.
    Also Endlosschleife.
    Damit wird auch der Code wärend einer Aktion tausende male durchlaufen.
    Also wo halte ich wie, welchen Systemzustand fest, und verhindere damit das Entscheidungsbäume während einer Aktion immer wieder durchlaufen werden und sich so Werte verschieben oder Aktionen vorzeitig Terminiert werden, weil Eingangsbedingungen mittleriweile nicht mehr erfüllt sind.

    delay sollte im Code nirgendswo vorkommen, sondern durch Timer ersetzt werden. so kann der Code durchlaufen werden und während einer Aktion auch andere Eingaben und Ausgaben verarbeitet werden.
    Wenn etwas wirklich genau sein soll, muß man über Interrupts nachdenken.

    Unter Umständen kann es notwendig sein den gesammten bisher erstellten Code auf den Prüfstand zu stellen und mit dme auge des neu erworbenen wissens zu überlegen ob ein kompletter Neubau nicht sinnvoller ist um schwächen und ausuferndes Volumen auszubügeln.

    Wenn das ganze erst mal zu komplex ist, kannst Du Dir auch Anleien bei UML holen und z.B. auf einem Sück Hartschaum mit kleinen Papierkarten die einzelnen Funkionsblöcke mit Stecknadeln feststecken sowie mit bunten Fäden die Abhängigkeiten (alternativ auch ein UML Programm am Computer) aufzeigen.
    Nach und nach eränzt man auf den Karten dan ndie Variabeln und erkennt so ob ein vorrausgehendes Modul die auch liefert oder ob eine Variabel nach dem Setzen auch irgendwo wieder gelöscht wird. Oder als Zombie das System blockiert.

    Das dann in Code zu bringen ist dann meist der einfachere Teil, da man da schon den meisten Denksport hinter sich hat und (fast) nur noch auf Syntax achten muß.
    Geändert von i_make_it (12.06.2017 um 13:02 Uhr)

  4. #14
    Benutzer Stammmitglied
    Registriert seit
    28.10.2013
    Beiträge
    34
    Hi

    Also ich habe das versucht so zu lösen :
    Code:
    else if (taskTrigger==3) { //nach rechts 
       switch (taskStep) {
         case 0:
           digitalWrite(leftMtrDirPin1, LOW);
          digitalWrite(leftMtrDirPin2, LOW);  
          digitalWrite(rightMtrDirPin1, HIGH);
          digitalWrite(rightMtrDirPin2, LOW); 
          analogWrite(leftMtrSpdPin, 255);   //drive the motor
          analogWrite(rightMtrSpdPin, 255);
           
           currentPosition=bearing;
           taskStep++;
           break;
         case 1:
           if (currentPosition= newPosition+90) { 
             taskTrigger=0;
             taskStep=0;  
       
        analogWrite(leftMtrSpdPin, 0);   //stopp the motors
        analogWrite(rightMtrSpdPin, 0);      
           }
       }
     }
    vorher kommt die Anweisung :
    Code:
    if (!taskTrigger && (uS2 < 15 & uS3 > 30 )) //abstand kleiner als 15cm und abstand links grösser als 30  
        taskTrigger=1;
        
    else if (!taskTrigger && ( uS2 < 15 & uS1 > 30 )) //wenn abstand kleiner als 15 und links groesser als 30 dann rechts
        taskTrigger=2;
    
    else if (!taskTrigger && (uS3 < 16)) //wenn abstand kleiner als 16 dann rechts drehen
        taskTrigger=3;
    leider "pulsiert" der Antrieb nur
    Es schert ihm nicht was die Werte des kompasmoduls machen.

    Ich krieg das nicht hin ....
    Warum wartet er nicht bis er um 90° gedreht hat ???

    Hat jemand einen Vorschlag ?

    Gruß
    Chr.

  5. #15
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    if (currentPosition= newPosition+90) {

    Syntaxfehler?
    http://www.arduino-tutorial.de/category/programmieren/

    Arithmetische Operatoren
    = Zuweisung a=2*b Weist der linken Seite den Wert auf der Rechten Seite zu.

    Vergleichsoperatoren
    == Gleichheit a==b Prüft auf Gleichheit.


    currentPosition=bearing;
    wird bei jedem Durchlauf aktualisiert

    und mit dem Inhalt von "newPosition+90" wieder überschrieben.
    if (currentPosition= newPosition+90) {

    Wo "newPosition" herkommt, wann es mit was gesetzt wird und was sicherstellt das es nur einmal am Anfang einer Drehung gesetzt wird kann ich nicht erkennen.
    Geändert von i_make_it (13.06.2017 um 15:44 Uhr)

  6. #16
    Benutzer Stammmitglied
    Registriert seit
    28.10.2013
    Beiträge
    34
    hmm sobald ich es vergleiche läuft er endlos weiter egal wie oft ich ihm um seine eigene Achse drehe ...

    Vielleicht zu Erklärung bzw. So wie ich es gemacht habe.
    currentPosition bekommt die Werte direkt vom baering aus diesem Code :

    Code:
      /////////////////////////////////////////////////////////////
      //     Kompass Modul Abfrage und senden der Daten         ///
      ////////////////////////////////////////////////////////////
      
      byte byteHigh, byteLow; // byteHigh / byteLow für Bearing
      char pitch, roll;       // Pitch und Roll
      int bearing;            // Bearing
    
      Wire.beginTransmission(CMPS10Addr); // Kommunikation mit CMPS10
      Wire.write(2);                      // Start Register (2)
      Wire.endTransmission();
      Wire.requestFrom(CMPS10Addr , 4); // Abfrage von 4 Bytes vom CMPS10
      while (Wire.available() < 4); // Warten, bis 4 Bytes verfügbar
      byteHigh = Wire.read();       // High-Byte für Bearing speichern
      byteLow = Wire.read();        // Low-Byte für Bearing speichern
      pitch = Wire.read();          // Byte für Pitch speichern
      roll = Wire.read();           // Byte für Roll speichern
      bearing = ((byteHigh << 8) + byteLow) / 10; // Bearing berechnen
      
      sendData(bearing, pitch, roll);             // Daten versenden
    
    void sendData(int bearing, int pitch, int roll) {
      String data = String(bearing) + ";" + String(pitch) + ";" + String(roll);
      
      lcd.setCursor(0,0);
        lcd.print("bear-pitch-roll");
        lcd.setCursor(0,1);
        lcd.print(data);
       
      
     // Serial.println(data);
    delay (100);
    }
    currentPosition und newPosition habe ich deklariert mit

    int currentPosition;
    int newPosition;

    in dem Fall ist newPosition = 0 ? oder
    wie übergebe ich nur für diese Anweisung die Werte von currentPosition an newPosition ?
    denn wenn ich das nach der Initialisierung mache mit newposition=currentposition dann ist doch new Position gleich wie current ,wenn ich dann vergleiche dann wird dieser Zustand, weil er ja dauernd übergeben wird nie erfüllt sein oder ?????

    ???

  7. #17
    Benutzer Stammmitglied
    Registriert seit
    28.10.2013
    Beiträge
    34
    Zitat Zitat von i_make_it Beitrag anzeigen
    if (currentPosition= newPosition+90) {

    Syntaxfehler?
    http://www.arduino-tutorial.de/category/programmieren/

    Arithmetische Operatoren
    = Zuweisung a=2*b Weist der linken Seite den Wert auf der Rechten Seite zu.

    Vergleichsoperatoren
    == Gleichheit a==b Prüft auf Gleichheit.


    currentPosition=bearing;
    wird bei jedem Durchlauf aktualisiert

    und mit dem Inhalt von "newPosition+90" wieder überschrieben.
    if (currentPosition= newPosition+90) {

    Wo "newPosition" herkommt, wann es mit was gesetzt wird und was sicherstellt das es nur einmal am Anfang einer Drehung gesetzt wird kann ich nicht erkennen.
    Ja das ist auch mein Schmerz ... keine Ahnung wie ich newPosition initialieseren , übergeben , deklarieren soll....

  8. #18
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Dein Triggerereigniss ist doch das einer oder mehrere us-Sensoren ein Hinderniss erkennen.

    Wenn du fest um 90° drehen willst,
    fragst Du ab ob die Sensoren was erkennen und der Veriegelungsmerker nicht gesetzt ist.
    Wenn das zutrifft, wird dieser Programmteil ausgeführt.
    Hier setzt Du dann die Variable für die Reaktion (links, Rechts, Rückwärts, wie auch immer).
    Setzt die Variable für den Zielwinkel auf den aktuellen Winkel plus/minus 90°
    Und setzt den Verriegleungsmerker.

    Jetzt hast Du die informatuion in welche Richtung Du drehen musst.
    Den Zielwinkel.
    Und eine Verriegelung die verhindert, das der Teil der das alles verändert nicht wieder durchlaufen wird.

    Im nächsten Programmteil wird abgefragt ob der Verrigelungsmerker gesetzt ist und nur dann der Teil ausgeführt.
    Dort wird dann entsprechend der Variable für die Drehrichtung die Motoren für Linksdrehung oder Rechtsdrehung aktiviert und der Zielwinkel mit dem aktuellen Winkel verglichen.

    Wenn Aktueller Winkel und Zielwinkel gleich sind werden die Motoren gestoppt (oder auf Gradeausfahrt), die Variable für die Reaktion/Richtung wieder auf 0 gesetzt und der Verriegelungsmerker ebenfalls auf 0 gesetzt.
    Damit hat das System wieder den Ausgangszustand.

    Du kannst das Ganze auch entwickeln ohne erst mal eine Zeile code in der Zielspache zu können.

    Male erst mal einen Kreis, und von oben eine Linie die auf den Kreis trifft.

    Der Kreis ist void main(); (Die hauptschleife)

    Die Linie ist void setup(); und was davor kommt (also alles was einmalig beim Power Up des µC durchlaufen wird)

    Jetzt kann man alles was im Programm passiert als Blöcke nehmen und auf kleinen Zetteln auf den Kreis kleben/anheften.

    Wenn Du alles was Du haben willst untergebracht hast, fahre mit dem Finger vom Beginn der Linie in den Kreis und dann im Uhrzeigersinn immer wieder den Kreis entlang.
    Bei jedem Punkt(Block) den Du hast, prüfe nach was passiert dort mit den Werten die alle Variablen zu dem Zeitpunkt haben.
    Mit IF wird dann entweder ein Block ausgeführt oder übersprungen.

    Dabei gehe aber niemals davon aus, das eine aktion wie z.B. um 90° drehen bei einem Kreisdurchlauf erkledigt wird.
    Nimm einfach an bei jedem durchlauf wird 1° geschafft.

    Dann mekrst Du nämlich sofort wenn du noch 89° zu drehen hast und wieder in den Block mit dem Setzen des Zielwinkels springst, das dieser wieder auf 90° unterscheid zum aktuellen winkel gesetzt wird.
    Der Systemzustand wird also nicht verändert sondern das System verbleibt in dem Zustand beginne mit dem Drehen.
    Die Folge ist ein endloses Drehen. Denn bei Jedem Programmdurchlauf wird einfach der bereits geschaffte Winkel wieder auf den noch zu drehenden winkel wieder draufgerechnet.

    So kannst Du mit so einem Ablaufdiagramm alle Systemzustände erst mal definieren und prüfen ob auch Wirklich das passiert was Du haben willst.

    Wenn das funktioniert, kannst Du hingehen und überlegen, was davon muß in der Hauptschleife bleiben und was kann in externe Funktionen ausgelagert werden, um die Zykluszeit der Hauptschleife klein zu halten.

    Am Ende wird der Kreis direkt links von dem Punkt wo die Linie auf ihn trifft aufgetrennt.
    So das du eine lange senkechte Linie hast.
    ausgelagerte Funktionen werden dann einfach unten dran gehängt.
    So bekommst Du
    Alles
    Für allgemeines Setup (includes etc.)
    void setup();
    {
    }
    void main();
    {
    }
    void funktion1();
    {
    }
    .
    .
    .

    Dann kannst Du anfangen zu koden ohne ständig wieder irgendwas anpassen zu müssen damit neues integriert werden kann.
    Oder ein komplett unübersichtlichen Code zu erhalten.


    Mit Deinen Codeschnipseln bin ich nicht klar gekommen,
    Code:
    /////////////////////////////////////////////////////////////
    //     Kompass Modul Abfrage und senden der Daten         ///
    /////////////////////////////////////////////////////////////
     
    byte byteHigh, byteLow; // byteHigh / byteLow für Bearing
    char pitch, roll;       // Pitch und Roll
    int bearing;            // Bearing
     
    Wire.beginTransmission(CMPS10Addr); // Kommunikation mit CMPS10
    Wire.write(2);                      // Start Register (2)
    Wire.endTransmission();
    Wire.requestFrom(CMPS10Addr , 4); // Abfrage von 4 Bytes vom CMPS10
    while (Wire.available() < 4); // Warten, bis 4 Bytes verfügbar
     
      byteHigh = Wire.read();       // High-Byte für Bearing speichern
      byteLow = Wire.read();        // Low-Byte für Bearing speichern
      pitch = Wire.read();          // Byte für Pitch speichern
      roll = Wire.read();           // Byte für Roll speichern
      bearing = ((byteHigh << 8) + byteLow) / 10; // Bearing berechnen
     
      sendData(bearing, pitch, roll);             // Daten versenden
     
     
    void sendData(int bearing, int pitch, int roll) 
    {
       String data = String(bearing) + ";" + String(pitch) + ";" + String(roll);
       lcd.setCursor(0,0);
       lcd.print("bear-pitch-roll");
       lcd.setCursor(0,1);
       lcd.print(data);
       // Serial.println(data);
       delay (100);
    }
    .
    .
    .
    .
    . ???
    .
    .
    .
         nicht Tasktrigger und us2 kleiner 15
      if (!taskTrigger && (uS2 < 15 & uS3 > 30 )) //abstand kleiner als 15cm und abstand links grösser als 30 
      {
        taskTrigger=1;
      }
      else if (!taskTrigger && ( uS2 < 15 & uS1 > 30 )) //wenn abstand kleiner als 15 und links groesser als 30 dann rechts
      {
        taskTrigger=2;
      }
      else if (!taskTrigger && (uS3 < 16)) //wenn abstand kleiner als 16 dann rechts drehen
      {
        taskTrigger=3;
      }
    .
    .
    .
    . ????
    .
    .
    .
      else if (taskTrigger==3) 
      { //nach rechts 
        switch (taskStep) 
        {
        case 0:
          digitalWrite(leftMtrDirPin1, LOW);
          digitalWrite(leftMtrDirPin2, LOW);  
          digitalWrite(rightMtrDirPin1, HIGH);
          digitalWrite(rightMtrDirPin2, LOW); 
          analogWrite(leftMtrSpdPin, 255);   //drive the motor
          analogWrite(rightMtrSpdPin, 255);
          currentPosition=bearing;
          taskStep++;
        break;
        case 1:
          if (currentPosition= newPosition+90) 
          { 
            taskTrigger=0;
            taskStep=0;  
            analogWrite(leftMtrSpdPin, 0);   //stopp the motors
            analogWrite(rightMtrSpdPin, 0);     
          }
        }
      }
    .
    .
    .
    .
    .
    .
    Ich kann nicht sagen ob und wo Du eventuell Syntaxfehler drin hast oder ungünstig was weggelassen hast.

    Schon bei:
    while (Wire.available() < 4);
    müsste von der Syntax eigentlich danach
    {
    der Code der solange ausgeführt wird
    }
    kommen.
    Und wenn es nur delay ist.
    Wobei es strittig ist ob man ein wire.available überhaupt braucht, da die Daten ja im Empfangspuffer stehen sollten.
    Geändert von i_make_it (14.06.2017 um 12:22 Uhr)

  9. #19
    HaWe
    Gast
    Zitat Zitat von i_make_it Beitrag anzeigen
    Schon bei:
    while (Wire.available() < 4);
    müsste von der Syntax eigentlich danach
    {
    der Code der solange ausgeführt wird
    }
    kommen.
    Und wenn es nur delay ist.
    Wobei es strittig ist ob man ein wire.available überhaupt braucht, da die Daten ja im Empfangspuffer stehen sollten.
    wieso?

    Wire.requestFrom(CMPS10Addr , 4);
    fordert 4 Bytes von der dev addr an, und
    while (Wire.available() < 4);
    wartet einfach solange, bis 4 Bytes tatsächlich im i2c-Puffer vorliegen.
    Und danach geht's weiter.

    so funktioniert einfach nun mal das API der Wire() class.

  10. #20
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Also
    Wire.endTransmission();
    Beendet die Übertragung und könnte mit den Returncodes 0 bis 4 zum Auswerten des Fehlerstatus benutzt werden.

    Wire.requestFrom(CMPS10Addr , 4);
    Fragt die (in diesem Fall 4) Bytes vom Slave ab. Danach stehen sie im Eingangspuffer.

    Wire.available()
    Gibt an wie viele Bytes im Puffer stehen.

    while (Wire.available() < 4);
    Wartet solange Wire.available() kleiner 4 ist.

    Aber ohne Abbruchbedingung falls der Vergleichswert nie erreicht wird und ohne einen Befehl der die Schleife verzögert.

    Sinnvoll wäre z.B. eine zweite, veroderte Abbruchbedingung und im Körper der Whileschleife ein Hochzählen.
    Wenn dann z.B. nach 1000 Schleifendurchläufen keine 4 Bytes vorhanden sind wird die Schleife durch die zweite Abbruchbedingung trotzdem terminiert und man kännte den Zählerstand auf Erreichen des Maximalwertes auswerten um danach eine Fehlerbehandlung zu starten.

    Will mann es unsauber, Quick & dirty machen, kann man es natürlich nackt hinschreiben, dann kann man es aber auch ganz weglassen und einfach ungeprüft den Puffer auslesen.

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Ähnliche Themen

  1. Motorsteuerung über Joystick
    Von konstii im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 3
    Letzter Beitrag: 18.06.2009, 10:38
  2. LPT motorsteuerung über den drucker
    Von st0rm im Forum Motoren
    Antworten: 1
    Letzter Beitrag: 10.12.2007, 15:45
  3. Motorsteuerung über Fahrtenregler
    Von glory im Forum Motoren
    Antworten: 2
    Letzter Beitrag: 01.06.2007, 20:34
  4. Motorsteuerung über RS232/USB
    Von ama7224290 im Forum Motoren
    Antworten: 0
    Letzter Beitrag: 07.02.2007, 17:24
  5. Motorsteuerung über PI-Regler
    Von Gromit im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 0
    Letzter Beitrag: 19.11.2004, 22:44

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress