For Schleife verlassen/Button Counter

Hallo,
ich habe ein Sketch gefunden, welches LED blinken lässt wenn bei einem Musiksignal der Beat kommt. Ich möchte mit einem Knopf eine Counter machen, mit dem man durch unterschiedliche Modi zippen kann. Wenn ich nun an die Stelle komme an dem ich in den Blink/Beat Teil komme (for Schleife) dann stecke ich in ihr fest. Wenn ich das durch eine if abfrage, ob der Knopf gedrückt wurde unterbrechen will, so springt mein counter auf einmal unkontrolliert irgendwo hin.

Ich hoffe ihr versteht wie mein Problem und jmd kann mir eine Lösung erklären da ich noch relativ neu auf dem Gebiet Arduino bin.

#define SAMPLEPERIODUS 200

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define PIN        9 // Pin für die Datenleitung
#define NUMPIXELS 50 // Anzahl der WS2812 LEDs oder der NEOPIXEL
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

unsigned long previousMillis = 0;
const long interval = 500; 
const int  buttonPin = 13;    // the pin that the pushbutton is attached to
      // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0; 
int lastButtonState = 0;

void setup() {
    pinMode(buttonPin, INPUT);

  Serial.begin(9600);
  pixels.begin();
    // Set ADC to 77khz, max for 10bit
    sbi(ADCSRA,ADPS2);
    cbi(ADCSRA,ADPS1);
    cbi(ADCSRA,ADPS0);

    //The pin with the LED
    pinMode(2, OUTPUT);
}

// 20 - 200hz Single Pole Bandpass IIR Filter
float bassFilter(float sample) {
    static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
    xv[0] = xv[1]; xv[1] = xv[2]; 
    xv[2] = (sample) / 3.f; // change here to values close to 2, to adapt for stronger or weeker sources of line level audio  
    

    yv[0] = yv[1]; yv[1] = yv[2]; 
    yv[2] = (xv[2] - xv[0])
        + (-0.7960060012f * yv[0]) + (1.7903124146f * yv[1]);
    return yv[2];
}

// 10hz Single Pole Lowpass IIR Filter
float envelopeFilter(float sample) { //10hz low pass
    static float xv[2] = {0,0}, yv[2] = {0,0};
    xv[0] = xv[1]; 
    xv[1] = sample / 50.f;
    yv[0] = yv[1]; 
    yv[1] = (xv[0] + xv[1]) + (0.9875119299f * yv[0]);
    return yv[1];
}

// 1.7 - 3.0hz Single Pole Bandpass IIR Filter
float beatFilter(float sample) {
    static float xv[3] = {0,0,0}, yv[3] = {0,0,0};
    xv[0] = xv[1]; xv[1] = xv[2]; 
    xv[2] = sample / 2.7f;
    yv[0] = yv[1]; yv[1] = yv[2]; 
    yv[2] = (xv[2] - xv[0])
        + (-0.7169861741f * yv[0]) + (1.4453653501f * yv[1]);
    return yv[2];
}

void loop() {

    unsigned long time = micros(); // Used to track rate
    float sample, value, envelope, beat, thresh;
    unsigned char i;

 buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.print("Programm Nummer: ");
      Serial.println(buttonPushCounter);
    } delay(50);
 if (buttonPushCounter == 8) buttonPushCounter = 0;


  if (buttonPushCounter == 7) {
    for(i = 0;;++i){buttonState = digitalRead(buttonPin);
          unsigned long currentMillis = millis();
          //Serial.println(currentMillis);
        // Read ADC and center so +-512
        sample = (float)analogRead(0)-503.f;

        // Filter only bass component
        value = bassFilter(sample);

        // Take signal amplitude and filter
        if(value < 0)value=-value;
        envelope = envelopeFilter(value);

        // Every 200 samples (25hz) filter the envelope 
        if(i == 200) {
                // Filter out repeating bass sounds 100 - 180bpm
                beat = beatFilter(envelope);

                // Threshold it based on potentiometer on AN1
                thresh = 0.02f * (float)analogRead(1);
               
                // If we are above threshold, light up LED
                if(beat > thresh) {digitalWrite(2, HIGH);previousMillis = currentMillis;
                  for(int q=0;q<5;q++){
                  pixels.setPixelColor(q, pixels.Color(100,255,70)); // Moderately bright green color.
                  pixels.show();}
                  for(int w=5;w<10;w++){
                  pixels.setPixelColor(w, pixels.Color(0,0,0)); // Moderately bright green color.
                  pixels.show();}}
                else {digitalWrite(2, LOW);
                  if (currentMillis - previousMillis >= interval){
                    for(int r=0;r<NUMPIXELS;r++){
                    pixels.setPixelColor(r, pixels.Color(0,0,0)); // Moderately bright green color.
                    pixels.show();};}
                  else {
                  for(int w=5;w<10;w++){
                  pixels.setPixelColor(w, pixels.Color(100,255,70)); // Moderately bright green color.
                  pixels.show();}
                  for(int q=0;q<5;q++){
                  pixels.setPixelColor(q, pixels.Color(0,0,0)); // Moderately bright green color.
                  pixels.show();}}
                  }

                //Reset sample counter
                i = 0;

               
        }

        // Consume excess clock cycles, to keep at 5000 hz
        for(unsigned long up = time+SAMPLEPERIODUS; time > 20 && time < up; time = micros());
   //if (buttonState != lastButtonState) break;
    
        
      
}}



}}

Das der Sketch nicht einwandfrei und sauber ist, und evlt Verbesserungen vorzunehmen sind, bin ich mir bewusst :slight_smile:

Auto_Wechsel_Beat.ino (5.23 KB)

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Hallo,

Du solltest den Taster noch entprellen. Dazu gibt es fertige Lösungen in Libs oder Du baust es selber.

Heinz

Du kannst doch in deiner if-Abfrage in eine bestimmte Funktion springen.
Dann sollte das funktionieren.

n17_:
ich habe ein Sketch gefunden, ...
... da ich noch relativ neu auf dem Gebiet Arduino bin. ...

Gerade dann solltest Du nicht irgendeinen „ich hab' da was gefunden“-Kram kopieren und darin herumstümpern.

Code, in dem

}}

vorkommt, ist gundsätzlich pfui.

Gruß

Gregor

Rentner:
Du solltest den Taster noch entprellen

Zumindest sehe ich ein delay(50); Das sollte beide Flankenwechsel des Tasters entprellen, wenn ich mich nicht verguckt habe.

Hallo

@michael_x stimmt

dennoch
der Taster ist mit einem externen Pulldown Widerstand versehen ? PinMode(pin, INPUT).
es fehlt die Zeile zum setzen des lastButtonState,
es fehlt die Zeile zum rücksetzen es lastButtonState

Also ehr in der Art:

const byte buttonPin = 13;
byte buttonPushCounter = 0;
bool buttonState = 0;
bool lastButtonState = 0;
void setup() {
  // put your setup code here, to run once:

  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

  buttonState = digitalRead(buttonPin);
  if (!buttonState) lastButtonState = false;
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    lastButtonState = true;
    if (buttonState == true) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.print("Programm Nummer: ");
      Serial.println(buttonPushCounter);
    } 
    delay(50);
    if (buttonPushCounter == 8) buttonPushCounter = 0;


  }
 
}