Ich finde den Fehler im simplen Code nicht :--(

Hallo zusammen,

ich Code nun mal wieder nach ca. 20 Jahren und finde seit Stunden vermutlich den banalen Fehler in einem eigentlich relativ einfachen Code (für den Controller Adafruit Feather 32u4 Bluefruit LE [2829]) nicht.
Über Hinweise zum Fehler oder Denkhilfe wäre ich sehr dankbar.
Folgendes:

Code snippet, der auch problemlos kompiliert und auf dem Controller ausgeführt wird:

   //read the state of the switch/button:
    mb_currentState = digitalRead(button7);

    if (mb_lastState == HIGH && mb_currentState == LOW) { // button is pressed
      mb_pressedTime = millis();
    } else if (mb_lastState == LOW && mb_currentState == HIGH) {  // button is released
      mb_releasedTime = millis();

      long mb_pressDuration = mb_releasedTime - mb_pressedTime;

      if (mb_pressDuration < SHORT_PRESS_TIME) {
        Serial.println("A short press is detected");
        Serial.println(mb_pressDuration);
      }
    }
    mb_lastState = mb_currentState;

Wenn ich den obigen Code allerdings wie nachfolgend ändere (um eine "else" erweitere), kompiliert die IDE anstandslos den Code, aber der Controller hängt dann, bis meine IDE den Controller bzw. den Port "verliert".

   //read the state of the switch/button:
    mb_currentState = digitalRead(button7);

    if (mb_lastState == HIGH && mb_currentState == LOW) { // button is pressed
      mb_pressedTime = millis();
    } else if (mb_lastState == LOW && mb_currentState == HIGH) {  // button is released
      mb_releasedTime = millis();

      long mb_pressDuration = mb_releasedTime - mb_pressedTime;

      if (mb_pressDuration < SHORT_PRESS_TIME) {
        Serial.println("A short press is detected");
        Serial.println(mb_pressDuration);
      } else {
        Serial.println("A extralong press is detected");
        Serial.println(mb_pressDuration);
      }
    }
    mb_lastState = mb_currentState;

Im Grunde ist da nur die zusätzliche "else" eingebaut. Mache ich da etwas falsch?

Danke & LG,
fxworker

Wenn Du Hilfe willst, dann gib uns einen Sketch der den Fehler hat und den wir kompilieren können.
Außerdem eine Kopie der Fehlermeldungen die Du erhälst, ist auch notwendig.
Grüße Uwe

Danke. Ok, gerne.

Nachfolgend die ino-Datei.
myController.ino (31,1 KB)

Fehlermeldungen erhalte wie oben genannt keine. Copy/paste aber gerne mal den Output:
Sketch uses 16862 bytes (58%) of program storage space. Maximum is 28672 bytes.
Global variables use 2340 bytes of dynamic memory.
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
Device code: 0x44

Info: Die besagte "else" befindet sich in Zeile 605.

Nutze mal zur Seriellen Ausgabe das F-Makro. Das schont den Arbeitsspeicher.


//read the state of the switch/button:
    mb_currentState = digitalRead(button7);

    if (mb_lastState == HIGH && mb_currentState == LOW) { // button is pressed
      mb_pressedTime = millis();
    } else if (mb_lastState == LOW && mb_currentState == HIGH) {  // button is released
      mb_releasedTime = millis();

      long mb_p) {
        Serial.println(F("A short press is detected"));
        Serial.println(mb_pressDuration);
      } else {
        Serial.println(F("A extralong press is detected"));
        Serial.println(mb_pressDuration);
      }
    }
    mb_lastState = mb_currentState;

Generell solltest du auch an anderen Stellen schauen, wie du am Arbeitsspeicherverbrauch sparen kannst.

Vielleicht willst Du die Auswertung auf die Länge des Tastendrucks nur machen, wenn sich der Status sich geändert hat. Dann würde (ohne Entprellung) außen herum noch eine entsprechende Abfrage fehlen:

