LED mit Visual Basic dimmen

Hallo,

ich hab mal vor kurzem im internet einen Code für VB und arduino gefunden, der ermöglicht, dass man über die serielle schnittstelle LEDs mit dem Arduino verbunden steuern kann. Das hat auch so soweit funktioniert. Nun will ich eine LED an einen pwm pin anschließen und diese über VB mit hilfe einer TrackBar (“Schieberegler”) dimmen. Leider bekomme ich dies nicht hin und hoffe mir könnte da einer weiterhelfen !

Hier der Code für Visual Basic :

Imports System.IO.Ports.SerialPort

Public Class Form1
    Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.EventArgs)
        If SerialPort1.IsOpen Then
            SerialPort1.Write(ChrW(100))

        End If
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'Verfügbare Comports suchen
        Dim ports As String() = GetPortNames()
        Dim Port As String

        'ComboBox richtig sortieren 
        ComboBox_Comport.Items.Clear()

        If ports.Length > 0 Then

            'für alle Com-NR. < 10 ein Leerzeichen einfügen
            For ii As Integer = 0 To (ports.Length - 1)
                If CInt(ports(ii).Substring(3)) < 10 Then
                    ports(ii) = "COM" & ports(ii).Substring(3)

                End If
            Next

            Array.Sort(ports)

            ' das Leerzeichen in "COM x" wieder entfernen
            For ii As Integer = 0 To (ports.Length - 1)
                ports(ii) = "COM" & ports(ii).Substring(3).Trim


            Next
        End If

        'In die Combobox übernehmen 
        For Each Port In ports
            ComboBox_Comport.Items.Add(Port)

        Next Port

        'Buttons setzen 
        Button_Disconnect.Enabled = False
        Button_Connect.Enabled = False




    End Sub

    Private Sub ComboBox_Comport_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox_Comport.SelectedIndexChanged

        'Comport auswählen 
        If ComboBox_Comport.SelectedItem <> "" Then
            Button_Connect.Enabled = True
        End If



    End Sub


    Private Sub Button_Connect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Connect.Click

        'Comport verbinden 
        Try

            'Buttons freigeben-/ sperren
            Button_Connect.Enabled = False
            Button_Disconnect.Enabled = True
            ComboBox_Comport.Enabled = False

            'Comport Einstellungen 
            SerialPort1.PortName = ComboBox_Comport.Text
            SerialPort1.BaudRate = 9600
            SerialPort1.Open()

            Timer1.Enabled = True



        Catch ex As Exception

            'Fehlermeldung
            MessageBox.Show("Achtung die Schnittstelle konnte nicht geöffnet werden!" + e.ToString, "Ausnahmefehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Button_Connect.Enabled = True
            Button_Disconnect.Enabled = False
            ComboBox_Comport.Enabled = True

        End Try




    End Sub

    Private Sub Button_Disconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Disconnect.Click

        'Verbindung trennen 
        SerialPort1.Write(ChrW(100))
        Timer1.Enabled = False
        Button_Connect.Enabled = True
        Button_Disconnect.Enabled = False
        ComboBox_Comport.Enabled = True
        SerialPort1.Close()
    End Sub

    Private Sub GroupBox1_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBox1.Enter

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click    <----Button der die LED anschaltet 
        If SerialPort1.IsOpen Then
            SerialPort1.Write(ChrW(10))     
        End If
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click    <----Button der die LED ausschaltet
        If SerialPort1.IsOpen Then
            SerialPort1.Write(ChrW(11))
        End If
    End Sub

Und hier der code für arduino:

int led1 = 10;
int SerialData = 0;

void setup()

{
  Serial.begin(9600);
  pinMode(led1, OUTPUT);
 
}

void loop()
{
  SerialData = Serial.read();
  
  switch(SerialData)
  {
    case 10:
    digitalWrite(led1, HIGH);
    break;
    
    case 11:
    digitalWrite(led1, LOW);
    break;
    
   
    
    }
}

Und du willst jetzt eine fertige Lösung von uns? Keine Chance - so lernst du nix.

Mein ansatz wäre: Bau einen Schieberegler ein, stell das minimum auf null, das maximum auf 255. Vergib einen OnValueChange-Event, bei dem du die serielle Schnittstelle öffnest, den Wert als Byte überträgst und anschließend wieder schließt. Wenn du magst, bastel noch eine Abfrage rein, ob der Event abgeschlossen ist, damit du solange der Event ausgeführt wird keine Fehlermeldungen bekommst.

Den übertragenen Wert schreibst du anschließend im Arduino-Sketch mit analogWrite auf einen der PWM-Pins.

Danke für deine antwort !

Irgendwie denken alle ich will immer sofort eine fertige lösung , ich weis nciht wieso ?! :smiley:
Das war mit schon klar, man will ja auch schliesslich nicht immer alles kopieren und so…

Also deinen lösungsansatz probier ich mal aus…hört sich gut. Mal schauen obs klappt !
Meld mich dann nochmal

Mir ist gerade noch etwas eingefallen: statt im OnChange-Event den Connect/Disconnect durchzuführen währe es schlauer bei OnClick zu connecten und bei OnRelease zu disconnecten

[quote author=Marcus W link=topic=115241.msg867443#msg867443 date=1342881791] Mir ist gerade noch etwas eingefallen: statt im OnChange-Event den Connect/Disconnect durchzuführen währe es schlauer bei OnClick zu connecten und bei OnRelease zu disconnecten [/quote]

Das finde ich unlogisch. Wenn der User zwar auf den Regler klickt, aber gar keinen neuen Wert einstellt, hast du ne Aktion am ser. Port laufen, die unnötig ist. Immer nur öffnen/schließen, wenn sicher ist, dass was übertragen werden muss!

Unlogisch ist zu klicken, ohne einen Wert einzustellen - vorallem ein klick ist dann ja eben nur ein connect/disconnect, ohne dass der Arduino irgentetwas machen muss.

Ein Connect/Disconnect zu machen, bei jedem OnChange Event ist overkill. Das würde ja dann ständig beim Verschieben des Reglers passieren.

  • Connect wenn OnClick
  • Permanantens Übertragen der Bytes solange, wie der Regler verschoben wird (OnChange)
  • Disconnect wenn OnRelease.

Meine Rede XD

hi, hat jetzt leider etwas länger gedauert. also ich habe eine code geschrieben nur der funktioniert noch nicht ganz. Also wenn ich den auf das arduino lade und dann bei vb die trackbar hin und her bewege, dann kommt auch was bei dem board an (rx led leuchtet auf), egal wo die trackbar sich befindet(auf der scala 0-255) Aber aus irgendeinem grund geht die led nur bei einer bestimmten stelle der trackbar an ?! woran könnte das liegen ?

Hier der Code für arduino:

int led1 = 10;
int SerialData = 0;

void setup(){
  Serial.begin(9600);
  pinMode(led1, OUTPUT);
  
}

void loop(){
  byte brightness;
  
  SerialData = Serial.read();
  
  switch(SerialData)
  {
  analogWrite(led1, brightness);
  
}

}

und hier der für VB: (habe jetzt den oberen teil weggelassen, ist immer das gleiche)

 Private Sub TrackBar1_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
        If SerialPort1.IsOpen Then
            Dim brightness As Byte
            brightness = TrackBar1.Value

            SerialPort1.Write(Chr(brightness))
        End If
    End Sub

gruß lorenz

Wo setzt du "brightness"? Und was machst du mit der "SerialData"? Das kann so nicht funktionieren...

Nene, das Problem liegt daran, dass der COM-Controller weitere Eingaben erwartet. Du musst quasi dein "Kommando" abschließen. Entweder mit einem Linefeed oder einem Carriage-Return. Das übernimmt dir die Serial Klasse aber, wenn du ganz einfach statt

Serial.Write()

ein

Serial.WriteLine()

schreibst :)

Vielen dank für dein Antwort ! Du meinst doch, ich soll statt serialport1.write(chr(brightness)) Serialport1.writeline(chr(brightness))

Oder hab ich das jetzt Falsch verstanden. Weil es funktioniert noch nicht.

Ich würde auch den Arduino-Code anpassen. Serial.read() liefert den Wert "-1", wenn keine Daten vorhanden sind. Das schreibst Du dann direkt per analgoWrite() auf dein PWM-Pin. Dahe hast Du vermutlich 99% der Zeit keine richtigen Werte. Dazu kommt, das der Code "switch(SerialData)" keinen Sinn macht, ohne Case-Blöcke. Erstaunlich das der Compiler das schluckt. Weiterhin verwendest Du den Wert "brightness" für das PWM-Signal, dieser Variable weisst Du aber nie im Code einen Wert zu, der aus der seriellen Verbindung gelesen wird.

Modifiziere den Code für den Arudino wiefolgt:

int led1 = 10;

void setup(){
  Serial.begin(9600);
  pinMode(led1, OUTPUT);
  
}

void loop(){
  byte brightness;
  
  if(Serial.available() > 0) {

      brightness = Serial.read();
  
      analogWrite(led1, brightness);

  }
}

Zum VB-Code, eine Zeilenumbruch solltest Du nicht senden, denn der wird ja von Deinem Arduino-Code auch wieder als Helligkeitswert gelesen. Einfach in die serielle Verbindung schreiben mit Serialport1.write(chr(brightness)) sollte schon funktionieren.

vielen dank ! es klappt recht gut. ach stimmt ! das mit "brightness" hab ich ja ganz vergessen. -_- maaan bin ich dumm... und wegen diesem switch(serialdata) da hab ich mir gedacht, da ich das in dem anderen code auch brauche, benötige ich das hierbei bestimmt auch. Anscheinend aber nicht. Also ich hab die TrackBar von 0 - 255, nur wenn ich über 125 komme dann fängt der pwm signal wieder von vorne an (?!). ich hab die trackbar einfach dann von 0-125 verändert und dann klappte das auch !

also nochmal vielen herzlichen danke an euch ! ()

Gruß Lorenz

Jetzt hab ich doch noch ein kleines Problem und zwar wollte ich auch noch andere leds normal an/aus schalten. Und jetzt meine Frage: Da ich ja die 255 Byte schon belegt habe, wegen dem Faden, kann ich ja keine anderen leds mehr, mit zB 500, ansteuern ?! Also hab das ausprobiert und das geht leider nicht, gibt es da eine andere Lösung die Bytes irgendwie erhöhen, sodass das arduino die lesen kann ?!

Gruß Lorenz

Ein Byte ist ein Byte, und damit immer 8 Bit groß. Daran wirst Du nichts ändern können :-) Was Du brauchst ist eine Möglichkeit, den Daten die Du sendest eine Struktur zu verleihen. Zur Zeit interpretiert Dein Arduino jedes Byte das kommt als Wert der für das PWM-Signal eines Pins, das musst Du ändern. Du brauchst ein "Protokoll" an das sich Sender (dein PC) und Empfänger (Arduino) halten. Ein einfacher Ansatz könnte z.B. sein, das Du immer zwei Bytes statt nur einem sendest. Das erste Byte gibt an, welches Pin verwendet werden soll und das zweite Byte legt dann fest was mit dem Pin passieren soll. Ein Beispiel für eine Protokoll-Definition:

  • Es wird definiert, das Pin 3,5 und 6 immer als PWM-Pin verwendet werden
  • Es wird definiert, das Pin 4,7,8 als digitaler Ausgang verwendet werden
  • Es wird definiert, das als erstes Byte die Pin-Nr gesendet wird
  • Es wird definiert, das als zweites Byte der zu schaltende Zustand des Pins gesendet wird
  • - Ist das zu verwendende Pin ein digitaler Ausgang, bedeutet 0x00 (also 0) als 2. Byte ausschalten und alles andere einschalten
  • - Ist das zu verwendende Pin ein PWM-Pin bedeutet das 2.Byte den PWM-Wert der zu setzen ist

