Jump to content

c# Anfängerfragen


Doeni

Recommended Posts

Für den Anfang würde ich Lektüre zu C# empfehlen:

http://www.tinkerunity.org/forum/index.php/topic,218.msg970.html#msg970

 

In Kombination mit der ausführlichen Doku und API Beschreibung auf der Website von TF genau studieren insbesondere die Code-Beispiele zum betreff. Bricklet analysieren.

 

Falls weiterhin Unklarheit, anschließend genauere Angaben zum Problem ins Forum stellen, welche Messwerte, welches Bricklet etc.

Link zu diesem Kommentar
Share on other sites

Ich vermute mal du hast bereits einen Code wie:

 

 

ipcon = new IPConnection(host, port);

temp = new BrickletTemperature(t.Uid);

temp.SetTemperatureCallbackPeriod(1000);

temp.RegisterCallback(new BrickletTemperature.Temperature(TempCB));

 

...

 

void TempCB(short val)

{

  labelxyz.text = val.ToString();

}

 

 

Problem ist klar da es Multi-Threaded ist kann man nicht auf das Label zugreifen.

Stichwort ist INVOKE!

      temp.RegisterCallback(new BrickletTemperature.Temperature(TempCB));

      SetValues = new SetPosDel(InvokeSetter);

 

...

 

 

      private delegate void SetPosDel(double val);

      private SetPosDel SetValues;

      void TempCB(short val)

      {

        try

        {

            object[] p = { (val / 100.0) };

            this.Invoke(SetValues, p);

        }

        catch

        {

        }

      }

 

      private void InvokeSetter(double val)

      {

        DateTime now = DateTime.Now;

 

        txt_log.Text = "Temperatur um "

            + now.ToString("yyyy-MM-dd HH:mm:ss:ff")

            +": " + val.ToString("0#.##") + "°C" + Environment.NewLine

            + txt_log.Text;

 

        txt_ExcelLog.Text += now.ToString("HH:mm:ss") + "\t" + val + Environment.NewLine;

      }

 

Link zu diesem Kommentar
Share on other sites

Dann hast du eine static class.

 

Von dieser können mit new keine neuen Instanzen angelegt werden. Das heißt alle Variablen und Methoden der Klasse brauchen auch das static-Schlüsselwort.

 

Ich weiß allerdings nicht ob du wirklich eine statische Klasse haben willst.

Die Lösung ist es entweder überall static dazuzuschreiben (in dieser Klasse) oder eben es vom class zu entfernen. Aus dem Bauch heraus würde ich sagen versuch es nicht-statisch, ist i.d.R. die richtige Lösung auch wenn statisch "erstmal einfacher (und hauptsache es läuft)" aussieht.

 

Poste gerne Code-Ausschnitte und sage was du wissen willst. Wir können nur kurz schreiben warum es nicht geht, aber ich kann mir auch Zeit nehmen und grundsätzliche Hinweise zum Code schreiben. Ist aber einfacher wenn man eine "Diskussionsgrundlage" hat ;)

Link zu diesem Kommentar
Share on other sites

Ah okay, dein eigener Code liegt grundsätzlich an der falschen Stelle (würde ich sagen).

 

Tatsächlich kannst du zunächst die Program-Klasse so lassen wie sie dir von Visual Studio erzeugt wird.

 

Dein eigener Code sollte besser in die Klasse Form1 wandern (rechtsklick auf Form1 im Solution Explorer und dort "View Code"). (Die Klasse Form1 darfst du auch gerne nach MainWindow o.ä. umbenennen, das ist aber nicht soooo wichtig ^^)

 

Grundlegend sollte das so aussehen:

- Instanz-variablen für deine Brick(let)s und die IPConnection

- Im Konstruktor der Form (nach InitializeComponents) die Instanzvariablen initialisieren (ipcon = new ... und ipcon.AddDevice(...))

- Beim Schließen der Form kannst du sowas machen wie ipcon.destroy

 

Woher weißt du wann die Form geschlossen wird?

Dazu im Solution Explorer die Form Doppelklicken, du solltest jetzt eine Vorschau davon sehen, auf properties gehen (Eigenschaften), dort kannst du dir Events anzeigen lassen, eines davon heißt closing. Dieses Event wird gerufen sobald sich die Form schließt. Ein Doppelklick darauf sollte reichen, damit dir automatisch eine Methode erzeugt wird die beim Schließen gerufen wird. Dort kann jetzt dein "aufräum-code" rein.

 

Grundsätzlich solltest du dir vermutlich auch ein bis zwei Einstiegshilfen in WinForms suchen... etwa die hier (sehr kurz):

http://msdn.microsoft.com/en-us/library/360kwx3z(v=vs.90).aspx