if (mb_currentState != mb_lastState) {
  // snippet
}

Der Rest vom Code hat übrigens Verbesserungspotential, auch wenn man nicht gleich in Klassen und Objekten denken mag. Von 1...9 nummerierte Variablen schreien nach Arrays, für Pin-Nummern Zustände reichen bool statt int (das spart auch Speicher) und Code-Wiederholungen nach Funktionen.

Vielen lieben Dank für die hilfreichen Hinweise.
Dass der Speicher voll zu laufen drohen könnte, hatte ich tatsächlich gar nicht im Kopf, und auch dass dies das Problem werden/sein könnte.

Der Code hat sicherlich mehr als ausreichend Verbesserungspotential - hatte es auf später aufgeschoben. Nehme ich nun ebenso als begleitende Prio-Task mit.

Danke euch herzlich. :hugs:

Kurze Frage: Auf welchem Controller soll das laufen?
Und dann hast Du einige Probleme da drin verbaut.
Erster Bock ist schon vor dem setup()

 #if SOFTWARE_SERIAL_AVAILABLE

Das muss richtig heissen:

#ifdef SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif

Richtig geil wird es erst, wenn man die Meldungen alle durch geht. Dann sieht man, das Adafruit das anscheinend auch so versucht.

/home/user1/arduino-1.8.19/portable/sketchbook/libraries/Adafruit_BluefruitLE_nRF51-master/Adafruit_BluefruitLE_UART.h:68:5: warning: this use of "defined" may not be portable [-Wexpansion-to-defined]
 #if SOFTWARE_SERIAL_AVAILABLE
     ^~~~~~~~~~~~~~~~~~~~~~~~~

und das in Größenordnungen.

Dann hast Du Konstanten gesetzt, die braucht es nicht.

const int button1state = LOW;

wäre da so ein Kandidat.
Deine Buttonabfrage für Deine 9 Btn ist sich wiederholender kopierter Code. Das lässt sich alles in einen 10Zeiler schieben.

Die widerholenden analogread()

  digitalWrite(ledRED, HIGH);
      // Joystick: set neutral positions
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);

sollen anscheinend dafür dienen, dass Du nicht den ersten Wert bekommst.
Wenn Du einen Wert haben möchtest, der gemittelt ist, dann macht man das anders... :wink:
Zumal es das auch mehrfach gibt....

Dann habe ich noch nicht verstanden, was das ble.send und ble.println unterschiedliches machen...
Aber definitiv müssen Deine delay() da raus.

ich glaub, wenn ich mich damit ne Runde beschäftige, wird der auf die Hälfte geschrumpft :slight_smile:

Die Antwort kam schon in Post #1

Beispiellink:
https://www.reichelt.de/adafruit-feather-32u4-bluefruit-le-ada-fb-32u4-bfle-p235449.html

1 Like

@Plumps, vielen Dank für die Beantwortung der Controller-Frage. War kurz noch mit der Family beschäfitg.

@my_xy_projekt, dass der Code nach einer QS sehr schrumpfen, besser ge-cocedet, etc. sein dürfte, nehme ich dir zu 100% ab.
Ich hätte kein Problem, mich in einer Druckbetankung via Screensharing auf die Finger hauen zu lassen, wenn ich dabei live zusehen und v. A. was in Realtime dabei lernen dürfte. :slight_smile:

Das muss richtig heissen:

#ifdef SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif

Oki, vielen Dank. Ist geändert.

Dann hast Du Konstanten gesetzt, die braucht es nicht.

const int button1state = LOW;

wäre da so ein Kandidat.

Ändere/lösche ich testweise ebenfalls.

Die widerholenden analogread()

  digitalWrite(ledRED, HIGH);
      // Joystick: set neutral positions
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);
      LR_neutral = analogRead(button8);
      UD_neutral = analogRead(button9);

