Arduino Bluetooth Data als Interrupt

Hallo zusammen

Ich wollte mir meinen eigenen Controller für ein NeoPixel Streifen basteln.
Das funktioniert theoretisch auch schon. Allerdings führt er jeden Modus komplett durch, auch wenn er zwischenzeitlich neue Bluetooth Daten bekommen hat. Ich würde gerne dass er den Modus komplett abbricht und nicht wie bei einem normalen interrupt an der selben Stelle wieder anfängt.

Sonst würde er ja einmal den neuen Modus machen, dann den vorherigen zu ende und ab dann wieder erst den neuen in Schleife.

Derzeit benutze ich einen Arduino UNO Rev3 und ein HC-05 BT Modul über PIN 2 und 3.

Ist das überhaupt möglich?

Hier mal mein bisheriger Code:

#include <Adafruit_NeoPixel.h>
#include<SoftwareSerial.h>

#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(30, PIN, NEO_GRBW + NEO_KHZ800);
String btData;
SoftwareSerial serialbluetooth(2, 3);

void setup() {

  serialbluetooth.begin(9600);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}


void loop() {
  strip.setBrightness(20);

  if(serialbluetooth.available() > 0){
    btData = serialbluetooth.readString();
  }
  draw(btData);
}

void draw(String data) {
  if (data == "rb") {
    rainbowCycle(20);  
  }else if (data == "cw"){
    colorWipe(strip.Color(0, 70, 220), 20);
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256/**5*/; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Hi

Zuerst: Ja
Dann aber: Mit dem Sketch wohl eher nicht
Auch fehlen mindestens die Funktionen rainbow() und colorWipe() - Die werden, so befürchte ich, blockierend geschrieben sein.

MfG

postmaster-ino:
Auch fehlen mindestens die Funktionen rainbow() und colorWipe() - Die werden, so befürchte ich, blockierend geschrieben sein.

Upps, habe sie noch hinzugefügt.

postmaster-ino:
Dann aber: Mit dem Sketch wohl eher nicht

Deswegen frage ich ja :smiley:

Die Frage ist, muss ich da jetzt um jede for-Schleife eine Abbruchbedingung schreiben, ob BT Daten empfangen wurden oder geht das über einen Interrupt der alles abbricht, egal was in der Funktion passiert?

Hi

Die Befürchtung hat Sich bestätigt :o
Wenn Du in eine der Funktionen springst, bist Du in der for-Schleife und den vielen delay() gefangen.
Während dieser Zeit fragst Du nicht ab, ob neue ‘Befehle’ eingetroffen sind.
Bei der/den seriellen Schnittstelle/n kannst Du via serialevent auf eingehende Daten reagieren, z.B. ein Flag setzen o.Ä.
Ob Das auch mit SoftSerial geht, habe ich jetzt nicht überprüft!

Wenn die Funktion verlassen werden soll, die Schleife abbrechen (Variable auf Endwert setzen würde reichen, um halbwegs sauber aus der FOR raus zu kommen).
Dabei muß man auch das Flag zurück setzen, sonst wird die nächste Funktion genau so auch abgebrochen.

Mein Beispiel kommt von der RTC DS3132 aus der IDE

/**
  Serial event handling
*/
void serialEvent() {
  while (Serial.available()) {
    char c = Serial.read();
    if (c != '\r') {
      if (input.length() < 20 && c != '\n') {
        input = input + c;
      }
    }
    // analyze input
    else if (input.length() > 0) {
      // first char is command
      char cmd = input.charAt(0);
      boolean updated = false;
      String value = "";
      if (input.length() > 1) {
        value = input.substring(1);
      }
      switch (cmd) {
        case 'm': switchTickMode(); break;
        case 'n': switchAlarmMode(); break;
        case 'q': rtc3231.toggleAlarm(); updated = true; break;
        case 'c': rtc3231.clearAlarm(); rtc3231.resetTick(); updated = true; break;
        case 'h': showHelp(); break;
        case 'i': showInfo(); break;
        case 'r': showRegister(); break;
        case 'x': toggleClock(); break;
        case 'o': rtc3231.clearOSF(); updated = true; break;
        case 'd': rtc3231.setDate(value); updated = true; break;
        case 't': rtc3231.setTime(value); updated = true; break;
        case 'a': rtc3231.setAlarm(value); updated = true; break;
        case 's': rtc3231.toggle32kHz(); updated = true; break;
        case 'L': //Level debuglevelab
          debugablevel = value.toInt();
          Serial.print("Debug-LEVEL-AB gesetzt auf: ");
          Serial.println(debugablevel);
          break;
        case 'O': //debugother
          debugother = !debugother;
          Serial.print("Debug OTHER :");
          Serial.print((debugother) ? "ON" : "OFF");
          break;
      }
      if (updated)
        showInfo();
      updated = false;
      input = "";
    }
  }
}

MfG

Hallo,

for schleifen an sich sind ja noch nicht das Problem, nur wenn in einer schleife auch noch ein delay() ist dann werden sie zum Problem.

Wenn Du das delay durch millis() ersetzt kommst du mit If abfragen aus.

sieht dann so aus

Heinz

if (millis()-altzeit > delayzeit){
altzeit=millis();

// tu was 

}

Nachtrag delay in delayzeit geändert, konnte zu Verwechslung führen