Damit sind die Spielregeln festgelegt, jetzt musst Du durch Deine Programmierung dafür sorgen, das sich Arduino und PC an diese Regeln halten. Der PC sendet zwei Bytes (z.B. 0x04 0x01) und der Arduino liest 2 Bytes. 0x04 sagt dem Arduino, das Pin Nr 4 verwendet werden soll. 0x01 bedeutet dann, das Pin 4 auf HIGH geschaltet werden soll. Wird z.B. 0x03 0xa0 gesendet, dann wird Pin 3 (PWM) verwendet und der Wert 160 für das PWM-Signal gesetzt ( hex 0xa0 = 160 dezimal).

Mario.

Wow, vielen dank für deine Erklärung. Also ich hab jetzt verstanden dass man immer 2bytes sendet/ausliest die dann sagen, welcher Pin gemeint ist und ob der auf HIGH oder LOW gesetzt werden soll. Nur weiß ich nicht wirklich wie ich das mit dem arduino realisieren kann ?! Da bräuchte ch vielleicht nochmal einen beispiel sketch oder so. Weil zB mit diesen (hex 0xa0 = 160 dezimal) kann ich irgendwie rein gar nichts anfangen.

Gruß Lorenz

Die Bezeichnung 0xa0 ist eine übliche Darstellung von hexadezimalen Zahlen. Das praktische ist, das man dann für ein Byte nur 2 Zeichen braucht, wenn man es hexadezimal darstellt. Da bei Hex-Zahlen aber auch "normale" Ziffern verwendet werden, muß man Hexzahlen von Dezimalzahlen unterscheiden können. 20 dezimal ist nämlich was anderes als 20 hex (das wären nämlich 32 dezimal), daher stellt man bei Hexzahlen gern ein "0x" davor. Die 256 verschiedenen Werte die ein Byte annehmen kann wären dann in Hex: 0x00 bis 0xff. Zu Deinem Code: Auf dem Arduino liest Du einfach zwei Bytes statt einem. Das erste gelesene Byte verwendest Du als Pin-Nummer, das zweite gelesene Byte als Wert für entweder digitalWrite() oder analogWrite(). Ich habe mal das switch-Kommando aus Deinem ursprünglichen Code mit eingebaut, da es in diesem Fall durchaus Sinn macht, das einzusetzen. Man kann das aber auch über "if(pin == 1) { ...} else if (pin == 2) { ... }.

