Lichtschranke Fader Aktion nur einmal ausführen?

Hallo zusammen,

ich bin absoluter Neuling auf dem Gebiet der C++ Programmierung und den kleinen Mikro -Controllern. Einfachste Dinge wie einen Taster auf eine Tastaturausgabe zu bringen oder einer Tastenkombination hab ich schon hin bekommen, jedoch stehe ich gerade echt auf dem Schlauch.

Vorhaben:

Ich besitze ein Audiointerface Yamaha AG03 das für das Mikrofon ein Fader besitzt. Nun möchte ich mittels Gabellichtschranke eine Tastatur-Tastenkombination zum PC schicken, sobald ich das Mikrofon öffne (also den Fader nach oben ziehe) um in einem Programm namens mAirList (Radioautomation) den Mikrofoneingang ein zu schalten. Genauso soll eine andere Tastenkombination gesendet werden, sobald der Fader wieder ganz nach unten gezogen ist, also sich in der Gabellichtschranke befindet. OnTop soll noch eine zusätzliche LED den IST-Zustand anzeigen was aber kein Problem dar stellt. (Fader offen = LED an, Fader geschlossen = LED aus)

Mein Problem:

Bis jetzt hab ich es hinbekommen das jeder Zustand, also egal ob Lichtschranke frei oder belegt ist, die entsprechende Tastenkombination zum PC gesendet wird, jedoch natürlich permanent.

Setup:
MikroController: Digispark Attiny85
Verwendete Gabellichtschranke

LED angeschlossen an PIN 1
Digital Read der Gabellichtschranke an PIN 2 ( HIGH, LOW)

Code den ich nicht selbst erstellt habe, sondern nur für meine Bedürfnisse angepasst hab, also PIN belegung etc.

#include "DigiKeyboard.h"

const int buttonPin = 2;
const int ledPin =  1;
int buttonState = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  DigiKeyboard.update();
}

void loop() {
  DigiKeyboard.sendKeyStroke(0);
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
    digitalWrite(ledPin, HIGH);
    DigiKeyboard.sendKeyPress(KEY_F8, MOD_CONTROL_LEFT);
    DigiKeyboard.delay(100);

  } else {
    digitalWrite(ledPin, LOW);
    DigiKeyboard.sendKeyPress(KEY_F7, MOD_CONTROL_LEFT);
    DigiKeyboard.delay(100);
  }
}

Quizfrage:
Wie bekomme ich es hin, das der Controller nur einmal eine Tastenkombination sendet wenn sich der Zustand verändert hat und nicht Permanent? boolean?

Vielen dank und ich hoffe das ich hier richtig bin auch wenn es kein Arduino Produkt ist??

  1. Wenn alter Tastenzustand HIGH und aktueller Tastenzustand LOW, dann sende Tastencode.
  2. alter Tastenzustand = aktueller Tastenzustand

Siehe IDE-Beispiel StateChangeDetection.

wenn du dein Signal hast, setzt du zusätzlich ein Block-Flag.
Wenn die Lichtschranke wieder retour geht, löscht du das Block-Flag.

ungetestet:

#include "DigiKeyboard.h"

const int buttonPin = 2;
const int ledPin =  1;
int buttonState = 0;
bool ready = true;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  DigiKeyboard.update();
}

void loop() {
  DigiKeyboard.sendKeyStroke(0);
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH  && ready == true) {
    digitalWrite(ledPin, HIGH);
    DigiKeyboard.sendKeyPress(KEY_F8, MOD_CONTROL_LEFT);  // annahme das ist das "Aktivieren"
    DigiKeyboard.delay(100);
    ready = false;                                        // blockieren
  } 
  else if (buttonState == LOW)
  {
    ready = true;                              // zurücksetzen
    digitalWrite(ledPin, LOW);
    DigiKeyboard.sendKeyPress(KEY_F7, MOD_CONTROL_LEFT);
    DigiKeyboard.delay(100);
  }
}

Das werde ich mir genauer anschauen. Danke für den Hinweis und vielen Dank schon mal für eure Bemühungen. Ich weis das zu schätzen.

@noiasca danke das du den Code auf deine Weise angepasst hast, leider funktioniert er aber nicht.
Die LED geht an weil die Lichtschranke offen ist, der Status (Offen STRG+F8) wird auch übertragen nach dem Start jedoch ändert sich der Zustand leider nicht wenn ich die Lichtschranke unterbreche. Die Dauerschleife ist allerdings behoben. Das funktioniert also schon mal.
image

