NETMF

KinderChocolateBot

Zu Weihnachten habe ich mir bisl Zeit genommen und wollte etwas mit Servo und NETMF machen. Brauche immer ein Projekt welches auch Sinn macht… Naja ob das Resultat sinnig ist, darf jeder selber Entscheiden.

Eigentlich sollte ich das Projekt unter Homeautomation einstellen, da es mir jeden Tag Zeit spart. Denn wir lieben Kinderschokolade :^)

Bevor ich aber jedes Mal alles rauskrame, dachte ich mir wäre doch ein Roboter, welcher mir die Arbeit abnimmt, sinnvoll.

Lego

Gesagt getan, endlich wieder mit Legos etwas bauen, passt irgendwie zu Weihnachten.

Bau 1 Bau 2

Bau Vorne Bau Hinten

Bau 3 Schalter

 

Rückansicht Seitlich Links

Seitlich Rechts Vorne

Folgende Komponenten wurden verbaut:

Gesamtkosten ca. 56€ was nicht gerade billig ist. Achja, Lego hatte ich schon, sonst wären es wahrscheinlich locker über 100€.

Das programmieren des Servos ist nicht ganz so einfach mit NETMF aufgrund fehlender Libraries für die Taktzeiten… hab mir bisl was zusammengesucht, denke aber ist nicht das beste Setup, da hier viel manuell gerechnet wurde (Clocktime). Da ist wohl ein nicht NETMF Controller besser.

Aber es funktioniert wie es sollte und schaut auch gut aus :^)

using Gadgeteer;
using Servo_API;
using Button = Gadgeteer.Modules.GHIElectronics.Button;

namespace Program
{
    public partial class Program
    {
        Servo servo; 
        private bool IsRunning;

        void ProgramStarted()
        {
            Debug("Set it UUUUP!");

            // Setup
            Mainboard.SetDebugLED(true);
            button.ButtonPressed += ButtonOnButtonPressed;
        }

        private void ButtonOnButtonPressed(Button sender, Button.ButtonState state)
        {
            if (!IsRunning)
            {
                Debug("Chocolate!");
                
                ledLeft.FadeOnce(Color.Red);
                ledRight.FadeOnce(Color.Red);

                IsRunning = true;

                servo = new Servo(extender);
                servo.Degree = -180;
                servo.Dispose();

                IsRunning = false;

                Debug("Bedtime!");                
            }
        }

        void Debug(string text)
        {
            Microsoft.SPOT.Debug.Print("==> " + text);
        }
    }
}
// Orginal http://stackoverflow.com/questions/22699174/netduino-class-servo-4-3-1

using Gadgeteer;
using Gadgeteer.Modules;
using Microsoft.SPOT.Hardware;
using System;
using System.Threading;

namespace Servo_API
{
    public class Servo : IDisposable
    {
        /// <summary>
        /// PWM handle
        /// </summary>
        private PWM servo;

        /// <summary>
        /// Timings range
        /// </summary>
        private int[] range = new int[2];

        /// <summary>
        /// Set servo inversion
        /// </summary>
        public bool inverted = false;

        /// <summary>
        /// Create the PWM Channel, set it low and configure timings
        /// </summary>
        public Servo(Module module)
        {
            // Init the PWM pin
            // servo = new PWM((Cpu.PWMChannel)channelPin, 20000, 1500, PWM.ScaleFactor.Microseconds, false);
            Socket SocketExtender = Socket.GetSocket(4, true, module, "socketExtender");
            servo = new PWM(SocketExtender.PWM9, 20000, 1500, PWM.ScaleFactor.Microseconds, false);
            servo.Period = 20000;

            // Typical settings
            range[0] = 900;
            range[1] = 2100;
        }

        public void Dispose()
        {
            disengage();
            servo.Dispose();
        }

        /// <summary>
        /// Allow the user to set cutom timings
        /// </summary>
        /// <param name="fullLeft"></param>
        /// <param name="fullRight"></param>
        public void setRange(int fullLeft, int fullRight)
        {
            range[1] = fullLeft;
            range[0] = fullRight;
        }

        /// <summary>
        /// Disengage the servo. 
        /// The servo motor will stop trying to maintain an angle
        /// </summary>
        public void disengage()
        {
            // See what the Netduino team say about this... 
            servo.DutyCycle = 0; //SetDutyCycle(0);
        }

        /// <summary>
        /// Set the servo degree
        /// </summary>
        public double Degree
        {
            set
            {
                // Range checksJa
                if (value > 180)
                    value = 180;

                if (value < 0)
                    value = 0;

                // Are we inverted?
                if (inverted)
                    value = 180 - value;

                // Set the pulse
                //servo.SetPulse(20000, (uint)map((long)value, 0, 180, range[0], range[1]));
                servo.Duration = (uint)map((long)value, 0, 180, range[0], range[1]);
                servo.Start();
                Thread.Sleep(360);
            }
        }


        private long map(long x, long in_min, long in_max, long out_min, long out_max)
        {
            return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
        }
    }
}
Von |2018-05-14T15:23:21+02:002015-03-10|Gadgeteer, NETMF, Projekte|

FEZ Game-O

Hab hier schon lange nichts mehr über den Gadgeteer gepostet… Mir fehlte einfach die Zeit, bzw. ist immer noch so. Ich habe einige Projekte im Kopf und hoffe Sie bald umsetzen zu können.

Wollte euch nur kurz das Kickstarter-Projekt FEZ Game-O vorstellen. Finde es einfach nur klasse. Denke gerade für Kinder/Jugendliche ist es eine tolle Sache hier in die Programmierung bzw. Hardware einzusteigen.

