NXT Balance

Java und so~

Mitglied
Alsooo~

Ich versuche gerade ein Programm zu schreiben, was bewirken soll, dass ein NXT mit zwei Lichtsensoren auf zwei Rädern balanciert.
Bis jetzt funktioniert mein Programm allerdings nur sehr schlecht...

wie kriegt man das besser hin ?

Code:
Java:
import lejos.nxt.*;
import lejos.nxt.addon.*;
import lejos.robotics.navigation.*;
import lejos.nxt.comm.*;

public class Balance {
      
  public static void main(String[] args) throws Exception {
    LightSensor light1 = new LightSensor(SensorPort.S1);
    LightSensor light2 = new LightSensor (SensorPort.S2);
    int x, y;
    Motor.A.setPower(20);
    Motor.B.setPower(20);
    
    while (!Button.ESCAPE.isPressed()) {
      LCD.drawString(""+light1.readValue(), 0, 1);
      LCD.drawString (""+light2.readValue(), 0, 2);
      x = light1.readValue();
      y = light2.readValue();
      
      if (x < y) {
        int z = x-y;
        LCD.drawString("Z: "+z, 0,3 );
        Motor.A.setPower(z);
        Motor.A.backward();
        Motor.B.setPower(z);
        Motor.B.backward();
        x = light1.readValue();
        y = light2.readValue();
      } else if (x > y) {
        int z = y-x;
        LCD.drawString("Z: "+z, 0,4 );
        Motor.A.setPower(z);
        Motor.A.forward();
        Motor.B.setPower(z);
        Motor.B.forward();
        x = light1.readValue();
        y = light2.readValue();
      }
      Thread.sleep(30);
    }
  }
}
 

chalkbag

Bekanntes Mitglied
NXT sind glaub ich diese Legoteile?

Java:
      LCD.drawString(""+light1.readValue(), 0, 1);
      LCD.drawString (""+light2.readValue(), 0, 2);
      x = light1.readValue();
      y = light2.readValue();

LCD Wert ist nicht gleich dem verwendeten Wert, also eher in etwa so


Java:
      x = light1.readValue();
      y = light2.readValue();
      LCD.drawString(""+x, 0, 1);
      LCD.drawString (""+y, 0, 2);


Ich glaube Balance verstehe ich hier auch falsch. Du fährst zwar vor und zurück, auch weiß ich nicht wo deine Lichtsensoren stecken, aber ich denke das wird mit den Sensoren nicht "perfekt" klappen. Hast du nicht sowas wie ein Bewegungssensor /Neigungssensor oder ähnliches, so wie wir es aus dem dollem idings kennen?
ich glaub schlichtweg die lichtsensoren sind zu langsam bzw. zu ungeau für dieses Problem? So sollte er von einer auf die andere Seite fallen?
 

Java und so~

Mitglied
Okay, das schonmal zur Ausgabe... allerdings bleibt noch immer das Problem, mit dem balancieren :D
mit den Lichtsensoren funktioniert es auf jeden Fall (siehe: YouTube - Balancing NXT with two light sensors ). Ich habe den Code nochmal umgeändert:

Java:
import lejos.nxt.comm.*;

public class Balance {
      
  public static void main(String[] args) throws Exception {
    LightSensor light1 = new LightSensor(SensorPort.S1);
    LightSensor light2 = new LightSensor (SensorPort.S2);
    int x, y;
    Motor.A.setSpeed(720);
    Motor.B.setSpeed(720);
    Motor.A.forward();
    Motor.B.forward();
    
    while (!Button.ESCAPE.isPressed()) {
      x = light1.readValue();
      y = light2.readValue();
      LCD.drawString(""+x, 0, 1);
      LCD.drawString (""+y, 0, 2);

      Thread.sleep(20);

      if (x > y && (x - y)>=1) {
        Motor.A.setSpeed(7200);
        Motor.B.setSpeed(7200);
        Motor.A.forward();
        Motor.B.forward();
        Thread.sleep(10);
      } else  if (x < y && (y - x)>=1) {
        Motor.A.setSpeed(7200);
        Motor.B.setSpeed(7200);
        Motor.A.backward();
        Motor.B.backward();
        Thread.sleep(10);
      }
    }
  }
}
Der Fehler liegt aus meiner Sicht bei den if-Anweisungen. Dort habe ich die Geschwindigkeit geändert, allerdings bleib er dann bei der Geschwindigkeit, ws er nicht tun soll, er soll sie nur als "kurzen Impuls" auffassen und nicht als neue Geschwindigkeit. Wie krieg ich es jetzt hin, dass er nur für ein paar Millisekunden das Tempo ändert und dann zurück zum alten geht?
 