Da ich leider von Programmierung noch sehr wenig verstehe, weis ich auch nicht wo ich ansetzen sollte. Könnte es daran liegen das der aTtiny85 kein else if versteht?

Disclaimer:
Ich bin mir bewusst das ich nicht einfach hier reinspazieren kann und mir den Code fertig basteln lassen kann. Das muss auch nicht sein denn ich möchte es ja lernen.
Ich habe hier auch noch mehrere Arduino UNO und MEGA rumliegen die auf ihren Einsatz warten nachdem ich mir ein paar Videos von GMD mal angesehen hab. Ihr kennt ihn bestimmt. :wink: Übrigens schade das er seinen Kanal nicht weiter betreibt. Gerade in Audiohardware fand ich seine Projekte sehr interessant.

Nein, das kannst Du ausschließen.

Erstes Ziel erreicht!

Du mußt die Signaländerung in beide Richtungen auswerten.

Wenn alter Tastenzustand ungleich aktueller Tastenzustand, dann

  1. wenn aktueller Tastenzustand HIGH, dann Code 1 senden
  2. wenn aktueller Tastenzustand LOW, dann Code 2 senden
1 Like

nein.

Da ich aber bei deinem Aufbau nicht weis was wann HIGH oder LOW ist, und du auch deinen Code nicht kommentiert hast, kann ich dir da auch nicht weiterhelfen.

Imho stimmt der Weg, du musst das gezeigte halt für dich anpassen.

1 Like

Nur nach Logik gebaut:

// Forensketch Keyboardcode nur bei Veränderung senden
// https://forum.arduino.cc/t/lichtschranke-fader-aktion-nur-einmal-ausfuhren/1052396/
// ungetestet

#include "DigiKeyboard.h"

const byte buttonPin = 2;
const byte ledPin =  1;
const bool aktiv = HIGH;  // HIER ggfls. ändrrn auf LOW
bool buttonState;
bool lastButtonState;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  DigiKeyboard.update();
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;
  auswerten(buttonState);
}

void loop()
{
  DigiKeyboard.sendKeyStroke(0);
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)
  {
    auswerten(buttonState);
    lastButtonState = buttonState;             // Zustand merken
    DigiKeyboard.delay(100);
  }
}

void auswerten(const bool zustand)
{
  if (zustand == aktiv)
  {
    digitalWrite(ledPin, HIGH);
    DigiKeyboard.sendKeyPress(KEY_F8, MOD_CONTROL_LEFT);
  }
  else
  {
    digitalWrite(ledPin, LOW);
    DigiKeyboard.sendKeyPress(KEY_F7, MOD_CONTROL_LEFT);
  }
}
1 Like

Danke für deinen Code. Werde ich heut Nachmittag mal testen.

Hallo @my_xy_projekt
Ich habe deinen Code mal als Lösung gesetzt weil dieser auf Anhieb auf dem Breadboard funktioniert hat.
Leider hatte ich vermutlich beim löten was kaputt gemacht wodurch der Attiny85 nicht mehr reagiert und ich erst neue bestellen musste.

Dennoch werde ich mir die Sache noch genauer anschauen um zu verstehen wie der Code funktioniert. Vielen Dank erst mal an alle die mir geholfen haben. :hearts: und schönen Sonntag

Ist eigentlich nicht weiter spektakulär.
Das, was vielleicht anders ist, ist die Übergabe in die Funktion auswerten.

Wenn Fragen sind, frag :wink:

So, nachdem ich mir meinen letzten Mikrocontroller beim verlöten zerbrutzelt hab, kamen die Tage die neuen und ich konnte mein Projekt umsetzen.
Das Resultat sieht nun so aus:

Mikrofon aus:

Sobald der Fader nun die Null Position aus der Gabellichtschranke verlässt schaltet sich in mAirList der Mikrofon Eingang ein und der Positionsstatus wird durch die LED unten signalisiert.

Nun meine Fragen zum Code:

Nun hab ja gerade erst begonnen C++ zu lernen.
Ich bin bisher immer davon aus gegangen das alle Variablen und Verarbeitenden Prozesse im
void loop selbst statt finden. Du @my_xy_projekt gehst aber einen ganz anderen weg und lässt nur das Resultat ausgeben im Bereich void auswerten oder? Das war mir neu.