Link zu diesem Kommentar
Share on other sites

Mal ein "anderer" Ansatz (durch code sieht und lernt man es am besten):

 

- Code ist verschoben

- und getestet (klappt mit meiner UID // ist bereits auf deine UID geändert.)

- sonst siehe oben.

 

- ich habe mich mal auf den Poti beschränkt.

- auf der Form ist ein label welches dir die Position des Potis anzeigt.

 

Edit: Ich erwarte, dass der Brick bereits angeschlossen ist (keine Fehlerprüfungen oder so) da es nur ein Beispiel ist.

Hilfestellung.zip

Link zu diesem Kommentar
Share on other sites

// ---

lcd = new Tinkerforge.BrickletLCD20x4(UID2);

ipcon.AddDevice(lcd);

lcd.BacklightOn();

// ---

Das Lcd ist nicht in der Connection.

 

Dann im Setter:

lcd.WriteLine(0, 0, "Ausgabe: " + lcdtext + "  " );

 

Die Leerzeichen am Ende sind nötig, damit die Verschiebung der negativen Zahlen ausgeglichen wird.

Link zu diesem Kommentar
Share on other sites

Kannst du mir die einzelnen Codeteile erklären weil ich dasselbe auch für den Abstandssensor machen will.

SetValues = new SetPosDel(InvokeSetter);

poti.RegisterCallback(new BrickletRotaryPoti.Position(PositionCB));
            poti.SetPositionCallbackPeriod(100);

delegate void SetPosDel(double val);
        private SetPosDel SetValues;

..

void PositionCB(short val)
        {
            try
            {
                object[] p = { (val) };
                this.Invoke(SetValues, p);
            }
            catch
            {
            }
        }

...

private void InvokeSetter(double val)
        {}

Link zu diesem Kommentar
Share on other sites

Kannst du mir die einzelnen Codeteile erklären weil ich dasselbe auch für den Abstandssensor machen will.

Gerne.

 

delegate void SetPosDel(double val);
         private SetPosDel SetValues;

Zeile 1 ist die Vereinbarung eines Funktionspointers (delegate) welche vorschreibt, dass eine Methode void zurückliefert und einen Parameter vom Typ double besitzt.

 

Zeile 2 ist dann ein Funktionspointer vom Typ "SetPosDel" mit dem Namen "SetValues". In diese Varibale können wir dann eine Funktion hinterlegen.

 

SetValues = new SetPosDel(InvokeSetter);

Dies passiert dann hier die Methode "InvokeSetter" wird in den Funkionspointer\Delegate "SetValues" gelegt.

 

private void InvokeSetter(double val) { /* Setzt die Daten  */ }

Dass ist die Methode welche unsere Daten im passenden Thread dann ausführt. Innerhalb dieser Methode kann man dann auf die Oberflächenelemente zugreifen.

 

 

poti.RegisterCallback(new BrickletRotaryPoti.Position(PositionCB));
            poti.SetPositionCallbackPeriod(100);

Dies ist TF Gebiet:

Zeile 1 wir legen hier auch einen Delegaten vom Typ "BrickletRotaryPoti.Position" an und geben diesen in das poti Objekt. Damit wird bei einer Positionsänderung oder Timer die Methode "PositionCB" aufgerufen.

 

Mit Zeile 2 legen wir fest, dass alle 100 ms der Callback aufgerufen werden soll.

 

void PositionCB(short val) {  
            try
            {
                object[] p = { (val) };
                this.Invoke(SetValues, p);
            } catch{}
        }

Hier dann als letztes die Callbackfuntion welches die TF Methoden mit dem Oberfläche "verbinden".

Der Try Catch Block soll Fehler abfangen, da mir im Beispiel Fehler beim Invoken egal sind ist er leer *grins*

 

"this" ist in diesen Fall eine Referenz auf die Oberfläche\Form. Jede Oberfläche hat einen eigenen Thread zum Darstellen der Elemente. Die TF Methoden laufen aber in anderen Threads um die Oberfläche nicht zu blockieren.

 

Um von einen Thread in einen Anderen auf Elemente zugreifen zu können ist die Invoke-Methode nötig. Diese führt dann fir übergebene Methode in dem anderen Thread aus. Parameter 1 ist "SetValues" unser Funktionspointer auf die "InvokeSetter" Methode und der zweite Parameter sind die Parameter der "InvokeSetter" Methode. Übergeben als "object" Array.

 

Also wird beim Invoke die Methode InvokeSetter mit dem "val" als Parameter aufgerufen. Im Grunde wäre es die Zeile:

InvokeSetter(val);

Welche Aufgrund der verschiedenen Threads Fehler werfen würde.

 

 

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...