1

Werde mir vorerst zwar noch keinen kaufen, da ich ja noch einiges hier habe, was noch programmiert werden will.

Das Projekt hat ihr Ziel schon erreicht, aber ihr könnt es noch unterstützen. Später wird die Hardware von GHI vertrieben.

42b1b15879d49924fa8557ee616c0c9b_large

Von |2018-05-14T15:22:53+02:002013-08-01|Gadgeteer, NETMF|

SimpleOledDisplay

Da ich mit der Standard Klasse des OLED Display modules nicht so glücklich bin, hab ich einen eigenen Treiber geschrieben.

Folgende Funktionen sind verfügbar:

  • Zeilen schreiben
  • Farbe definieren
Bis jetzt ist nur der SmallFont verfügbar.
Beispiel:
//Setup
SimpleOledDisplay.Display = oledDisplay;
Thread.Sleep(3000);
SimpleOledDisplay.Clear();

// WriteLine
SimpleOledDisplay.Writeline(SimpleOledDisplay.Linenumber.Three, "Hello World", GT.Color.Yellow);
SimpleOledDisplay.Writeline(SimpleOledDisplay.Linenumber.Five, "... and Gadgeteer!", GT.Color.Red);
Thread.Sleep(3000);
SimpleOledDisplay.Clear();

// Write more than one line
SimpleOledDisplay.DefaultTextColor = GT.Color.LightGray;
for (int i = 0; i < SimpleOledDisplay.Lines.Length; i++) {     SimpleOledDisplay.Lines[i] = "Write text in line ==> " + (i + 1);
}
SimpleOledDisplay.WriteAllLines();
Thread.Sleep(3000);
SimpleOledDisplay.Clear();

// Color fade
GT.Color myColor;
for (int i = 0; i < 255; i++)
{
    myColor = GT.Color.FromRGB((byte) i, 0, 0);
    SimpleOledDisplay.Writeline(SimpleOledDisplay.Linenumber.Three, "Hello World", myColor);
}
for (int i = 0; i < 255; i++)
{
    myColor = GT.Color.FromRGB(255, (byte) i, 0);
    SimpleOledDisplay.Writeline(SimpleOledDisplay.Linenumber.Three, "Hello World", myColor);
}
for (int i = 0; i < 255; i++)
{
    myColor = GT.Color.FromRGB(255, 255, (byte) i);
    SimpleOledDisplay.Writeline(SimpleOledDisplay.Linenumber.Three, "Hello World", myColor);
}
Von |2012-11-11T16:44:08+01:002012-11-11|Gadgeteer, NETMF|

OLED Display Module debug window

Als sehr praktisch erwies sich die fertige Klasse von RorschachUK aus dem TinyCLR-Forum.

Man kann das Display Modul als Debug Output verwenden. Somit hat man eine schöne Ausgabe direkt bei seinen Modulen.

Quelle: TinyCLR

Die Klasse ist mit der Low-Memory-Methode FlushRawBitmap erstellt und läuft somit auch auf dem FEZ Cerberus.

Ich hab mal ein Video erstellt um es euch zu zeigen.

 

 

Und so wird die Klasse verwendet:

DebugWindow.display = oledDisplay;         // init display
DebugWindow.EchoToDebug = true;            // show in VS output window
for (int i = 0; i < 100; i++)
{
    DebugWindow.Print("Hello value " + i); // print on display
    Thread.Sleep(50);
}
Von |2017-07-25T09:50:11+02:002012-11-08|Gadgeteer, NETMF|

OLED Display Module

Ich hab mir mal das OLED Display Module von Seedstudio geleistet. Der Preis ist mit 30$ ganz OK. Das größere und touchemfindliche Display TE35 war mir für 75$ zu teuer.

Da ich ein FEZ Cerberus Mainboard besitze stehe ich vor einen kleinen Problem. Kleiner Speicher…

Das Module besitzt (komfort) Methoden zum Darstellen von Text:

oledDisplay.SimpleGraphics.DisplayText("Hello World!",
Resources.GetFont(Resources.FontResources.small), GT.Color.Red, 10, 10);

Diese Methode erstellt dummerweise eine Bilddatei (BMP) mit 128×128 Pixeln und stellt es da. Dies ist die Größe des gesamten Bildschirmmoduls.

 

Es gibt eine weitere Möglichkeit Bereiche des Bildschirms zu beschreiben. Dazu nutzen wir die Methode FlushRawBitmap, welche mit virtuellem RAM arbeitet und somit Speicher spart.

 

Beispiel Text:

byte[] vramText = new byte[128 * 20 * 2];
Bitmap bitmapText = new Bitmap(128, 20);
bitmapText.DrawText("Suplanus", Resources.GetFont(Resources.FontResources.small), GT.Color.Yellow, 0, 0);
Util.BitmapConvertBPP(bitmapText.GetBitmap(), vramText, Util.BPP_Type.BPP16_BGR_BE);
oledDisplay.FlushRawBitmap(0, 0, 128, 20, vramText);

Beispiel Bild:

byte[] vramImage32 = new byte[32 * 32 * 2];
Util.BitmapConvertBPP(Resources.GetBitmap(Resources.BitmapResources.star32).GetBitmap(), vramImage32, Util.BPP_Type.BPP16_BGR_BE);
oledDisplay.FlushRawBitmap(48, 40, 32, 32, vramImage32);

Um Bilder zu laden müssen diese zuvor in Resources.resx eingefügt werden.

Von |2018-05-14T15:22:45+02:002012-11-03|Gadgeteer, NETMF|