sollen anscheinend dafür dienen, dass Du nicht den ersten Wert bekommst.
Wenn Du einen Wert haben möchtest, der gemittelt ist, dann macht man das anders... :wink:
Zumal es das auch mehrfach gibt....

Hatte ich iiiiirgendwo aufgeschnappt, daß man das sicherheitshalber mehrfach abfragen kann, falls die Initial-Werte beim ersten Mal nicht gelesen werden können.
Habe aber die mittlerweile auch nur 1x drin.
(Nein, gemittelt werden sollte da nichts.)

Dann habe ich noch nicht verstanden, was das ble.send und ble.println unterschiedliches machen...

Öhhmm... keine Ahnung. Soll ich hier nur das Eine oder das Andere verwenden, oder ist es "nur" ein Schönheitsfehler?

Aber definitiv müssen Deine delay() da raus.

Da versuche ich mich gerade "durch zu fuchsen" (und bin mangels Wissen&Erfahrung noch bissl ängstlich, was das zur Folge hätte und wann man was am Besten einsetzt.)

An dieser Stelle, danke vielmals für eure Tips und Hinweise. :hugs:
Jeder Erkenntnisgewinn ein Genuß.

PS: Falls mir jemand auf die Finger klopfen will via Teams/WebEx/wasAuchImmer, bitte gerne melden :innocent:

Hab ich nicht als richtigen Controller erkannt... Asche aufs Haupt...

Das richtigste und wichtigste der Welt!

1 Like

Ich bin mal durchgescrollt...
Sag mir mal kurz, was LR_neutral und UD_neutral ist.
Da hängt ein Joystick dran. Ist das einmal X und Y Achse?

Alles andere löse ich auf, wenn Du mir noch kurz erklärst, was das hier werden soll:


      for (int i = 1; i <= softApp; i++)
      {
        digitalWrite(ledGREEN, HIGH);
        delay(300);
        digitalWrite(ledGREEN, LOW);
        delay(300);
      }

Sieht aus, wie der Versuch eines Blinkers.

Genau, da hängt ein Joy-/Thumbstick dran.
LR_neutral und UD_neutral sind die Variablen, die die Werte bei der "Leer-/Neutralstellung" speichern.

Die For-Schleife:
Beim Starten des Controllers kann ich zwischen 5 Anwendungen wählen und die Grüne LED blinkt zwischen 1-5 Mal, um anzuzeigen, welche der Buttons ich gedrückt habe. Kann eigentlich raus für meinen Zweck.

Ne. :rofl:
Ok. Ich seh mal zu, was sich daraus machen lässt.
Denn die Werte für LR_neutral / UD_neutral änderst Du während des laufenden Betriebes; Ich kann mir aber vorstellen, was das insgesamt ist.

Man liest sich morgen - ich nehm den mal in die Nacht mit.

1 Like

Der HAMMER! :smiling_face_with_three_hearts:
In Ordnung. Danke dir schon mal herzlichst.
Ich gedulde mich dann mal optimistisch und gespannt.

etwas Grundlagen.

Wenn die Signalquelle zu hochomig ist kann der interne Sample ans Hold Kondensator (der speichert die Spannung während der AD Wandlung weil diese Schrittweise gemacht wird und von anfang bis Ende die Sapnnung konstant sein muß) in einer Ladezeit nicht auf Endwert geladen /entladen werden. Da hilft mehrmaliges messen, weil so mehrmals auf die gleiche Spannung geladen wird.

So wie Du es machst ist das sinnlos da Du die Messung abwechseld machst und so immer zwischen 2 Spannungen hin und her geladen wird. Wenn Du das machen willst dann 4x LR_neutral und dann 4 mal UD_neutral.

https://www.semiversus.com/dic/hardwarenahe_programmierung/avr_adc.html

Grüße Uwe

Vielen Dank @uwefed, so verstehe ich den Hintergrund diesen Aufrufs auch. :pray:
Auch wenn der bei mir mittlerweile, wie gesagt schon weggebaut ist.