Zuletzt bearbeitet:

chalkbag

Bekanntes Mitglied
Ich bin nicht wirklich erfahren, was NXE angeht.

Aber er fährt halt mindestens 20 Millisekunden.
Würde es nich helfen,

Geschwindigikeit setzen auf 7200
Fahren
Geschwindigkeit setzen auf 0
(fährt er dann noch, ansonsten fahren mit Geschwindigkeit 0)

Kann auch sein das man andere schwellwerte für den lichtsensor braucht.

Wie gesagt, ich hab keine Ahnung, wi rhaben nur mal die typische Linienverfolgung umgesetzt, und das ist schon bisl her, also rate ich nur ins Blinde. :bahnhof:
 

chalkbag

Bekanntes Mitglied
Servus, hab mir gerade das Video angeguckt, da ich das in der Arbeit nicht konnte.
Ist auf jeden Fall eine sehr gute Leistung, man muss aber auch sagen das das Resultat aus einer 6 monatigen Diplomarbeit enstanden ist, also wohl doch nicht ganz trivial ;)

Wenn du das auch erreich willst denk ich gibt es ganz viel auszuprobieren. Man muss wohl die Geschwindigkeit anhand der Neigung, welche du mittels Lichtsensor wohl errechnen kannst, berechnen /anpassen. Sicherlich spielt der Reifenradius noch in die aktuelle Geschwindigkeit mit ein.

Also Block raus, Formelsammlung aufgeschlagen und in die Hände gespuckt. Ich freu mich auf Resultate. Nicht entmutigen lassen, wenn das für ein Thema der Diplomarbeit reicht, klingt das nach Arbeit :applaus:
 

Java und so~

Mitglied
Also arbeit ist es auf jeden Fall, allerdings haben andere "Nichtdiplomarbeitenschreiber" es auch irgendwie hingekriegt... also müsste es ja irgendwie in 2-3 Wochen zu schaffen sein...
Das mit den Formeln hab ich auch schonmal in Betracht gezogen, habe aber bis jetzt nichts gefunden was mir irgendwie weiter helfen könnte...
Naja, auf jeden Fall werd ich es weiter machen bis dieses Ding endlich balanciert oder es explodiert, weil es kein Bock mehr hat, je nachdem ;D

Hab ich grade noch gefunden:
Java:
#pragma config(Sensor, S3,     light,               sensorLightActive)
#pragma config(Motor,  motorA,          mA,            tmotorNormal, openLoop, reversed)
#pragma config(Motor,  motorB,          mB,            tmotorNormal, openLoop, reversed)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 
 
/* Author : Mohammed Al-Mohanna
*
*       This program is a balance program using the light sensor
*       It uses PD control (since there is no steady state error, there is no need for the integral portion
*       Using scale to accommodate for the battery difference:
*       when the battery full it is 2 and when it is half depleted it is 1 (no scaling down)
*/
task main(){
 
  float kp = 11,
        kd = 14,
        scale = 2;
 
  float  p=0,
                 d=0;
 
  int output,
          error = 0,
          goal,
          actual_position,
          previous_error;
 
  wait10Msec(10);
 
  //initializing the goal by taking 101 reading and statistically compute it
  goal = SensorRaw[S3];
  for(int n; n< 100;n++){
        goal = (goal * 15 + SensorRaw[S3] )/16  ;
        wait1Msec(1);
  }
 
        //Calculate pd for one time “unit”
  while (1){
        //synchronizing both motors B and C
        nSyncedMotors = synchBC;
        nSyncedTurnRatio = 100;
       
        actual_position = SensorRaw[S3];
        previous_error = error;
        error = goal - actual_position;
       
        //computing the propotional part
        p = kp * error;
       
        //computing the deferintial part
        d = kd * (error - previous_error);
       
        output = p + d;
       
        //scaling down the output level if the battery is fresh
    output /= scale;
    motor[motorB] = (int) output;
    wait1Msec(5);
        }
}
leider ist das kein Java undich hab keine Ahnung, was das sonst für ne ProgSprache ist, allerdings soll es mit diesem Code gehen... weiß nur nicht wie ich den in Java umformulieren kann... ???:L
 
