- 3D-Druck Einstieg und Tipps    Werbung      
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 19 von 19

Thema: Einstieg in das EV3 System mit 31313

  1. #11
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    14.04.2007
    Ort
    Einhausen
    Alter
    70
    Beiträge
    701
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hier sieht man gut die Möglichkeiten des BrickPI3. Interessante Perspektive. Ist der Raspberry Pi in dem Brick bereits enthalten, oder ist das nur ein Interface zwischen Lego und Raspberrv PI?

    Wie auch immer, das spricht doch alles sehr für EV3 als Einstieg.

  2. #12
    HaWe
    Gast
    nein, der Pi ist in den BasicSets nicht dabei, es ist ein Shield (stackable), und die Ports sind sogar auch NXT-Sensor/Motor-kompatibel.
    Geändert von HaWe (19.07.2020 um 14:19 Uhr) Grund: BasicSets

  3. #13
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    14.04.2007
    Ort
    Einhausen
    Alter
    70
    Beiträge
    701
    Die LEGO-Seite habe ich verstanden, auch den I²C Anschluss. Passt der Raspberry Pi auch noch in den BrickPi3 hinein? Z.B. hier. Ist da der Raspberry Pi integriert? Da steht, dass ein Raspberry Pi 3 dabei ist. Wo genau wird dieser angeschlossen?

    Zurzeit hat der EV3 halt viele Vorteile, weil er kompakt ist und seine Akkus innen dabei hat. Das Display ist auch brauchbar. Dazu Bluetooth. Nachteil ist, dass ein Akku-Wechsel nicht ganz einfach ist.

    Auf jeden Fall ist das eine klasse Sache, dass man da weiter wachsen kann, noch dazu recht flexibel. Danke nochmals für den wichtigen Hinweis.

  4. #14
    HaWe
    Gast
    ja, dort ist noch ein Pi3 dabei, vlt aber noch der alte, nicht der neue 3B+, weiß ich aber nicht. Der BrickPi3 ist ein Shield zum Aufstecken (26-pol Header) , da passt nichts "hinein".

    - - - Aktualisiert - - -

    PS,
    neues Thema => bitte neues Topic!

  5. #15
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    14.04.2007
    Ort
    Einhausen
    Alter
    70
    Beiträge
    701
    Ja, wir bleiben zunächst beim EV3. Alleine die Schlange "R3PTAR" ist schon den Kauf wert. Eine Meisterleistung von LEGO und auch bezüglich Programmierung interessant.

  6. #16
    Neuer Benutzer Öfters hier
    Registriert seit
    17.09.2020
    Beiträge
    11
    ehenkes was kannst du über die R3PTAR berichten?

  7. #17
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    14.04.2007
    Ort
    Einhausen
    Alter
    70
    Beiträge
    701
    Die Schlange R3PTAR ist einfach klasse. Der Überraschungseffekt, wenn sie mit ihren Zähnen zuschnappt, das gefällt vor allem den Kindern. Aufbau und Programmierung sind ebenfalls gut gemacht. Für mich ein Highlight.

  8. #18
    Neuer Benutzer Öfters hier Avatar von JayWay
    Registriert seit
    01.10.2011
    Ort
    Dresden
    Alter
    55
    Beiträge
    21
    Noch ein Nachtrag der von Interesse sein könnte...

    Meine beiden Söhne arbeiten im Gymnasium im Informatik-Unterricht mit Python (Tigerjython). Nachdem ich Python auch für verschiedene Dinge verwende habe ich da mal etwas tiefer nachgegraben. Als erstes fand ich Neuigkeiten bei Texas Instruments, die für Ihre CAS und GTR seit kurzem ein Update mit Circuitpython als Programmiersprache anbieten. Da lag es nahe, auch mal wieder bei LEGO nachzusehen und siehe da, für die Hubs (EV3, Inventor...) von LEGO gibt es jetzt ebenfalls eine Variante mit Python.

    Lego, offiziell
    Pybricks, das Projekt

    Was soll ich sagen, die Kiste mit den EV3 und NXT-Teilen wurde umgehend entstaubt und es rollen und robben wieder die wunderlichsten Systeme durch die Wohnung. Zumindest um Informatik muss ich mir jetzt in "Home-Schooling-Zeiten" keine Gedanken mehr machen.

    Gruß Jay
    Lächle am Morgen, dann hast du es hinter dir.

  9. #19
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    14.04.2007
    Ort
    Einhausen
    Alter
    70
    Beiträge
    701
    Wir sind nun im Zeitalter der KI angekommen. Daher habe ich mit ChatGPT diskutiert, was man so mit den alten EV3 Sets machen könnte. Zunächst habe ich den "Farbsortierer" https://assets.education.lego.com/v3...f?locale=de-de verwendet, da ich mit der visuellen Lego-Programmierung Probleme hatte, die Farben grün und blau sicher zu unterscheiden. ChatGPT-5.6 Sol hat zunächst via usb-Anbindung mit mir zusammen recht schnell eine C# .Net Konsolen-Anwendung gebastelt, die gut funktioniert. Als Modul in .Net wurde HidSharp verwendet, da ein LegoMindstorms-Modul nicht funktionierte.
    Längerfristig ist eine Idee, zwei EV3-Systeme zusammen mit einer zentralen Steuerung auf dem PC mit WebCams verschiedene Aufgaben erledigen zu lassen.
    Hier ist das aktuelle C#-Programm:
    // ================================================== ==========================
    // LEGO MINDSTORMS EV3 Color Sorter
    //
    // PC-controlled version using direct EV3 USB/HID commands.
    // No program has to be downloaded to the EV3 brick.
    //
    // Hardware:
    // Motor A - eject/feed mechanism
    // Motor D - sorter carriage positioning mechanism
    // Sensor S1 - touch sensor / carriage home switch
    // Sensor S3 - EV3 color sensor
    //
    // NuGet:
    // HidSharp
    // ================================================== ==========================using System.Buffers.Binary;
    using System.Diagnostics;
    using HidSharp;


    namespace Ev3ColorSorter;


    internal static class Program
    {
    private static void Main()
    {
    Console.WriteLine("LEGO EV3 Color Sorter - C# USB Control");
    Console.WriteLine("--------------------------------------");
    Console.WriteLine();


    try
    {
    using var ev3 = Ev3Brick.ConnectUsb();


    var classifier = ColorClassifier.CreateFromLearnedCentroids();


    var sorter = new ColorSorterController(ev3, classifier);


    sorter.RunInteractive();
    }
    catch (Exception ex)
    {
    Console.WriteLine();
    Console.WriteLine("ERROR:");
    Console.WriteLine(ex.Message);
    }


    Console.WriteLine();
    Console.WriteLine("Program finished.");
    }
    }


    internal sealed class ColorSorterController
    {
    private readonly Ev3Brick _ev3;
    private readonly ColorClassifier _classifier;


    private static readonly Dictionary<SortColor, int> BinPositions =
    new()
    {
    [SortColor.Blue] = 10,
    [SortColor.Green] = 132,
    [SortColor.Yellow] = 360,
    [SortColor.Red] = 530
    };


    private const int BatchCapacity = 8;


    // Raw RGB brightness required to consider an object present.
    private const int ObjectBrightnessThreshold = 10;


    // Reject classifications that are too close to a second color.
    private const double MinimumConfidence = 0.20;


    private bool _ejectorHomed = false;


    public ColorSorterController(
    Ev3Brick ev3,
    ColorClassifier classifier)
    {
    _ev3 = ev3;
    _classifier = classifier;
    }


    public void RunInteractive()
    {
    Console.WriteLine("EV3 connected successfully.");
    Console.WriteLine();
    Console.WriteLine("Commands:");
    Console.WriteLine(" H = Home sorter carriage (Motor D)");
    Console.WriteLine(" E = Test one eject cycle (Motor A)");
    Console.WriteLine(" P = Test sorter bin positions (Motor D)");
    Console.WriteLine(" R = Run one complete sorting batch");
    Console.WriteLine(" Q = Quit");
    Console.WriteLine();


    while (true)
    {
    Console.Write("> ");


    ConsoleKey key = Console.ReadKey(true).Key;


    try
    {
    switch (key)
    {
    case ConsoleKey.H:
    HomeCarriage();
    break;


    case ConsoleKey.E:
    TestEjector();
    break;


    case ConsoleKey.P:
    TestBinPositions();
    break;


    case ConsoleKey.R:
    RunBatch();
    break;


    case ConsoleKey.Q:
    SafeStop();
    return;
    }
    }
    catch (Exception ex)
    {
    SafeStop();


    Console.WriteLine();
    Console.WriteLine($"Operation aborted: {ex.Message}");
    Console.WriteLine();
    }
    }
    }

    private void RunBatch()
    {
    Console.WriteLine();
    Console.WriteLine("=== NEW SORTING BATCH ===");
    Console.WriteLine();


    HomeEjector();
    HomeCarriage();


    List<SortColor> colors = ScanBatch();


    if (colors.Count == 0)
    {
    Console.WriteLine("No objects registered.");
    return;
    }


    Console.WriteLine();
    Console.WriteLine($"Sorting {colors.Count} object(s)...");
    Console.WriteLine();


    SortBatch(colors);


    Console.WriteLine();
    Console.WriteLine("Returning carriage to home...");
    HomeCarriage();


    _ev3.PlayTone(880, 150);


    Console.WriteLine();
    Console.WriteLine("Batch completed.");
    Console.WriteLine();
    }

    private void HomeCarriage()
    {
    Console.WriteLine();
    Console.WriteLine("Homing sorter carriage...");


    // If the switch is already pressed, the carriage is already at home.
    if (!_ev3.ReadTouchSensor())
    {
    // Move toward the home switch.
    _ev3.RunMotorPower(
    MotorPort.D,
    -20);


    var timeout = Stopwatch.StartNew();


    while (!_ev3.ReadTouchSensor())
    {
    if (timeout.Elapsed > TimeSpan.FromSeconds(6))
    {
    _ev3.StopMotor(MotorPort.D);


    throw new TimeoutException(
    "Carriage home switch was not reached.");
    }


    Thread.Sleep(20);
    }
    }


    _ev3.StopMotor(MotorPort.D);


    Thread.Sleep(200);


    // Define this mechanical position as encoder position zero.
    _ev3.ClearMotorCount(MotorPort.D);


    Thread.Sleep(50);


    int position = _ev3.ReadMotorCount(MotorPort.D);


    Console.WriteLine(
    $"Carriage home position established: {position}°");
    }

    private List<SortColor> ScanBatch()
    {
    var result = new List<SortColor>();


    Console.WriteLine();
    Console.WriteLine("SCAN MODE");
    Console.WriteLine(
    $"Scan up to {BatchCapacity} objects using the color sensor.");
    Console.WriteLine("Press ENTER to start sorting early.");
    Console.WriteLine("Press Q to cancel the batch.");
    Console.WriteLine();


    while (result.Count < BatchCapacity)
    {
    if (Console.KeyAvailable)
    {
    ConsoleKey key = Console.ReadKey(true).Key;


    if (key == ConsoleKey.Enter && result.Count > 0)
    break;


    if (key == ConsoleKey.Q)
    return new List<SortColor>();
    }


    RgbRaw raw = _ev3.ReadRgbRaw();


    if (raw.Brightness < ObjectBrightnessThreshold)
    {
    Thread.Sleep(40);
    continue;
    }


    Chromaticity? measured = CaptureStableColor();


    if (measured is null)
    continue;
    Console.WriteLine(
    $"Measured: r={measured.Value.R:F3} " +
    $"g={measured.Value.G:F3} " +
    $"b={measured.Value.B:F3}");


    ColorClassification classification =
    _classifier.Classify(measured.Value);


    if (classification.Confidence < MinimumConfidence)
    {
    Console.WriteLine(
    $"Color uncertain " +
    $"({classification.Color}, " +
    $"{classification.Confidence:P0}). " +
    $"Please scan again.");


    _ev3.PlayTone(300, 150);


    WaitUntilObjectRemoved();


    continue;
    }


    result.Add(classification.Color);


    Console.WriteLine(
    $"#{result.Count}: " +
    $"{classification.Color,-6} " +
    $"confidence {classification.Confidence:P0}");


    _ev3.PlayTone(
    FrequencyForColor(classification.Color),
    100);


    WaitUntilObjectRemoved();
    }


    if (result.Count == BatchCapacity)
    {
    Console.WriteLine();
    Console.WriteLine(
    "Batch is full. Place the last object into the chute.");
    Console.WriteLine(
    "Press ENTER when all objects are ready for sorting.");


    while (Console.ReadKey(true).Key != ConsoleKey.Enter)
    {
    }
    }


    Console.WriteLine();


    Console.WriteLine(
    "Registered sequence: " +
    string.Join(" -> ", result));


    return result;
    }


    private Chromaticity? CaptureStableColor()
    {
    const int requestedSamples = 7;


    double sumR = 0;
    double sumG = 0;
    double sumB = 0;


    int validSamples = 0;


    for (int i = 0; i < requestedSamples; i++)
    {
    RgbRaw raw = _ev3.ReadRgbRaw();


    if (raw.Brightness >= ObjectBrightnessThreshold)
    {
    Chromaticity c = Chromaticity.FromRaw(raw);


    sumR += c.R;
    sumG += c.G;
    sumB += c.B;


    validSamples++;
    }


    Thread.Sleep(20);
    }


    if (validSamples < 4)
    return null;


    return new Chromaticity(
    sumR / validSamples,
    sumG / validSamples,
    sumB / validSamples);
    }




    private void WaitUntilObjectRemoved()
    {
    int consecutiveEmptyReadings = 0;


    var timeout = Stopwatch.StartNew();


    while (timeout.Elapsed < TimeSpan.FromSeconds(10))
    {
    RgbRaw raw = _ev3.ReadRgbRaw();


    if (raw.Brightness < ObjectBrightnessThreshold)
    {
    consecutiveEmptyReadings++;


    if (consecutiveEmptyReadings >= 3)
    return;
    }
    else
    {
    consecutiveEmptyReadings = 0;
    }


    Thread.Sleep(30);
    }
    }


    private void SortBatch(IReadOnlyList<SortColor> colors)
    {
    for (int i = 0; i < colors.Count; i++)
    {
    SortColor color = colors[i];


    int targetPosition = BinPositions[color];


    Console.WriteLine(
    $"Object #{i + 1}: {color,-6} -> " +
    $"carriage target {targetPosition}°");


    _ev3.MoveMotorTo(
    MotorPort.D,
    targetPosition,
    speedPercent: 45);


    Thread.Sleep(250);


    EjectOneObject();


    Thread.Sleep(350);
    }
    }


    private const int EjectorHomeBackoff = 230;
    private const int EjectorStroke = 180;


    private void HomeEjector()
    {
    const int homingPower = 40;


    Console.WriteLine("Searching for Motor A mechanical stop...");


    int previousPosition =
    _ev3.ReadMotorCount(MotorPort.A);


    int stationarySamples = 0;


    var timeout = Stopwatch.StartNew();


    _ev3.RunMotorPower(
    MotorPort.A,
    homingPower);


    try
    {
    while (true)
    {
    Thread.Sleep(60);


    int currentPosition =
    _ev3.ReadMotorCount(MotorPort.A);


    int movement =
    Math.Abs(
    currentPosition -
    previousPosition);


    previousPosition = currentPosition;


    if (movement <= 1)
    stationarySamples++;
    else
    stationarySamples = 0;


    if (stationarySamples >= 12)
    break;


    if (timeout.Elapsed > TimeSpan.FromSeconds(5))
    {
    throw new TimeoutException(
    "Motor A mechanical stop was not detected.");
    }
    }
    }
    finally
    {
    _ev3.StopMotor(MotorPort.A);
    }


    Console.WriteLine("Motor A stop detected.");


    Thread.Sleep(150);


    // The mechanical stop is our reference position.
    int detectedStop = _ev3.ReadMotorCount(MotorPort.A);
    Console.WriteLine($"Detected Motor A stop at encoder position: {detectedStop}°");
    _ev3.ClearMotorCount(MotorPort.A);


    Console.WriteLine($"Backing Motor A away from stop by {EjectorHomeBackoff}°...");


    _ev3.MoveMotorRelative(
    MotorPort.A,
    -EjectorHomeBackoff,
    speedPercent: 35);


    int position =
    _ev3.ReadMotorCount(MotorPort.A);


    Console.WriteLine(
    $"Motor A home position established: {position}°");


    _ejectorHomed = true;
    }

    private void EjectOneObject()
    {
    int start = _ev3.ReadMotorCount(MotorPort.A);


    Console.WriteLine(
    $"Motor A start position: {start}°");


    _ev3.MoveMotorRelative(
    MotorPort.A,
    +EjectorStroke,
    speedPercent: 35);


    int forward = _ev3.ReadMotorCount(MotorPort.A);


    Console.WriteLine(
    $"After eject movement: {forward}° " +
    $"(delta {forward - start}°)");


    Thread.Sleep(150);


    _ev3.MoveMotorRelative(
    MotorPort.A,
    -EjectorStroke,
    speedPercent: 35);


    int back = _ev3.ReadMotorCount(MotorPort.A);


    Console.WriteLine(
    $"After return movement: {back}° " +
    $"(delta {back - start}°)");
    }




    private void TestEjector()
    {
    Console.WriteLine();


    if (!_ejectorHomed)
    {
    Console.WriteLine("Motor A is not initialized yet.");
    Console.WriteLine("Homing Motor A...");


    HomeEjector();
    }


    Console.WriteLine("Running one Motor A eject cycle...");


    EjectOneObject();


    Console.WriteLine("Eject cycle completed.");
    Console.WriteLine();
    }




    private void SafeStop()
    {
    try
    {
    _ev3.StopMotor(MotorPort.A);
    }
    catch
    {
    }


    try
    {
    _ev3.StopMotor(MotorPort.D);
    }
    catch
    {
    }
    }




    private static int FrequencyForColor(SortColor color)
    {
    return color switch
    {
    SortColor.Blue => 600,
    SortColor.Green => 750,
    SortColor.Yellow => 900,
    SortColor.Red => 1050,
    _ => 800
    };
    }


    private void TestBinPositions()
    {
    Console.WriteLine();
    Console.WriteLine("=== SORTER POSITION TEST ===");
    Console.WriteLine();


    HomeCarriage();


    SortColor[] testOrder =
    {
    SortColor.Blue,
    SortColor.Green,
    SortColor.Yellow,
    SortColor.Red
    };


    foreach (SortColor color in testOrder)
    {
    int target = BinPositions[color];


    Console.WriteLine();
    Console.WriteLine(
    $"Press ENTER to move to {color} ({target}°), " +
    "or Q to abort.");


    while (true)
    {
    ConsoleKey key = Console.ReadKey(true).Key;


    if (key == ConsoleKey.Q)
    {
    Console.WriteLine("Position test aborted.");
    HomeCarriage();
    return;
    }


    if (key == ConsoleKey.Enter)
    break;
    }


    _ev3.MoveMotorTo(
    MotorPort.D,
    target,
    speedPercent: 25);


    int actual =
    _ev3.ReadMotorCount(MotorPort.D);


    Console.WriteLine(
    $"Motor D position: {actual}° " +
    $"(target {target}°)");


    Console.WriteLine(
    "Check the mechanical alignment before continuing.");
    }


    Console.WriteLine();
    Console.WriteLine("All four positions tested.");
    Console.WriteLine("Returning carriage to home...");


    HomeCarriage();


    Console.WriteLine("Position test completed.");
    Console.WriteLine();
    }
    }


    internal sealed class ColorClassifier
    {
    private readonly Dictionary<SortColor, Chromaticity> _centroids;


    private ColorClassifier(
    Dictionary<SortColor, Chromaticity> centroids)
    {
    _centroids = centroids;
    }




    public static ColorClassifier CreateFromLearnedCentroids()
    {
    return new ColorClassifier(
    new Dictionary<SortColor, Chromaticity>
    {
    [SortColor.Red] =
    new Chromaticity(
    0.490,
    0.229,
    0.281),


    [SortColor.Green] =
    new Chromaticity(
    0.179,
    0.458,
    0.363),


    [SortColor.Blue] =
    new Chromaticity(
    0.162,
    0.186,
    0.653),


    [SortColor.Yellow] =
    new Chromaticity(
    0.376,
    0.335,
    0.289)
    });
    }




    public ColorClassification Classify(
    Chromaticity measured)
    {
    var distances =
    _centroids
    .Select(
    item => new
    {
    Color = item.Key,
    Distance =
    measured.DistanceTo(item.Value)
    })
    .OrderBy(item => item.Distance)
    .ToArray();


    var best = distances[0];
    var second = distances[1];


    double confidence;


    if (second.Distance <= 1e-12)
    {
    confidence = 1.0;
    }
    else
    {
    confidence =
    1.0 -
    best.Distance /
    second.Distance;
    }


    confidence =
    Math.Clamp(
    confidence,
    0.0,
    1.0);


    return new ColorClassification(
    best.Color,
    best.Distance,
    confidence);
    }
    }


    internal sealed class Ev3Brick : IDisposable
    {
    private const int LegoVendorId = 0x0694;
    private const int Ev3ProductId = 0x0005;


    private const byte DirectCommandReply = 0x02;


    private readonly HidDevice _device;
    private readonly HidStream _stream;


    private ushort _messageCounter;




    private Ev3Brick(
    HidDevice device,
    HidStream stream)
    {
    _device = device;
    _stream = stream;


    _stream.ReadTimeout = 3000;
    _stream.WriteTimeout = 3000;
    }




    public static Ev3Brick ConnectUsb()
    {
    HidDevice? device =
    DeviceList.Local.GetHidDeviceOrNull(
    LegoVendorId,
    Ev3ProductId);


    if (device is null)
    {
    throw new InvalidOperationException(
    "EV3 USB device was not found.");
    }


    HidStream stream = device.Open();


    return new Ev3Brick(
    device,
    stream);
    }



    public RgbRaw ReadRgbRaw()
    {
    var op = new List<byte>();


    op.Add(0x99); // opINPUT_DEVICE
    op.Add(0x1C); // READY_RAW


    AddConstant(op, 0); // Layer
    AddConstant(op, 2); // S3 -> internal port 2
    AddConstant(op, 29); // EV3 Color Sensor
    AddConstant(op, 4); // RGB-RAW mode
    AddConstant(op, 3); // Three values


    AddGlobalVariable(op, 0);
    AddGlobalVariable(op, 4);
    AddGlobalVariable(op, Bild   ;


    byte[] data =
    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 12);


    int r =
    BinaryPrimitives.ReadInt32LittleEndian(
    data.AsSpan(0, 4));


    int g =
    BinaryPrimitives.ReadInt32LittleEndian(
    data.AsSpan(4, 4));


    int b =
    BinaryPrimitives.ReadInt32LittleEndian(
    data.AsSpan(8, 4));


    return new RgbRaw(r, g, b);
    }


    public bool ReadTouchSensor()
    {
    var op = new List<byte>();


    op.Add(0x99); // opINPUT_DEVICE
    op.Add(0x1D); // READY_SI


    AddConstant(op, 0); // Layer
    AddConstant(op, 0); // S1 -> internal port 0
    AddConstant(op, 16); // EV3 Touch Sensor
    AddConstant(op, 0); // Touch mode
    AddConstant(op, 1); // One value


    AddGlobalVariable(op, 0);


    byte[] data =
    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 4);


    int bits =
    BinaryPrimitives.ReadInt32LittleEndian(data);


    float value =
    BitConverter.Int32BitsToSingle(bits);


    return value > 0.5f;
    }

    public int ReadMotorCount(
    MotorPort port)
    {
    var op = new List<byte>();


    op.Add(0xB3); // opOUTPUT_GET_COUNT


    AddConstant(op, 0);
    AddConstant(op, (int)port);


    AddGlobalVariable(op, 0);


    byte[] data =
    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 4);


    return
    BinaryPrimitives.ReadInt32LittleEndian(data);
    }




    // ------------------------------------------------------------------------
    // Reset the motor encoder count used for positioning.
    // ------------------------------------------------------------------------


    public void ClearMotorCount(
    MotorPort port)
    {
    var op = new List<byte>();


    op.Add(0xB2); // opOUTPUT_CLR_COUNT


    AddConstant(op, 0);
    AddConstant(op, MotorMask(port));


    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 0);
    }


    public void RunMotorPower(
    MotorPort port,
    int powerPercent)
    {
    if (powerPercent is < -100 or > 100)
    throw new ArgumentOutOfRangeException(
    nameof(powerPercent));


    int mask = MotorMask(port);


    var op = new List<byte>();


    op.Add(0xA4); // opOUTPUT_POWER


    AddConstant(op, 0);
    AddConstant(op, mask);
    AddConstant(op, powerPercent);


    op.Add(0xA6); // opOUTPUT_START


    AddConstant(op, 0);
    AddConstant(op, mask);


    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 0);
    }




    public void StopMotor(
    MotorPort port,
    bool brake = true)
    {
    var op = new List<byte>();


    op.Add(0xA3); // opOUTPUT_STOP


    AddConstant(op, 0);
    AddConstant(op, MotorMask(port));
    AddConstant(op, brake ? 1 : 0);


    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 0);
    }


    public void MoveMotorRelative(
    MotorPort port,
    int degrees,
    int speedPercent)
    {
    if (degrees == 0)
    return;


    if (speedPercent is <= 0 or > 100)
    throw new ArgumentOutOfRangeException(
    nameof(speedPercent));


    int direction =
    Math.Sign(degrees);


    int speed =
    direction * speedPercent;


    int steps =
    Math.Abs(degrees);


    int mask =
    MotorMask(port);


    var op = new List<byte>();


    op.Add(0xAE); // opOUTPUT_STEP_SPEED


    AddConstant(op, 0);
    AddConstant(op, mask);
    AddConstant(op, speed);


    AddConstant(op, 0); // Ramp-up steps
    AddConstant(op, steps); // Constant-speed steps
    AddConstant(op, 0); // Ramp-down steps


    AddConstant(op, 1); // Brake at target


    op.Add(0xA6); // opOUTPUT_START


    AddConstant(op, 0);
    AddConstant(op, mask);


    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 0);


    Thread.Sleep(30);


    WaitForMotor(
    port,
    TimeSpan.FromSeconds(5));
    }




    public void MoveMotorTo(
    MotorPort port,
    int targetDegrees,
    int speedPercent)
    {
    int current =
    ReadMotorCount(port);


    int difference =
    targetDegrees - current;


    MoveMotorRelative(
    port,
    difference,
    speedPercent);
    }


    private bool IsMotorBusy(
    MotorPort port)
    {
    var op = new List<byte>();


    op.Add(0xA9); // opOUTPUT_TEST


    AddConstant(op, 0);
    AddConstant(op, MotorMask(port));


    AddGlobalVariable(op, 0);


    byte[] data =
    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 1);


    return data[0] != 0;
    }




    private void WaitForMotor(
    MotorPort port,
    TimeSpan timeout)
    {
    var stopwatch =
    Stopwatch.StartNew();


    while (IsMotorBusy(port))
    {
    if (stopwatch.Elapsed > timeout)
    {
    StopMotor(port);


    throw new TimeoutException(
    $"Motor {port} movement timed out.");
    }


    Thread.Sleep(25);
    }
    }


    public void PlayTone(
    int frequency,
    int durationMilliseconds)
    {
    var op = new List<byte>();


    op.Add(0x94); // opSOUND
    op.Add(0x01); // TONE


    AddConstant(op, 30); // Volume
    AddConstant(op, frequency);
    AddConstant(op, durationMilliseconds);


    ExecuteDirectCommand(
    op,
    globalMemoryBytes: 0);
    }




    private byte[] ExecuteDirectCommand(
    List<byte> operations,
    int globalMemoryBytes)
    {
    if (globalMemoryBytes is < 0 or > 1023)
    {
    throw new ArgumentOutOfRangeException(
    nameof(globalMemoryBytes));
    }


    ushort messageCounter =
    _messageCounter++;


    int memoryHeader =
    globalMemoryBytes;


    int messageLength =
    2 + // Message counter
    1 + // Command type
    2 + // Memory header
    operations.Count;


    byte[] report =
    new byte[_device.GetMaxOutputReportLength()];


    int p = 1; // HID report ID is byte zero.


    report[p++] =
    (byte)(messageLength & 0xFF);


    report[p++] =
    (byte)((messageLength >> Bild   & 0xFF);


    report[p++] =
    (byte)(messageCounter & 0xFF);


    report[p++] =
    (byte)(messageCounter >> Bild   ;


    report[p++] =
    0x00; // Direct Command WITH reply


    report[p++] =
    (byte)(memoryHeader & 0xFF);


    report[p++] =
    (byte)((memoryHeader >> Bild   & 0xFF);


    operations.CopyTo(
    report,
    p);


    _stream.Write(report);


    byte[] reply =
    new byte[_device.GetMaxInputReportLength()];


    int bytesRead =
    _stream.Read(reply);


    if (bytesRead < 6)
    {
    throw new IOException(
    "Incomplete EV3 reply.");
    }


    ushort replyCounter =
    BinaryPrimitives.ReadUInt16LittleEndian(
    reply.AsSpan(3, 2));


    if (replyCounter != messageCounter)
    {
    throw new IOException(
    "EV3 reply message counter mismatch.");
    }


    if (reply[5] != DirectCommandReply)
    {
    throw new IOException(
    $"EV3 returned reply type 0x{reply[5]:X2}.");
    }


    byte[] result =
    new byte[globalMemoryBytes];


    if (globalMemoryBytes > 0)
    {
    Array.Copy(
    reply,
    6,
    result,
    0,
    globalMemoryBytes);
    }


    return result;
    }

    private static void AddConstant(
    List<byte> buffer,
    int value)
    {
    if (value is >= -32 and <= 31)
    {
    buffer.Add(
    (byte)(value & 0x3F));


    return;
    }


    if (value is >= sbyte.MinValue and <= sbyte.MaxValue)
    {
    buffer.Add(0x81); // LC1
    buffer.Add(
    unchecked((byte)(sbyte)value));


    return;
    }


    if (value is >= short.MinValue and <= short.MaxValue)
    {
    buffer.Add(0x82); // LC2


    short v =
    (short)value;


    buffer.Add(
    (byte)(v & 0xFF));


    buffer.Add(
    (byte)((v >> Bild   & 0xFF));


    return;
    }


    buffer.Add(0x83); // LC4


    buffer.Add(
    (byte)(value & 0xFF));


    buffer.Add(
    (byte)((value >> Bild   & 0xFF));


    buffer.Add(
    (byte)((value >> 16) & 0xFF));


    buffer.Add(
    (byte)((value >> 24) & 0xFF));
    }




    private static void AddGlobalVariable(
    List<byte> buffer,
    int byteOffset)
    {
    if (byteOffset is < 0 or > 31)
    {
    throw new ArgumentOutOfRangeException(
    nameof(byteOffset));
    }


    buffer.Add(
    (byte)(0x60 | byteOffset));
    }




    private static int MotorMask(
    MotorPort port)
    {
    return 1 << (int)port;
    }




    public void Dispose()
    {
    _stream.Dispose();
    }
    }




    // ================================================== ==========================
    // Data types
    // ================================================== ==========================


    internal enum MotorPort
    {
    A = 0,
    B = 1,
    C = 2,
    D = 3
    }




    internal enum SortColor
    {
    Red,
    Green,
    Blue,
    Yellow
    }




    internal readonly record struct RgbRaw(
    int R,
    int G,
    int B)
    {
    public int Brightness =>
    R + G + B;
    }




    internal readonly record struct Chromaticity(
    double R,
    double G,
    double B)
    {
    public static Chromaticity FromRaw(
    RgbRaw raw)
    {
    double sum =
    raw.R + raw.G + raw.B;


    if (sum <= 0)
    return new Chromaticity(0, 0, 0);


    return new Chromaticity(
    raw.R / sum,
    raw.G / sum,
    raw.B / sum);
    }




    public double DistanceTo(
    Chromaticity other)
    {
    double dr =
    R - other.R;


    double dg =
    G - other.G;


    double db =
    B - other.B;


    return Math.Sqrt(
    dr * dr +
    dg * dg +
    db * db);
    }
    }




    internal readonly record struct ColorClassification(
    SortColor Color,
    double Distance,
    double Confidence);



    - - - Aktualisiert - - -

    Mit diesem Programm klappt vor allem die Farberkennung sehr gut, da man das Erkennen einer bestimmten Farbe - der größte Schwachpunkt bei diesem Modell - durch Referenzwerte, die man gezielt für den Aufbau und das Umfeld ermitteln kann, steuern kann.

Seite 2 von 2 ErsteErste 12

Ähnliche Themen

  1. embedded system
    Von Unregistriert im Forum Suche bestimmtes Bauteil bzw. Empfehlung
    Antworten: 4
    Letzter Beitrag: 13.12.2015, 09:51
  2. Car-System
    Von sp33dy im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 3
    Letzter Beitrag: 08.04.2010, 19:44
  3. BUS System
    Von HannoHupmann im Forum Elektronik
    Antworten: 11
    Letzter Beitrag: 08.01.2009, 16:02
  4. Mit AVR an das OBD-2 System ?
    Von Natron im Forum Elektronik
    Antworten: 6
    Letzter Beitrag: 09.11.2006, 19:01
  5. Bus-System
    Von x-ryder im Forum Elektronik
    Antworten: 20
    Letzter Beitrag: 26.07.2004, 21:09

Stichworte

Berechtigungen

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

    Werbung      fchao-Sinus-Wechselrichter AliExpress