Alter.... was ist denn das für ein Code. :weary:
Da sitz ich noch ne Nacht dran...
Was ich mittlerweile verstanden habe sind 5 Push- und 2 Toggle-button.
Dann zwei analoge Eingänge für die Joystickbewegung up/Down Left/right
Interessant ist dann die Verarbeitung.
softApp ist eine Merkervariable, aber Du machst einen typischen Anfängerfehler. Grundsätzlich: Wenn gezählt wird, wird mit 0 angefangen!
Damit ist dann natürlich alles andere was danach kommt auch zu bearbeiten.

Um Dir mal einen Eindruck zu geben... So sieht derzeit der bearbeitete erste Teil aus.
Vergleich das mal mit Deinem :slight_smile:

#include <Arduino.h>
#include <SPI.h>
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"

#ifdef SOFTWARE_SERIAL_AVAILABLE
  #include <SoftwareSerial.h>
#endif

// #if USB_HID_KEYS
// #include <usb_hid_keys.h>
// #endif
/**
   Modifier masks - used for the first byte in the HID report.
   NOTE: The second byte in the report is reserved, 0x00
*/
#define KEY_MOD_LCTRL 0x01
#define KEY_MOD_LSHIFT 0x02
#define KEY_MOD_LALT 0x04
#define KEY_MOD_LMETA 0x08
#define KEY_MOD_RCTRL 0x10
#define KEY_MOD_RSHIFT 0x20
#define KEY_MOD_RALT 0x40
#define KEY_MOD_RMETA 0x80

Adafruit_BluefruitLE_SPI ble(8, 7, 4);

//Factory reset to 0 for no reset, or 1 to factory reset when scketch starts
constexpr byte FACTORYRESET_ENABLE {0};

constexpr int BUFSIZE {128};  // Size of the read buffer for incoming data

/////////////////////////////////////////////////////////
//Choose some setting that may be different on your unit
/////////////////////////////////////////////////////////

//APP LED SEQUENCE OF COLOUR. SWOP THE VALUE OF YOUR COLCOURS ARE WRONG WAY AROUND
constexpr byte ledGREEN {A1};
constexpr byte ledRED {A0};

//PUSH BUTTONS STATE FOR NORMALLY OPEN AND NORMALLY CLOSED
//FOR Normally open buttons keen the state LOW.
//FOR Normally closed buttons change the state to HIGH

constexpr byte pushBtn[] {12, 11, 10, 9, 5};
constexpr byte pushBtnSize {sizeof(pushBtn) / sizeof(pushBtn[0])};

constexpr byte toggleBtn[] {A2, A3};
constexpr byte toggleBtnSize {sizeof(toggleBtn) / sizeof(toggleBtn[0])};