Zuletzt bearbeitet:

Java und so~

Mitglied
Noch ein kleiner Zusatz...

Mein bisheriger Code
Java:
import lejos.nxt.*;
import lejos.nxt.addon.*;
import lejos.robotics.navigation.*;
import lejos.nxt.comm.*;

public class Balance {
      
  public static void main(String[] args) throws Exception {
    LightSensor light1 = new LightSensor(SensorPort.S1);
    LightSensor light2 = new LightSensor (SensorPort.S2);
    int x = 0, y = 0, z = 2;
    Motor.A.backward();
    Motor.B.backward();
    
    while (!Button.ESCAPE.isPressed()) {
      x = light1.readValue();
      y = light2.readValue();
      LCD.drawString(""+x, 0, 1);
      LCD.drawString (""+y, 0, 2);
      Motor.A.setSpeed(360);
      Motor.B.setSpeed(360);

      if (x > y && (x - y)>=1) {
          Motor.A.setSpeed(900);
          Motor.B.setSpeed(900);
          Motor.A.forward();
          Motor.B.forward();
      } else  if (x < y && (y - x)>=1) {
          Motor.A.setSpeed(900);
          Motor.B.setSpeed(900);
          Motor.A.backward();
          Motor.B.backward();
      }
    }
  }
}

Mein Problem ist noch immer das alte: die Geschwindigkeit 900 in den if-Schleifen, soll nur kurzzeitig - als Impuls - gesetzt werden, allerdings bleibt er dann bei der Geschwindigkeit und geht nicht zurück zur 360. Wenn ich vor den i-Schleifen einen Thread.sleep mache, bleibt er nur bei 360 und verwendet die 900 nicht mehr und wenn dich denThrea.sleep in den if-Schleifen mache, bleibt er bei 900 und geht nicht zurück zur 360. Also wie krieg ich es jetzt hin, dass er die 900 nur als Impuls für 1-2 Millisekunden setzt? ???:L
 

chalkbag

Bekanntes Mitglied
Java:
while (!Button.ESCAPE.isPressed()) {
      x = light1.readValue();
      y = light2.readValue();
      LCD.drawString(""+x, 0, 1);
      LCD.drawString (""+y, 0, 2);
     
      if (x > y && (x - y)>=1) {
          Motor.A.setSpeed(900);
          Motor.B.setSpeed(900);
          Motor.A.forward();
          Motor.B.forward();
      } else  if (x < y && (y - x)>=1) {
          Motor.A.setSpeed(900);
          Motor.B.setSpeed(900);
          Motor.A.backward();
          Motor.B.backward();
      }
      Motor.A.setSpeed(0);
      Motor.B.setSpeed(0);
      Motor.A.forward();
      Motor.B.forward();

Ich denke wenn du die Geschwindigkeit setzt, musst du die Motoren danach auch bewegen.
 

Java und so~

Mitglied
Okay, sadistische Gedanken sind mal wieder auf Hochturen und gute Laune am Tiefpunkt... also nächstes "grandioses" Problem: Es gab früher mal eine MEthode die TachoNavigator hieß, wurde dann in SimpleNavigator umbenannt, die es so aber auch nicht mehr gibt und jetzt wahrscheinlich LegacyNavigator heißt... aber den LegacyNavigator gibt es auchn icht mehr (was'n Wunder...), also hat mal jemand 'ne Idee, wie das Ding jetzt heißt?!
 

Neue Themen


Oben