Ansonsten danke ich allen sehr für eure Hilfe. :+1:
Mal sehen wann ich mich an das nächste Projekt setze und dadurch das programmieren erweitere.
Bis jetzt hab ich nur das Franzis Starter Set angefangen. Werd mich da aber noch weiter beschäftigen. Ach ja und meine Lötskills muss ich auch noch verbessern das ich mir nicht noch mehr Bauteile verbrutzel :stuck_out_tongue:

Ja.
Ich stückele in Funktionen...
Im loop() rufe ich normalerweise nur die Funktionen auf.
Das könnte bei Dir dann zum Beispiel - ausgehend von meinem Sketch oben - so aussehen:

// Forensketch Keyboardcode nur bei Veränderung senden
// https://forum.arduino.cc/t/lichtschranke-fader-aktion-nur-einmal-ausfuhren/1052396/
// basiert auf https://forum.arduino.cc/t/lichtschranke-fader-aktion-nur-einmal-ausfuhren/1052396/7?u=my_xy_projekt
// ungetestet

#include "DigiKeyboard.h"

const byte buttonPin = 2;
const byte ledPin =  1;
const bool aktiv = HIGH;  // HIER ggfls. ändrrn auf LOW
bool buttonState;
bool lastButtonState;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  DigiKeyboard.update();
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;
  auswerten(buttonState);
}

void loop()
{
  DigiKeyboard.sendKeyStroke(0);
  whatIsButtonState();
}

void whatIsButtonState()
{
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)
  {
    auswerten(buttonState);
    lastButtonState = buttonState;             // Zustand merken
    DigiKeyboard.delay(100);
  }
}

void auswerten(const bool zustand)
{
  if (zustand == aktiv)
  {
    digitalWrite(ledPin, HIGH);
    DigiKeyboard.sendKeyPress(KEY_F8, MOD_CONTROL_LEFT);
  }
  else
  {
    digitalWrite(ledPin, LOW);
    DigiKeyboard.sendKeyPress(KEY_F7, MOD_CONTROL_LEFT);
  }
}

und macht genau das selbe.
Wenn Du jetzt eine unbestimmte Menge Funktionen hast, dann kannst Du durch einfaches auskommentieren einer Zeile im loop() ganze Codeblöcke übergehen. :wink:

Da ich sehr viel mit dem seriellen Monitor als Kontrollinstanz code, habe ich mir angewöhnt nur Änderungen der Variablen ausgeben zu lassen.
Das passiert mit dem Aufruf auswerten(), wenn sichergestellt ist, das der neue Zustand buttonState sich vom alten lastButtonState unterscheidet.

Man könnte auch stetig den Zustand des buttonState senden und damit den Keyboardbuffer am Rechner flooden:

// Forensketch Keyboardcode nur bei Veränderung senden
// https://forum.arduino.cc/t/lichtschranke-fader-aktion-nur-einmal-ausfuhren/1052396/
// basiert auf https://forum.arduino.cc/t/lichtschranke-fader-aktion-nur-einmal-ausfuhren/1052396/7?u=my_xy_projekt
// ungetestet

#include "DigiKeyboard.h"

const byte buttonPin = 2;
const byte ledPin =  1;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  DigiKeyboard.update();
}

void loop()
{
  sendButtonState();
}

void sendButtonState()
{
  DigiKeyboard.sendKeyStroke(0);
  if (digitalRead(buttonPin) == HIGH)
  {
    digitalWrite(ledPin, HIGH);
    DigiKeyboard.sendKeyPress(KEY_F8, MOD_CONTROL_LEFT);
  }
  else
  {
    digitalWrite(ledPin, LOW);
    DigiKeyboard.sendKeyPress(KEY_F7, MOD_CONTROL_LEFT);
  }
  DigiKeyboard.delay(100);
}

:slight_smile:

Das ist echt schlau.
Naja insofern man verhindert das nur eine Aufgabe bei änderung erfolgt, könnte das Flooten doch auch verhindert werden oder? Aber so ist es natürlich die genialere Lösung.

Über eine Ausgabe per Seriell hab ich auch schon nachgedacht. serialprintln oder so das auch in mAirList interpretiert werden könnte.
Aber mit der Tastenkombination ist es allerdings viel einfacher und ggf auch manuell korrigierbar. Zudem lassen sich hiermit auch Discord oder andere Programme steuern. :wink: Daher hab ich mich für diesen Weg entschieden.

