Midi Noten senden, wenn sie in einem Bestimmten bereich des analog-Wert ist

Tommy56:
Eigentlich muss er eine ganze Messreihe mit verschiedenen Probanten fahren.

Vorschlag: Er lädt die Forumsschreiber zum Messtrinken ein und protokolliert die Werte. Er selbst muss dabei natürlich nüchtern bleiben :wink:

Gruß Tommy

ihr dürft sehr gerne kommen, entweder zum Messreihen Fahren oder zum Finalen bestaunen am Stadtfest.

agmue:
In #15 habe ich einen Fehler bereinigt: analogRead() ein paar Zeilen runter, denn man muß das nur tun, wenn die Zeit abgelaufen ist.

Na gut, das mit den doppelten Grenzen habe ich nicht gelöst bekommen, aber etwas struct geht schon:

const int AOUTpin = 0; //Der AOUT-Pin des Alkoholsensors geht in den analogen Pin A0 des Arduino über

const byte noteOn = 144;
uint32_t jetzt;

// MIDI-Nachricht senden
void MIDImessage (byte command, byte data1, byte data2) {
  Serial.write(command);
  Serial.write(data1);
  Serial.write(data2);
}

struct Grenzen
{
  const uint16_t Min, Max;
  const uint32_t pausen;
  const byte message;

Grenzen(const uint16_t Min, const uint16_t Max, const uint32_t pausen, const byte message)
    : Min(Min), Max(Max), pausen(pausen), message(message) {}

void ausgabe(uint16_t wert, byte &m, uint32_t &p)
  {
    if (wert >= Min && wert < Max)
    {
      if (m != message)
      {
        m = message;
        MIDImessage(noteOn, message, 127);
        p = pausen;
      }
    }
  }
};

Grenzen grenzen[]
{
  //min, max, pause, message
  {0, 200, 1800, 60},
  {200, 280, 1000, 61},
  {280, 350, 1000, 62},
  {450, 1024, 1000, 64},
  {350, 450, 1000, 63},
};

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

void loop()
{
  jetzt = millis();
  testeBereich();
  herzschlag();
}

void testeBereich() {
  static uint32_t vorhin = 0;
  static uint32_t pause;
  static byte me;
  if (jetzt - vorhin >= pause)
  {
    vorhin = jetzt;
    uint16_t wert = analogRead(AOUTpin); //Liest den analaog-Wert vom AOUT-Pin des Alkoholsensors
    for (Grenzen g : grenzen) g.ausgabe(wert, me, pause);
  }
}