void setup() {};

void loop(){
  byte pin;
  byte value;
   //prüfen ob mehr als ein Byte empfangen wurde
  if(Serial.available() > 1) {

      //erstes Byte lesen (Pin-Nummer)
      pin = Serial.read();
      
      //zweites Byte lesen (Wert)
      value = Serial.read();

      //hier macht ein switch - case - Block Sinn
      //anhand der gelesenen Pin-Nummer wird verzweigt
      switch(pin) {
        
        //Pin 3 ist ein PWM Pin
        case 3:
          analogWrite(pin,value);
          break;
          
        //Pin 4 ist ein "digitales"
        case 4:
          digitalWrite(pin,value);
          break;
        default:
          //hier landen alle Fälle die nicht abgefangen wurden
          break;
      }  

  }
}

Nochmals vielen Dank ;) Okay, das ist ja doch nicht so schwer wie befürchtet habe. Und VB was für zahlen würde VB senden ? Kommt dann da dieses mit den hexzahlen rein ?

Gruß Lorenz

Ach ne…wäre so ein Code für VB richtig ?:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click    <----Button der die LED ausschaltet
        If SerialPort1.IsOpen Then
            SerialPort1.Write(ChrW(10)) //das ist für den pon
            SerialPort1.Write(ChrW(120)) //das ist für value
        End If
    End Sub

Ist das so richtig aufgefasst ?

Gruß
Lorenz