Mal sehen ob ich irgendwann Mal ein ganzes Mischpult mit Faderstart ausstatten werde. Das Prinzip ist ja das selbe nur mit dem Unterschied der zustande für mehrere Fader statt nur einem. Aber das sollte kein großes Problem sein.

Danke dir :+1:

Zu diesem Zweck gibt es dann Arrays und als Vollkomnung Array of struct.

Dann kannst Du die bisherigen Funktionen weiter verwenden und brauchst nur mit einem Zähler die Elemente durchgehen.

Rufst also einmal das gesamte Pult ab, gibst die geänderten Zustände raus, setzt das keyboard.delay() und fängst wieder an von vorn.
Wobei dann darauf geachtet werden muss, wie die Übernahme der Keyboardcodes tatsächlich funktionert -> Abhängig von der Anzahl Kanäle

Der Code zeigt das exemplarisch mit genau Deinem einen Kanal.
Erweiterung dann nur oben vor dem setup().
Ich hoffe nix übersehen zu haben...

// Forensketch Keyboardcode nur bei Veränderung senden
// https://forum.arduino.cc/t/lichtschranke-fader-aktion-nur-einmal-ausfuhren/1052396/
// ungetestet

#include "DigiKeyboard.h"


constexpr byte kanaele = 1;                                  // Anzahl der tatsächlichen Kanäle
constexpr byte buttonPin[kanaele] = {2,};                    // Für jeden Kanal einen PIN
constexpr byte ledPin[kanaele] = {1,};                       // Ebenfalls....
constexpr byte keyOneON[kanaele] = {KEY_F8, };               // Für jeden Kanal die entsprechende Keyboardtaste(n)
constexpr byte keyOneOFF[kanele] = {KEY_F7,};
constexpr byte KeyTwoON[kanaele] = {MOD_CONTROL_LEFT,};
constexpr byte kaeyTwoOFF[kanaele] = {MOD_CONTROL_LEFT,};
bool lastButtonState[kanaele] = {false,};                    // Für jeden Kanal einen Merker


const bool aktiv = HIGH;  // HIER ggfls. ändrrn auf LOW
bool buttonState;

void setup()
{
  DigiKeyboard.update();
  for (byte b = 0; b < kanaele; b++)
  {
    pinMode(ledPin[b], OUTPUT);
    pinMode(buttonPin[b], INPUT_PULLUP);
    buttonState = digitalRead(buttonPin[b]);
    lastButtonState[b] = buttonState;
    auswerten(lastButtonState[b]);
  }
}

void loop()
{
  DigiKeyboard.sendKeyStroke(0);
  for (byte b = 0; b < kanaele; b++)
  {
    buttonState = digitalRead(buttonPin[b]);
    if (buttonState != lastButtonState[b])
    {
      lastButtonState[b] = buttonState;             // Zustand merken
      auswerten(buttonState, b);
    }
  }
  DigiKeyboard.delay(100);
}

void auswerten(const bool zustand, const byte kanalNummer)
{
  if (zustand == aktiv)
  {
    digitalWrite(ledPin[kanalNummer], HIGH);
    DigiKeyboard.sendKeyPress(keyOneON[kanalNummer], keyTwoON[kanalNummer]);
  }
  else
  {
    digitalWrite(ledPin[kanalNummer], LOW);
    DigiKeyboard.sendKeyPress(keyOneOFF[kanalNummer], keyTwoOFF[kanalNummer]);
  }
}

Cool, auch wenn ich die hälfte davon "noch" nicht verstehe. :yum:
Aber das kommt auch noch...
Abgesehen davon, sollte ich Mal ein ganzes Mischpult mit soetwas ausstatten würde ich vermutlich nicht mehr über HID Keystrokes gehen sondern entweder Midi oder direkt seriell.
Das macht dann die Einbindung in speziellen Programmen einfacher die diese Schnittstelle besitzen.
Aber bis dahin ist noch viel Zeit und ich werde mir deine Antworten noch öfter anschauen.

Danke dir

Bei diesen Stichwörtern fällt mir mein Teensy 3.2 ein, der hilfreiche Bibliotheken zu der vorhandenen Hardware anbietet. Die Teensys lassen sich über eine Erweiterung auch mit der Arduino-IDE programmieren. Ist mein Tipp für so ein Projekt.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.