void herzschlag()
{
  static uint32_t vorhin;
  if (jetzt - vorhin >= 500)
  {
    vorhin = jetzt;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}



Zufrieden?

hei danke viel mals für s weiter tüfteln, kapier es noch nicht, werde es aber ausprobieren und herausfinden. Ich brauche esmanchmal visuelle sachen um es zu kapieren.

Mahimus:
Da wir jetzt aber einen anderen Ablauf erläutert bekommen haben als im ersten Post: Dazu musst du eigentlich erst ein Programm laufen lassen, welches den maximalen Wert innerhalb einer Zeit misst (Bsp: Piepston oder LED als "Go", dann 5 Sek pusten, in dieser Zeit wird gemessen). Danach kommt erst das zweite Teilprogramm dran, welches entscheidet, in welcher Range der ermittelte Maximalwert liegt und welcher Ton abgespielt wird.

Dein Sketch macht stattdessen folgendes: Er nimmt den ersten Wert und spielt dann direkt die entsprechende Melodie und blockiert so lange weitere Messungen.

jo genau sowas wärs. Jetzt verstehe ich dein Sketch, dies ist auch sehr gut. Danke. Werde ich gleich ausprobieren

for (Grenzen g : grenzen) g.ausgabe(wert, me, pause);

Besser:

for (Grenzen& g : grenzen) g.ausgabe(wert, me, pause);

Serenifly:

for (Grenzen g : grenzen) g.ausgabe(wert, me, pause);

Besser:

for (Grenzen& g : grenzen) g.ausgabe(wert, me, pause);

Darüber hatte ich nachgedacht, mich dann für die Kopie entschieden. Da es aber inzwischen keine Variablen, die überflüssigerweise aufgehoben würden, mehr gibt, stimme ich Dir zu. Eine Kopie von Konstanten ist überflüssig.

Danke für den Hinweis, ich habe es geändert.

agmue:
Nach dem fünften kannst Du mal meine gerkürzte Version probieren (ungetestet):

const int AOUTpin = 0; //Der AOUT-Pin des Alkoholsensors geht in den analogen Pin A0 des Arduino über

const byte noteOn = 144;
uint32_t jetzt;

void setup() {
  Serial.begin(9600);
  pinMode (LED_BUILTIN, OUTPUT);
}
const uint16_t grenzen[] = {0, 200, 280, 350, 450, 1024};
const uint32_t pausen[] = {67800, 60000, 60000, 60000, 60000};
const byte message[] = {60, 61, 62, 63, 64};
const byte elemete = sizeof(message);

void loop()
{
  jetzt = millis();
  testeBereich();
  herzschlag();
}

void testeBereich() {
  static uint32_t vorhin, pause;
  static byte bereich = 255;
  if (jetzt - vorhin >= pause)
  {
    vorhin = jetzt;
    uint16_t wert = analogRead(AOUTpin); //Liest den analaog-Wert vom AOUT-Pin des Alkoholsensors
    for (byte b = 0; b < elemete; b++)
    {
      if (wert >= grenzen[b] && wert < grenzen[b + 1])
      {
        if (b != bereich)
        {
          bereich = b;
          MIDImessage(noteOn, message[b], 127);
          pause = pausen[b];
        }
      }
    }
  }
}

void herzschlag()
{
  static uint32_t vorhin;
  if (jetzt - vorhin >= 500)
  {
    vorhin = jetzt;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}
// MIDI-Nachricht senden
void MIDImessage (byte command, byte data1, byte data2) {
    Serial.write (command);
    Serial.write (data1);
    Serial.write (data2);
}



Damit Du merkst, da läuft noch was, habe ich einen Herzschlag eingebaut.
Gute Idee, als Schüler habe ich mal sowas gemacht, da mußte leider [u]ich[/u] nüchtern bleiben, blöd gelaufen :disappointed_relieved:

Wo schreibe ich die Zeit hin in der der Test läuft?
ansonsten funkt ziemlich gut. Muss dann nur noch ein externes LED Ansteuern für Atem befehl.

ResBaechli81:
Wo schreibe ich die Zeit hin in der der Test läuft?

Während ich programmiert habe, ist da möglicherweise eine neue Anforderung in die Diskussion gekommen, die ich nicht berücksichtigt habe. Ich wollte Dir auch nur eine Anregung geben, kein fertiges Programm.

agmue:
Während ich programmiert habe, ist da möglicherweise eine neue Anforderung in die Diskussion gekommen, die ich nicht berücksichtigt habe. Ich wollte Dir auch nur eine Anregung geben, kein fertiges Programm.

die Anregung ist super, es spornt mich noch mehr an diese arduino welt zu verstehen. Sau toll und anstrengend, wie eine komplett neue Sprache für mich.
Verstehe ich das richtig, die void herzschlag() und void testeBereiche() sind quasy erweiterte loops.?. L
Könnte mann theoretisch unendlich solcher loop programme einbauen?

sagen wir "Aufgaben".
Solange du jeder Aufgabe oft genug aufrufst und die anderen Aufgaben NICHT BLOCKIEREN, kannst du das verwenden.

@ResBaechli81: Bitte beachte, daß ich meine Beiträge #19 und #24 etwas geändert habe.

ResBaechli81:
die Anregung ist super, es spornt mich noch mehr an diese arduino welt zu verstehen. Sau toll und anstrengend, wie eine komplett neue Sprache für mich.

So soll es sein!

ResBaechli81:
Verstehe ich das richtig, die void herzschlag() und void testeBereiche() sind quasy erweiterte loops.?.

Es gibt nur eine Schleife, loop() ist die Schleife. Wenn Du von anderen Programmiersprachen kommst, hilft Dir möglicherwise die Vorstellung, im Hauptprogramm werden zunächst die Setups durchgeführt, dann folgt while(1).

herzschlag() und testeBereiche() sind Funktionen, die von der Schleife aufgerufen werden, es sind aber auch Verschachtelungen möglich. Funktionen können der Übersichtlichkeit dienen, sie können aber auch immer wiederkehrenden Code zusammenfassen.

Ich würde es daher etwas anders formulieren: Funktionen sind Erweiterungen von loop().

ResBaechli81:
jo genau sowas wärs. Jetzt verstehe ich dein Sketch, dies ist auch sehr gut. Danke. Werde ich gleich ausprobieren

Ich hatte keinen Sketch gepostet. Der Sketch von agmue ist meiner Meinung nach nicht anfängerfreundlich, wenn auch in sehr schönem Stil geschrieben soweit ich das überhaupt beurteilen kann. Ich empfehle: arbeite mit deinem eigenen Ansatz weiter.

Kannst du Programmabläufe abhängig von der Zeit steuern? Dazu benutzt man die funktion millis(). Suche mal nach Tutorials wenn du es noch nicht beherrscht.
Dann musst du eben eine bestimmte Zeit lang NUR messen und immer den Wert merken, der bis dato der höchste war. Du merkst dir also bei jedem loop-Durchlauf den letzten Wert und vergleichst das neue Messergebnis mit diesem. Wenn der neue Wert größer ist, setze den gemerkten "value_max" mit diesem gleich. Viel Erfolg, und poste gerne deinen Versuch, wenn es noch Probleme/Fragen gibt.

Mahimus:
Ich hatte keinen Sketch gepostet. Der Sketch von agmue ist meiner Meinung nach nicht anfängerfreundlich, wenn auch in sehr schönem Stil geschrieben soweit ich das überhaupt beurteilen kann. Ich empfehle: arbeite mit deinem eigenen Ansatz weiter.

Kannst du Programmabläufe abhängig von der Zeit steuern? Dazu benutzt man die funktion millis(). Suche mal nach Tutorials wenn du es noch nicht beherrscht.
Dann musst du eben eine bestimmte Zeit lang NUR messen und immer den Wert merken, der bis dato der höchste war. Du merkst dir also bei jedem loop-Durchlauf den letzten Wert und vergleichst das neue Messergebnis mit diesem. Wenn der neue Wert größer ist, setze den gemerkten "value_max" mit diesem gleich. Viel Erfolg, und poste gerne deinen Versuch, wenn es noch Probleme/Fragen gibt.

super danke, werde ich gerne tun.

Ich hatte heute mal Lust auszuschreiben wie ich es mir gedacht habe.
Hier läuft immer 5 Sek lang eine Messung, der größte in dieser Zeit gemessene Wert wird dann herangezogen um den Midisound auszuwählen. 4 Sek nach Ende der Messung geht es wieder los. Diesen Ablauf könntest du auch noch mit einem Taster steuern als nächsten Erweiterungsschritt.

Hab den Code nicht getestet, sag gern bescheid ob's funktioniert.

const int AOUTpin = 0; //Der AOUT-Pin des Alkoholsensors geht in den analogen Pin A0 des Arduino
#define Status_Pin 13

int limit;
int value;
int noteOn = 144;
unsigned long timer = 0;

const int Messdauer = 5000;  // so lange dauert die Messung
int value_max = 0;



void setup() {

  Serial.begin(9600);

}

void loop() {


  if (millis() - timer < Messdauer) {
    digitalWrite(Status_Pin, HIGH);
    value = analogRead(AOUTpin);          // Liest den analaog-Wert vom AOUT-Pin des Alkoholsensors
    if (value_max < value) {
      value_max = value;
    }
  }
  else {

    digitalWrite(Status_Pin, LOW);
    value_max = 0;

    if (value_max < 200)
    {
      MIDImessage(noteOn, 60, 127);
    }
    if (value_max >= 200 && value_max < 280)
    {
      MIDImessage(noteOn, 61, 127);
    }
    if (value_max >= 280 && value_max < 350)
    {
      MIDImessage(noteOn, 62, 127);
    }
    if (value_max >= 350 && value_max < 450)
    {
      MIDImessage(noteOn, 63, 127);
    }
    if (value_max > 450)
    {
      MIDImessage (noteOn, 64, 127);
    }
      delay(4000);
      timer = millis() ;
  }
  
}

//send MIDI message
// MIDI-Nachricht senden
void MIDImessage (byte command, byte data1, byte data2) {
  Serial.write (command);
  Serial.write (data1);
  Serial.write (data2);

}

Hier kannst du nachlesen, wie du eigene Funktionen deklarieren kannst: Function Declaration
Und nein, du kannst nicht unendlich viele davon einbauen, nur so viele bis der Programmspeicher auf deinem Arduino voll ist. Also viele. :wink:
Du hast ja selbst auch schon eine Funktion in deinem Code um den Midi Sound zu senden. Damit weißt du ja wie du sie in den Code einpflegst.

Mahimus:
Ich hatte heute mal Lust auszuschreiben wie ich es mir gedacht habe.
Hier läuft immer 5 Sek lang eine Messung, der größte in dieser Zeit gemessene Wert wird dann herangezogen um den Midisound auszuwählen. 4 Sek nach Ende der Messung geht es wieder los. Diesen Ablauf könntest du auch noch mit einem Taster steuern als nächsten Erweiterungsschritt.

Hab den Code nicht getestet, sag gern bescheid ob's funktioniert.

const int AOUTpin = 0; //Der AOUT-Pin des Alkoholsensors geht in den analogen Pin A0 des Arduino

#define Status_Pin 13

int limit;
int value;
int noteOn = 144;
unsigned long timer = 0;

const int Messdauer = 5000;  // so lange dauert die Messung
int value_max = 0;

void setup() {

Serial.begin(9600);

}

void loop() {

if (millis() - timer < Messdauer) {
    digitalWrite(Status_Pin, HIGH);
    value = analogRead(AOUTpin);          // Liest den analaog-Wert vom AOUT-Pin des Alkoholsensors
    if (value_max < value) {
      value_max = value;
    }
  }
  else {

digitalWrite(Status_Pin, LOW);
    value_max = 0;

if (value_max < 200)
    {
      MIDImessage(noteOn, 60, 127);
    }
    if (value_max >= 200 && value_max < 280)
    {
      MIDImessage(noteOn, 61, 127);
    }
    if (value_max >= 280 && value_max < 350)
    {
      MIDImessage(noteOn, 62, 127);
    }
    if (value_max >= 350 && value_max < 450)
    {
      MIDImessage(noteOn, 63, 127);
    }
    if (value_max > 450)
    {
      MIDImessage (noteOn, 64, 127);
    }
      delay(4000);
      timer = millis() ;
  }
 
}

//send MIDI message
// MIDI-Nachricht senden
void MIDImessage (byte command, byte data1, byte data2) {
  Serial.write (command);
  Serial.write (data1);
  Serial.write (data2);

}





Hier kannst du nachlesen, wie du eigene Funktionen deklarieren kannst: [Function Declaration](https://www.arduino.cc/en/Reference/FunctionDeclaration)
Und nein, du kannst nicht unendlich viele davon einbauen, nur so viele bis der Programmspeicher auf deinem Arduino voll ist. Also viele. ;-) 
Du hast ja selbst auch schon eine Funktion in deinem Code um den Midi Sound zu senden. Damit weißt du ja wie du sie in den Code einpflegst.

Super danke werde dies alles dieses Wochende ausprobieren und mich melden wenn alles geklappt hat.
Danke viel mals

Hallo noch mal an die netten Helfer,
ich habe das Problem jetzt für mich am einfachsten und verständlichsten gelöst.
Habe noch einen einfachen ein aus Taster eingebaut.

Ablauf: Mensch kommt drückt Knopf ein Signalbild (auch via MIDI an Resolume) Sagt er kann rein Atmen, nach einer kurzen Verzögerung (muss ich noch ein bisschen tüfteln wie lange die sein soll) gibt es den letzen wert als midi befehl weiter.
so klappt es gerade recht gut.

Hier mein Code.

  const int AOUTpin = 0; //Der AOUT-Pin des Alkoholsensors geht in den analogen Pin A0 des Arduino
  #define Status_Pin 13
  
  int taste= LOW;
  int tasteAlt= LOW;
  
  int limit;
  int value;
  int noteOn = 144;
  
  

void setup() {

  Serial.begin(9600);
  pinMode(2, INPUT);
}

void loop() {
 taste = digitalRead(2);
  if (taste== HIGH && tasteAlt == LOW){
    Serial.write(144);
    Serial.write(36);
    Serial.write(127);
    tasteAlt = taste;
    value= analogRead(AOUTpin);//Liest den analaog-Wert vom AOUT-Pin des Alkoholsensors
    {delay (3000);}
  if(value<200) 
  {
      MIDImessage(noteOn, 60, 127);      
  }
  if (value>=200 && value<280)
  {
      MIDImessage(noteOn, 61, 127);      
  }
  if (value>=280 && value<350)
  {
      MIDImessage(noteOn, 62, 127);      
  }
  if (value>=350 && value <450)
  {
      MIDImessage(noteOn, 63, 127);      
  }
  if(value>450)
  {
      MIDImessage(noteOn, 64, 127);     
  } 

  
    
  }
  if (taste == LOW && tasteAlt == HIGH){
    Serial.write(144);
    Serial.write(36);
    Serial.write(0);
    tasteAlt = taste;
  }

  
  
}

//send MIDI message
// MIDI-Nachricht senden
void MIDImessage (byte command, byte data1, byte data2) {
  Serial.write (command);
  Serial.write (data1);
  Serial.write (data2);

}

Werde es eventuell noch mit weiteren Sensoren bestücken um ein bisschen die Umgebungsgeräusche oder licht Verhältnisse auf zu nehmen.

Vielen dank
A.