constexpr byte joy[] {A4, A5};
constexpr byte joySize {sizeof(joy) / sizeof(joy[0]};


//TOGGLE SWITCH BUTTONS
const int button6 = A2;  // Not used currently, so deactivating it! => Trying to use it now (28.12.) as Time-based App ModeSelect-Button
const int button7 = A3;  // <= Joystick Button
const int button8 = A4;
const int button9 = A5;


//APP SWITCH BUTTON
constexpr byte modeSelectPin {6};   // Mode-Switch-Button on PIN-6
byte modeSelectState = 0;  // Testing to set Mode-Select via "Taster-Knopf"
//int softApp;                //Keep softapp default 0 when starting up
byte softApp = 1;  //preset softapp to app 3 when starting up

// For Button-6
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;  // will store last time LED was updated
// constants won't change:
const long interval = 250;  // interval at which an App can be selected (milliseconds)

// Joystick: analog readings for positions (l,r,u,d)
int LR;
int UD;
// Joystick: variables for calibration
int LR_neutral;
int UD_neutral;
int mouseClickFlag = 0;
//BleMouse bleMouse;
const int Deadzone = 100;

//BUTTON & TOGGLE FIXED SCROLL SPEED
const int buttonWait = 250;
const int toggleWait = 150;
const int arrowButtonWait = 250;

// COUNTER FOR LOCUS BUTTON ITERATO7
int locusIter;

#define SHORT_PRESS_TIME 1000  // 500 milliseconds
// Variables will change:
bool mb_lastState = LOW;  // the previous state from the input pin
bool mb_currentState;     // the current reading from the input pin
unsigned long mb_pressedTime = 0;
unsigned long mb_releasedTime = 0;

////////////////////////////////////////////////////////////////////////////////////////////////

void serPrint(const __FlashStringHelper *err)
{
  Serial.println(err);
  //while (1);
}


////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
  //Serial.begin(115200);
  Serial.begin(9600);
  Serial.println(F("Starting up ..."));
  bleINIT();
  //Push buttons
  for (byte b = 0; b < pushBtnSize; b++)
  { pinMode(pushBtn[b], INPUT_PULLUP); }
  //Toggle switch buttons
  pinMode(button7, INPUT_PULLUP);  // For MouseClick
  //pinMode(button8, INPUT);
  //pinMode(button9, INPUT);
  //Mode LEDs
  pinMode(ledGREEN, OUTPUT);
  pinMode(ledRED, OUTPUT);
  //App rocker switch
  pinMode(modeSelect, INPUT_PULLUP);
  // Joystick: set neutral positions
  LR_neutral = analogRead(button8);
  UD_neutral = analogRead(button9);
  //ble Mouse Starter
  //bleMouse.begin();
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
  //  Serial.print("SoftApp # at startup is: ");
  //  Serial.println(softApp);
  //////////////////////////////////////////////////////////////
  // START SOFT APP SELECT LOOP
  //////////////////////////////////////////////////////////////
  //Start of select softapp 1
  if (!digitalRead(modeSelectPin))             // Taste geddrückt?
  {
    digitalWrite(ledRED, HIGH);                // 
    digitalWrite(ledGREEN, LOW);
    //Serial.print(" modeSelect = LOW :: "); Serial.println(modeSelect);
    for (byte b = 0; b < pushBtnSize; b++)     // frage die tasten ab
    {
      if (!digitalRead(pushBtn[b]))            // Taste gedrückt?
      {
        softApp = b + 1;                       // Tastendruck merken
        setApp(softApp);                       // Voreinstellung setzen
      }
    }     // END SOFT APP SELECT LOOP
  }
  else                                         // Taste nicht gedrückt
  {
    digitalWrite(ledRED, LOW);
    digitalWrite(ledGREEN, HIGH);
    //Serial.print(" modeSelect = HIGH :: "); Serial.println(modeSelect);
    switch (softApp)
    {
      case 0:
        //Serial.println("You are in softApp: ZERO");
        digitalWrite(ledGREEN, HIGH);
        delay(300);
        digitalWrite(ledGREEN, LOW);
        delay(300);
        break;  //End softapp 0
      case 1:
        digitalWrite(ledGREEN, HIGH);
        if (locusIter >= 10)
        {
          locusIter = 0;
        }
        //PUSH BUTTONS
        for (byte b = 0; b < pushBtnSize; b++)
        {
          if (!digitalRead(pushBtn[b]))
          { sendFuncOne(b); }
        }
        break;  //End softapp 1
      case 2:
        digitalWrite(ledGREEN, HIGH);
        digitalWrite(ledRED, LOW);
        //PUSH BUTTONS
        for (byte b = 0; b < pushBtnSize; b++)
        {
          if (!digitalRead(pushBtn[b]))
          { sendFuncTwo(b); }
        }
        break; //End softapp 2
      case 3:
        digitalWrite(ledGREEN, HIGH);
        digitalWrite(ledRED, LOW);
        //PUSH BUTTONS
        for (byte b = 0; b < pushBtnSize; b++)
        {
          if (!digitalRead(pushBtn[b]))
          { sendFuncThree(b); }
        }
        break;  //End softapp 3
      case 4:
        digitalWrite(ledGREEN, HIGH);
        digitalWrite(ledRED, LOW);
        //PUSH BUTTONS
        for (byte b = 0; b < pushBtnSize; b++)
        {
          if (!digitalRead(pushBtn[b]))
          { sendFuncFour(b); }
        }
        break;  //End softapp 4
      case 5:
        // 0x7F Keyboard Mute
        // 0x80 Keyboard Volume Up
        // 0x81 Keyboard Volume Down
        digitalWrite(ledGREEN, HIGH);
        digitalWrite(ledRED, LOW);
        //Serial.println("You are in softApp");
        //PUSH BUTTONS
        for (byte b = 0; b < pushBtnSize; b++)
        {
          if (!digitalRead(pushBtn[b]))
          { sendFuncFive(b); }
        }
        break;  //End softapp 5
    }
    // ******************************************************** START of GLOBAL PART *****************************************************

Alles, was Du jetzt nicht siehst, ist bereits umgeschrieben und ausgelagert.
Deine Push-Button-Auswahl Ausführung ist jeweils runtergekürzt -> Für Ebene 1 hier die komplette Funktion.

void sendFuncOne(const byte btn)
{
  digitalWrite(ledGREEN, LOW);
  delay(buttonWait);
  digitalWrite(ledGREEN, HIGH);
  switch (btn)
  {
    case 0:
      Serial.println("Button 1-1");
      ble.sendCommandCheckOK("AT+BleHidControlKey=VOLUME+");
      break;
    case 1:
      Serial.println("Button 1-2");
      ble.sendCommandCheckOK("AT+BleHidControlKey=VOLUME-");
      break;
    case 2:
      Serial.println("Button 1-3");
      ble.sendCommandCheckOK("AT+BLEKEYBOARDCODE=00-00-15-00-00-00-00");
      ble.sendCommandCheckOK("AT+BLEKEYBOARDCODE=00-00");
      break;
    case 3:
      Serial.println("Button 1-4");
      ble.sendCommandCheckOK("AT+BLEKEYBOARDCODE=00-00-06-00-00-00-00");
      ble.sendCommandCheckOK("AT+BLEKEYBOARDCODE=00-00");
      break;
    case 4:
      Serial.println("Button 1-5");
      ble.sendCommandCheckOK("AT+BLEKEYBOARDCODE=00-00-07-00-00-00-00");
      ble.sendCommandCheckOK("AT+BLEKEYBOARDCODE=00-00");
      break;
  }
}

Davon hast Du 5 - Wenn ich mit der Auflösung fertig bin, dann werden die 5 Funktionen wieder zusammengefasst und die Auswahl genau anders rum gelöst, damit die Codeduplikate entfallen.

Also alles machbar.
Ich bau weiter kleine Blöcke um zu verstehen, was Du da hast... Und dann wird Dir der Speicher auch reichen.

Entschuldige den WIP Code bitte.
Aber man sieht, daß du das Coden einfach kannst - Top!

Bezüglich Tasten, etc., ich hab folgendes:
5x Pushbuttons (Taster)
1x Joystick inkl. Taster (Mause-Klicks)
1x Taster (um den App-Wechsel für 1-2 Sekunden zu ermöglichen)

Ich bin gleich im Auto unterwegs, gebe dir aber für direktere Kommunikation gleich im PN meine WhatsApp-Nummer durch, für den Fall dass du Fragen hast (was für ´nen Schmarrn ich da wo gemacht bzw. mir gedacht hatte) :grimacing: :see_no_evil:

Kein WA.
Ich hab sowas nicht.
Es geht schon - las mich mal bauen, ich versteh schon, was Du da machen willst.
Such Dir morgen Nachmittag schon mal ne Stunde Zeit.