Arduino-Impulsgeber VB-Ansteuerung

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Banause.

    Arduino-Impulsgeber VB-Ansteuerung


    Ansteuerung

    Guten Tag zusammen,
    ich wollte mir einen Impulsgeber mit 4 Ausgängen bauen die unabhängig von einander geschaltet werden können sollen (also auswählen welche mittels des "An"-Buttons Impulse senden sollen), jedoch die gleiche Frequenz (wobei diese auch mittels VB vorgegeben werden soll) haben sollen. Dabei sieht die Situation wie folgt aus:
    Ich habe einen Arduino Micro (9600 Baud, COM-Schnittstelle) folgendermaßen programmiert.
    Spoiler anzeigen

    C-Quellcode

    1. int i = 0, impOut[4]={0,0,0,0}, stat[4]={0,0,0,0}, sum = 0, stat_length = 0, L3_L4=8, spgFrei = 3, j = 0;
    2. int frequenz = 1, periode = 500, tHigh = 40, tLow = 940, spgZustand = 2, Dosierung = 0, dosCount = 0;
    3. int on = 0;
    4. String incString = "";
    5. void setup() {
    6. stat_length = sizeof(stat)/sizeof(stat[0]); //Länge des Arrays berechnen
    7. Serial.begin(9600); //Serielle Verbindung mit 9600 bps
    8. for(i = 0; i < stat_length; i++){ //Initialisieren der Ausgänge für die Impulse
    9. pinMode(i+4, OUTPUT);
    10. impOut[i]=i+4;
    11. }
    12. pinMode(L3_L4, OUTPUT); //Initialisieren der 3Leiter 4Leiter Umschaltung
    13. pinMode(spgFrei, OUTPUT); //Initialisieren der Spannungsfreischaltung an der Ausgangsklemme 9 und 10
    14. pinMode(spgZustand, OUTPUT); //Initialisieren der Leuchte für Spannungsfreiheit
    15. }
    16. void loop() {
    17. if(Serial.available() > 0) { //Nur bei Veränderung des Eingangssinals abarbeiten
    18. incString = Serial.readString(); //Auslesen des USB's
    19. if(incString == "f") { //einlesen der Frequenz //Länge des Arrays ermitteln
    20. Serial.println("Frequenz eingeben"); //Kann als Abfrage dienen ob der Microcontroller bereit zur Eingabe ist
    21. while(Serial.available() == 0) {} //Dauerschleife bis die gewuenschte Frequenz eingegeben ist
    22. frequenz = Serial.readString().toInt(); //einlsesn der Frequenz (MAXIMAL 25 Hz) und umwandlen aus String in Integer
    23. if(frequenz <= 25) {
    24. periode = 1000 / frequenz; //Berechnen der Low/High Zeit
    25. tLow = periode - tHigh;
    26. Serial.println("fAcc"); //Bestätigung der Frequenzübernahme
    27. }
    28. else {
    29. Serial.println("fOF");
    30. tLow = 0;
    31. tHigh = 40;
    32. }
    33. }
    34. if(incString == "spgRot") { //Umschalten auf Rot der Spannungsleuchte
    35. digitalWrite(spgZustand, HIGH);
    36. Serial.println("uON");
    37. }
    38. else if(incString == "spgGruen") { //Umschalten auf Gruen der Spannungsleuchte
    39. digitalWrite(spgZustand, LOW);
    40. Serial.println("uOFF");
    41. }
    42. if(incString == "off") { //Ausschalten der LEDs auf einmal
    43. for(i=0; i< stat_length; i++) { //Mit jedem Durchgang wird eine LED deaktiviert
    44. digitalWrite(impOut[i], LOW);
    45. stat[i] = 0;
    46. }
    47. Serial.println("impOFF"); //Statusausgabe
    48. on = 0;
    49. }
    50. if(incString == "go") {
    51. on = 1;
    52. }
    53. if(incString == "allon") { //Ausschalten der LEDs auf einmal
    54. for(i=0; i< stat_length; i++) { //Mit jedem Durchgang wird eine LED aktiviert
    55. stat[i] = 1;
    56. }
    57. Serial.println("allON");
    58. }
    59. for(i=0;i<stat_length;i++) {
    60. if(incString == "p"+String(i+1)) { //Vergleichen des eingebenen Strings mit einem String zusammen mit einem Variablen Integer
    61. stat[i] = 1;
    62. Serial.print("P"); Serial.print(i+1); Serial.println("ON"); //Kaskadierung der Ausgabe, da Konstante Strings nicht mit variablen Integern ausgegeben werden können
    63. }
    64. else if(incString == "p"+String(i+1)+"o") { //Deaktivieren der Impulse
    65. stat[i] = 0;
    66. Serial.print("P"); Serial.print(i+1); Serial.println("OFF"); //Kaskadierung der Ausgabe, da Konstante Strings nicht mit variablen Integern ausgegeben werden können
    67. }
    68. }
    69. if(incString == "3L") { //Umschalten af 3 Leiter
    70. digitalWrite(L3_L4, HIGH);
    71. Serial.println("3LON");
    72. }
    73. else if(incString == "4L") { //Umschalten auf 4 Leiter (Standardmäßig)
    74. digitalWrite(L3_L4, LOW);
    75. Serial.println("4LON");
    76. }
    77. if(incString == "LEDzu") { //Zuschalten der LED an der Ausgangsklemme 9 und 10
    78. digitalWrite(spgFrei, HIGH);
    79. Serial.println("LEDcircuit");
    80. }
    81. else if(incString == "LEDweg") { //Wegschalten der LED an der Ausgangsklemme 9 und 10
    82. digitalWrite(spgFrei, LOW);
    83. Serial.println("LEDsave");
    84. }
    85. sum = 0;
    86. for(i=0;i<stat_length;i++) { //Addieren der einzelnen Einträge, wenn >0 herauskommt, dann muss mindestens 1 Ausgang Impulse ausgeben
    87. sum=sum+stat[i];
    88. }
    89. if(incString == "dosON") {
    90. sum = 0;
    91. Dosierung = 1;
    92. Serial.println("DosCount");
    93. while(Serial.available() == 0) {} //Dauerschleife bis die gewuenschte Frequenz eingegeben ist
    94. dosCount = Serial.readString().toInt();
    95. Serial.println("Dosierung uebernommen");
    96. }
    97. }
    98. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    99. if(sum > 0 && Dosierung == 0 && on == 1) { //Um den Delay zu umgehen wird durch if ermittelt ob überhaupt ein Impuls aktiviert werden muss => Zeit sparen
    100. for(i=0; i<stat_length;i++) { //Setzen des jeweiligen Impulses durch if Abfrage mit dem jeweiligen "stat" (Status)
    101. if(stat[i] == 1) { //Einschalten der jeweilgen Impulses
    102. digitalWrite(impOut[i], HIGH);
    103. }
    104. else {
    105. digitalWrite(impOut[i], LOW);
    106. }
    107. }
    108. delay(tHigh); //Verzögerung um standardmäßig 40ms
    109. for(i=0; i<stat_length;i++) { //Ausschalten des Impulses nach der Verzögerung
    110. if(stat[i] == 1) {
    111. digitalWrite(impOut[i], LOW);
    112. }
    113. }
    114. delay(tLow); //Verzögerung um periode-tHigh
    115. }
    116. /**************************************************************************************************************************************/
    117. if(sum > 0 && Dosierung == 1 && on == 1) { //Um den Delay zu umgehen wird durch if ermittelt ob überhaupt ein Impuls aktiviert werden muss => Zeit sparen
    118. for(j=dosCount; j>0; j--) {
    119. for(i=0; i<stat_length;i++) { //Setzen der jeweiliges Impulses durch if Abfrage mit dem jeweiligen "stat" (Status)
    120. if(stat[i] == 1) { //Einschalten der jeweilges Impulses
    121. digitalWrite(impOut[i], HIGH);
    122. }
    123. else {
    124. digitalWrite(impOut[i], LOW);
    125. }
    126. }
    127. delay(tHigh); //Verzögerung um standardmäßig 40ms
    128. for(i=0; i<stat_length;i++) { //Ausschalten des Impulses nach der Verzögerung
    129. if(stat[i] == 1) {
    130. digitalWrite(impOut[i], LOW);
    131. }
    132. }
    133. delay(tLow); //Verzögerung um periode-tHigh
    134. }
    135. if(j == 0) {
    136. Dosierung = 0;
    137. sum = 0;
    138. on = 0;
    139. }
    140. }
    141. }


    Es geht mir hauptsächlich um die Impulsausgänge die ich generieren möchte, welche mittels eines Programms das mit VB geschrieben ist, gesteuert werden sollen und die Frequenz variabel ist. Meine Vorstellung war es, dass ich je nach dem was betätigt wird Strings gesendet werden um den Arduino zu steuern.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.IO.Ports
    3. Public Class Form1
    4. Private WithEvents SerialPort1 As New System.IO.Ports.SerialPort("COM5")
    5. Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
    6. SerialPort1.Open()
    7. SerialPort1.Write("p1")
    8. End Sub
    9. Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
    10. SerialPort1.Open()
    11. SerialPort1.Write("p2")
    12. End Sub
    13. Private Sub CheckBox3_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox3.CheckedChanged
    14. SerialPort1.Open()
    15. SerialPort1.Write("p3")
    16. End Sub
    17. Private Sub CheckBox4_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox4.CheckedChanged
    18. SerialPort1.Open()
    19. SerialPort1.Write("p4")
    20. End Sub
    21. Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
    22. End Sub
    23. Private Sub TextBox2_TextChanged(sender As Object, e As EventArgs) Handles TextBox2.TextChanged
    24. End Sub
    25. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    26. SerialPort1.Write("go")
    27. SerialPort1.Close()
    28. End Sub
    29. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    30. SerialPort1.Write("off")
    31. SerialPort1.Close()
    32. CheckBox1.CheckState = 0
    33. CheckBox2.CheckState = 0
    34. CheckBox3.CheckState = 0
    35. CheckBox4.CheckState = 0
    36. End Sub
    37. End Class


    Mein Problem ist es nun, das jedes mal eine Fehlermeldung auftaucht wenn der SerialPort1 zum zweiten mal geöffnet wird und ich nicht weis wie ich dies umgehen kann. Außerdem weis ich nicht wie ich die Frequenz bzw. eine Dosierungsvorgabe (Anzahl der Impulse bevor diese von alleine aufhören).

    Falls mehr Infos benötigt werden, so einfach danach fragen :)
    Zum einem, prüfst du den, ob der Comport geöffnet ist, bevor du drauf zu greifst?
    Das kannst du mit If SerialPort1.IsOpen() then... prüfen...

    Was die Impulse angeht, vielleicht wäre es hilfreich, eine bestimmte Anzahl von impulsen mit geben, wenn du eine frequenz auswählst. somit würde der mcontroller die anzahl durchspielen und wieder in einen zustand zurück fallen...

    Insgesammt würde ich dir sehr empfehlen bei mcontrollern mit zuständen zu arbeiten. irgend wie hast du was änliches drin, aber irgend wie strings als zustände... aber das ist geschmacksache...
    Willkommen im Forum. :thumbup:

    Banause schrieb:

    der SerialPort1
    wird bei Programmstart geöffnet und bei Programmbeendigung wieder geschlossen.
    Oder gibt es da ein zweites Programm auf dem Rechner, das alternierend auf dieses Port zugreift?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vielen dank für eure Antworten, die Impulse tun ihren Job.
    Jedoch ist es problematisch wenn man zu schnell die Checkboxen anklickt (ich schätze das die Strings zu schnell hintereinander gesendet werden).
    Wie kann ich das beheben?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    3. SerialPort1.Open()
    4. End Sub
    5. Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
    6. If SerialPort1.IsOpen = True Then
    7. SerialPort1.Write("p1")
    8. End If
    9. End Sub
    10. Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
    11. If SerialPort1.IsOpen = True Then
    12. SerialPort1.Write("p2")
    13. End If
    14. End Sub
    15. Private Sub CheckBox3_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox3.CheckedChanged
    16. If SerialPort1.IsOpen = True Then
    17. SerialPort1.Write("p3")
    18. End If
    19. End Sub
    20. Private Sub CheckBox4_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox4.CheckedChanged
    21. If SerialPort1.IsOpen = True Then
    22. SerialPort1.Write("p4")
    23. End If
    24. End Sub
    25. Private Sub An_Click(sender As Object, e As EventArgs) Handles An.Click
    26. If SerialPort1.IsOpen = True Then
    27. SerialPort1.Write("go")
    28. End If
    29. End Sub
    30. Private Sub Aus_Click(sender As Object, e As EventArgs) Handles Aus.Click
    31. If SerialPort1.IsOpen = True Then
    32. SerialPort1.Write("off")
    33. CheckBox1.CheckState = 0
    34. CheckBox2.CheckState = 0
    35. CheckBox3.CheckState = 0
    36. CheckBox4.CheckState = 0
    37. End If
    38. End Sub
    39. End Class


    Außerdem stellt sich mir die Frage mit der Vorgabe der Frequenz. Laut meines Quellcodes in C vom Arduino war es gedacht das ein "f" als String an den Arduino gesendet wird, damit dieser bereit ist die Frequenz als Integer einzulesen. Nun, kann man irgendwie es schaffen das, wenn ein Wert in der Textbox steht und bei Betätigung der "Return"-Taste ein "f" gesendet wird und anschließend der Wert der in der Textbox steht? (jedoch wahrscheinlich mit dem selben Fehler behaftet wie mit den Checkboxen, wenn diese zu schnell angeklickt werden)
    Was genau passiert,

    Banause schrieb:

    wenn man zu schnell die Checkboxen anklickt
    :?:
    Was genau meinst Du mit "f" als String an den Arduino gesendet wird?
    Wie sieht die Syntax dieses Befehls aus? So was?

    VB.NET-Quellcode

    1. SerialPort1.WriteLine("f1000")
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Wie sieht die Syntax dieses Befehls aus?


    Anhand des Auszuges aus dem Quellcode von oben kann man es vielleicht besser verstehen.

    Spoiler anzeigen

    Auszug:

    C-Quellcode

    1. incString = Serial.readString(); //Auslesen des USB's
    2. if(incString == "f") { //einlesen der Frequenz
    3. Serial.println("Frequenz eingeben");
    4. while(Serial.available() == 0) {} //Dauerschleife bis die gewuenschte Frequenz eingegeben ist
    5. frequenz = Serial.readString().toInt(); //einlesen der Frequenz (MAXIMAL 25 Hz)
    6. if(frequenz <= 25) {
    7. periode = 1000 / frequenz; //Berechnen der Low/High Zeit
    8. tLow = periode - tHigh;
    9. Serial.println("fAcc"); //Bestätigung der Frequenzübernahme
    10. }
    11. else {
    12. Serial.println("fOF");
    13. tLow = 0;
    14. tHigh = 40;
    15. }
    16. }

    Wird im Grundzustand des Arduino's ein String über die COM-Schnittstelle, so wird dieser an den if(incString=.........) {.........} verglichen und dem entsprechend reagiert.
    Durch das Senden eines f gerät der Arduino in eine Dauerschleife bis eine neue Eingabe via COM rein kommt. Diese weitere Information ist dann die gewünschte Frequenz für den Impulsgeber.

    EDIT:
    Danke für de Idee mit dem VB.NET-Quellcode @RodFromGermany!
    Ich habe mein C-Quellcode so angepasst, dass auf ein f als erstes Stringzeichen gescannt wird und anschließend die Zahl dahinter (welche noch als String deklariert ist) in ein Integer umgewandelt wird und als Ausschnitt weiter verarbeitet wird. So sollte der Aufwand in VB deutlich leichter sein. Mein jetziges Problem ist nun wie es machbar ist beim zu schnellen anklicken der Checkboxen nicht alles erfasst wird.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Banause“ ()