switch case läuft immer durch!

Hallo, ich habe eine Ganganzeige mit einem Poti gebastelt.

Ich verwende einen Arduino UNO und ein 2,4" TFT Display.

In meinem Programm blinkt der Text im Display immer auf weil alles immer in der schleife liegt. Wie kann ich das umgehen?

Es soll immer zum Gangwechsel das Display erst frei gemacht werden da sich sonst di zahlen überlappen.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

const int sensoreCambio = A5;   // Sonsor-PIN
int valoreSensore = 0;          // Sensor inizialisieren
byte state = 0;                 // Zustände

void drawpete(void) {
  tft.setCursor(20, 280);
  tft.setTextColor(WHITE);  tft.setTextSize(2);
  tft.println("Sviluppato da:");
  tft.setCursor(20, 300);
  tft.println("Pietro Manzella");
}

void problem(void) {
  tft.setCursor(38, 150);
  tft.setTextColor(WHITE);  tft.setTextSize(4);
  tft.println("ASSENZA");
  tft.setCursor(38, 200);
  tft.println("SEGNALE");
}

void drawr(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("R");
}
void drawn(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("N");
}

void draw1(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("1");
}

void draw2(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("2");
}

void draw3(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("3");
}

void draw4(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("4");
}

void draw5(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("5");
}

void draw6(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("6");
}

void setup(void) {

  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(2);
  tft.fillScreen(RED);
  drawpete();
  delay(2000);
  tft.fillScreen(RED);
}

  void loop() {
  // liest den Sensor
  valoreSensore = analogRead(sensoreCambio);

switch (state)
  {
  case 0:  // ASSENZA SEGNALE
    if ( valoreSensore  <= 700) { 
    problem();
    }
  break;

  case 1:
    if ( valoreSensore >= 807 && valoreSensore <= 813) { //R
    drawr();
    }
  break;

  case 2:
    if ( valoreSensore >= 820 && valoreSensore <= 826) { //N
    drawn();
    }
  break;  

  case 3:
    if ( valoreSensore >= 833 && valoreSensore <= 839) { //1
    draw1();
    }
  break;

  case 4:
    if ( valoreSensore >= 846 && valoreSensore <= 852) { //2
    draw2();
    }
  break;

  case 5:
    if ( valoreSensore >= 858 && valoreSensore <= 864) { //3
    draw3();
    }
  break;

  case 6:
    if ( valoreSensore >= 871 && valoreSensore <= 877) { //4
    draw4();
    }
  break;

  case 7:
    if ( valoreSensore >= 884 && valoreSensore <= 890) { //5
    draw5();
    }
  break;

  case 8:
    if ( valoreSensore >= 896 && valoreSensore <= 902) { //6
    draw6();
    }
  break;
  }
}

Vielen Dank!

Einfach nur dann das Display neu beschreiben, wenn sich der Gang ändert. Also in einer Variable den Gang merken und vergleichen.

Kann ich das mit "Do - While" lösen?
Wenn ja, wie?

Du solltest den Sinn der loop() verstehen.

Die kommt immer wieder ( so schnell wie möglich ) dran, und sollte meistens feststellen, dass nichts zu tun ist und sich beenden. Kommt dann natürlich sofort wieder dran, aber das ist ja der Sinn der Sache.

Wenn sich selten mal ein Zustand ändert, wird das LCD beschrieben und fertig.

Schleifen innerhalb von loop sind in aller Regel falsch.

Wie sollte ich das dann lösen?

Sinnvoll wäre es, mit dem Poti zuerst eine Mittelwertbildung durchzuführen, um ggf. falsche Werte auszufiltern. Falls es derzeit passt, liegt das nur daran, dass die Werte so schnell wieder überschrieben werden.

Ansonsten wegen dem Display

static int lastState;

if(val > 800 && val <= 810) state = 1;
....

if(lastState != state) {
lastState = state;
case 1:
do();
break;
...
}

Ist das so korrekt?

Vielen Dank!

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

const int sensoreCambio = A5;   // Sonsor-PIN
int valoreSensore = 0;          // Sensor inizialisieren
byte state = 0;                 // Zustände
static int lastState;

void drawpete(void) {
  tft.fillScreen(RED);
  tft.setCursor(20, 100);
  tft.setTextColor(WHITE);  tft.setTextSize(1);
  tft.println("Sviluppato da:");
  tft.setCursor(20, 120);
  tft.println("Pietro Manzella");
  tft.setCursor(20, 200);
  tft.setTextColor(WHITE);  tft.setTextSize(2);
  tft.println("per");
  tft.setCursor(20, 220);
  tft.println("ELABORAZIONI");
  tft.setCursor(20, 240);
  tft.setTextColor(WHITE);  tft.setTextSize(3);
  tft.println("LA MANNA");
}

void problem(void) {
  tft.fillScreen(RED);
  tft.setCursor(38, 150);
  tft.setTextColor(WHITE);  tft.setTextSize(4);
  tft.println("ASSENZA");
  tft.setCursor(38, 200);
  tft.println("SEGNALE");
}

void drawr(void) {
  tft.fillScreen(RED);
  tft.setCursor(20, 20);
  tft.setTextColor(WHITE);  tft.setTextSize(40);
  tft.println("R");
}
void drawn(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("N");
}

void draw1(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("1");
}

void draw2(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("2");
}

void draw3(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("3");
}

void draw4(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("4");
}

void draw5(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("5");
}

void draw6(void) {
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  tft.setTextSize(40);
  tft.println("6");
}

void setup(void) {

  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(0);
  tft.fillScreen(RED);
  drawpete();
  delay(2000);
  tft.fillScreen(RED);
}

  void loop() {
  // liest den Sensor
  valoreSensore = analogRead(sensoreCambio);

  if(valoreSensore  <= 700) state = 0; // Kein Signal
  if(valoreSensore >= 807 && valoreSensore <= 813) state = 1; // R
  if(valoreSensore >= 820 && valoreSensore <= 826) state = 2; // N
  if(valoreSensore >= 833 && valoreSensore <= 839) state = 3; // 1
  if(valoreSensore >= 846 && valoreSensore <= 852) state = 4; // 2
  if(valoreSensore >= 858 && valoreSensore <= 864) state = 5; // 3
  if(valoreSensore >= 871 && valoreSensore <= 877) state = 6; // 4
  if(valoreSensore >= 884 && valoreSensore <= 890) state = 7; // 5
  if(valoreSensore >= 896 && valoreSensore <= 902) state = 8; // 6

  if(lastState != state) {
lastState = state;
    
switch (state)
  {
  case 0:  // Kein Signal
     problem();
  break;

  case 1:   // R
    drawr();
  break;

  case 2:   // N
     drawn();
  break;  

  case 3:   // 1. Gang
    draw1();
  break;

  case 4:   // 2. Gang
    draw2();
  break;

  case 5:   // 3. Gang
    draw3();
  break;

  case 6:   // 4. Gang
    draw4();
  break;

  case 7:   // 5. Gang
    draw5();
  break;

  case 8:   // 6. Gang
    draw6();
  break;
  }
  }
}

Wenn du lastState in den GLOBAL VARS nutzt, braucht es kein static. Ansonsten sieht das ganze besser aus als vorher.

Was könnte ich denn verbessern?

Was sollen diese ganzen Funktionen die alle das gleiche machen? Du kannst doch den Text als Parameter übergeben:

void drawText(const char* str)
{
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  
  tft.setTextSize(40);
  tft.print(str);
}

Oder da es sowieso nur ein Zeichen ist:

void drawChar(char c)
{
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  
  tft.setTextSize(40);
  tft.print(c);
}

Und dann nur mit drawChar('1') aufrufen. Bei der ersten Version kann man auch mehr als ein Zeichen ausgeben, z.B. drawText("Test")

Hab das ganze jetzt mal praktisch getestet. Die Gänge laufen aber immer durch. Das Display zeigt völlig wirre Zahlenfolgen an obwohl ich per "serialmonitor" für alle Gänge die Werte bestimmt habe und auch wie man sieht Toleranzen eingebaut habe.

Du hast Definitionslücken:

z.B.:

if (valoreSensore >= 807 && valoreSensore <= 813) state = 1; // R
if (valoreSensore >= 820 && valoreSensore <= 826) state = 2; // N

Was passiert bei valoreSensore == 817?

Ich würde valoreSensore am Anfang erstmal auf einen Defaultwert setzen, und dann, falls ein gültiger Wert kommt, den Wert ändern:

valoreSensore  = 99;   // defaultwert.
 if (valoreSensore  <= 700) state = 0; // Kein Signal
 if (valoreSensore >= 807 && valoreSensore <= 813) state = 1; // R
 if (valoreSensore >= 820 && valoreSensore <= 826) state = 2; // N

...

Und zum Ende deiner switch case Anweisung diesen Zustand abfangen:

default:
  // fa niente

zum Durchlaufen:
lass dir doch mal alle gelesenen Werte anzeigen:

valoreSensore = analogRead(sensoreCambio);
 Serial.println(valoreSensore);

ob hier wirklich sinnvolle Werte ankommen.
Wie hast du das Poti angeschlossen? Mit RC-Glied zum filtern?

@ guntherb: Ich habe einen 10kOhm in Reihe und 22µF + 100nF Parallel auf GND am Eingang.

Wieso bleibt nach dem Einschalten jetzt das Display immer am letzten "tft.fillScreen(RED);" aus dem loop hängen wenn kein Sensor angeschlossen ist?
Sollte da nicht "state 0" ausgeführt werden?

Ich habe eure Ratschläge befolgt und nun sieht der code so aus:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

const int sensorGetriebe = A5;   // Sonsor-PIN
int sensorWert = 0;          // Sensor inizialisieren
byte state = 0;                 // Zustände
int lastState = 0;

void drawpete(void) {
  tft.fillScreen(RED);
  tft.setCursor(20, 100);
  tft.setTextColor(WHITE);  tft.setTextSize(1);
  tft.println("Sviluppato da:");
  tft.setCursor(20, 120);
  tft.println("Pietro Manzella");
  tft.setCursor(20, 200);
  tft.setTextColor(WHITE);  tft.setTextSize(2);
  tft.println("per");
  tft.setCursor(20, 220);
  tft.println("ELABORAZIONI");
  tft.setCursor(20, 240);
  tft.setTextColor(WHITE);  tft.setTextSize(3);
  tft.println("LA MANNA");
}

void problem(void) {
  tft.fillScreen(RED);
  tft.setCursor(38, 150);
  tft.setTextColor(WHITE);  tft.setTextSize(4);
  tft.println("ASSENZA");
  tft.setCursor(38, 200);
  tft.println("SEGNALE");
}

void drawChar(char c)
{
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  
  tft.setTextSize(40);
  tft.print(c);
}

void setup(void) {

  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(0);
  tft.fillScreen(RED);
  drawpete();
  delay(2000);
  tft.fillScreen(RED);
}

  void loop() {
 
   // liest den Sensor
   long sensorSumme=0;
  #define SAMPLES 200
  for (int i=0; i<SAMPLES; i++) // Signal mehrmals messen, ca. 20 Millisekunden lang
  {
    sensorSumme+=analogRead(sensorGetriebe);
  }
  int sensorWert = sensorSumme/SAMPLES; // Mittelwert bilden
    
  if(sensorWert <= 806) state = 0; // Kein brauchbares Signal
  if(sensorWert >= 807 && sensorWert <= 819) state = 1; // R
  if(sensorWert >= 820 && sensorWert <= 832) state = 2; // N
  if(sensorWert >= 833 && sensorWert <= 845) state = 3; // 1
  if(sensorWert >= 846 && sensorWert <= 857) state = 4; // 2
  if(sensorWert >= 858 && sensorWert <= 870) state = 5; // 3
  if(sensorWert >= 871 && sensorWert <= 883) state = 6; // 4
  if(sensorWert >= 884 && sensorWert <= 895) state = 7; // 5
  if(sensorWert >= 896 && sensorWert <= 902) state = 8; // 6
  if(sensorWert >= 903) state = 0; // Kein brauchbares Signal

  if(lastState != state) {
lastState = state;
    
switch (state)
  {
  case 0:  // Kein Signal
     problem();
  break;

  case 1:   // R
    drawChar('R');
  break;

  case 2:   // N
    drawChar('N');
  break;  

  case 3:   // 1. Gang
    drawChar('1');
  break;

  case 4:   // 2. Gang
    drawChar('2');
  break;

  case 5:   // 3. Gang
    drawChar('3');
  break;

  case 6:   // 4. Gang
    drawChar('4');
  break;

  case 7:   // 5. Gang
   drawChar('5');
  break;

  case 8:   // 6. Gang
   drawChar('6');
  break;

  default:
  problem();
  }
  }
}

Da das Getriebe unheimlich vibriert springt die anzeige manchmal zwischen zwei Gängen hin und her. Wie kann ich das programmiertechnisch beseitigen?

//25.08.2015
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

const int sensorGetriebe = A5;   // Sonsor-PIN
int sensorWert = 0;          // Sensor inizialisieren
byte state = 0;                 // Zustände
int lastState = 0;

void problem(void) {
  tft.fillScreen(RED);
  tft.setCursor(38, 150);
  tft.setTextColor(WHITE);  tft.setTextSize(4);
  tft.println("NO");
  tft.setCursor(38, 200);
  tft.println("SIGNAL");
}

void drawChar(char c)
{
  tft.fillScreen(WHITE);
  tft.setCursor(20, 20);
  tft.setTextColor(RED);  
  tft.setTextSize(40);
  tft.print(c);
}

void setup(void) {
  
  Serial.begin(9600);
  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(0);
  tft.fillScreen(RED);
 }

  void loop() {
 
   // liest den Sensor
   long sensorSumme=0;
  #define SAMPLES 200
  for (int i=0; i<SAMPLES; i++) // Signal mehrmals messen, ca. 20 Millisekunden lang
  {
    sensorSumme+=analogRead(sensorGetriebe);
  }
  int sensorWert = sensorSumme/SAMPLES; // Mittelwert bilden
   Serial.println(sensorWert);

    
  if(sensorWert <= 806) state = 0; // Kein brauchbares Signal
  if(sensorWert >= 807 && sensorWert <= 819) state = 1; // R
  if(sensorWert >= 820 && sensorWert <= 832) state = 2; // N
  if(sensorWert >= 833 && sensorWert <= 845) state = 3; // 1
  if(sensorWert >= 846 && sensorWert <= 857) state = 4; // 2
  if(sensorWert >= 858 && sensorWert <= 870) state = 5; // 3
  if(sensorWert >= 871 && sensorWert <= 883) state = 6; // 4
  if(sensorWert >= 884 && sensorWert <= 895) state = 7; // 5
  if(sensorWert >= 896 && sensorWert <= 902) state = 8; // 6
  if(sensorWert >= 903) state = 0; // Kein brauchbares Signal

  if(lastState != state) {
  lastState = state;
    
      switch (state)
      {
      case 0:  // Kein Signal
         problem();
      break;
      
      case 1:   // R
        drawChar('R');
      break;
      
      case 2:   // N
        drawChar('N');
      break;  
      
      case 3:   // 1. Gang
        drawChar('1');
      break;
      
      case 4:   // 2. Gang
        drawChar('2');
      break;
      
      case 5:   // 3. Gang
        drawChar('3');
      break;
      
      case 6:   // 4. Gang
        drawChar('4');
      break;
      
      case 7:   // 5. Gang
       drawChar('5');
      break;
      
      case 8:   // 6. Gang
       drawChar('6');
      break;
      
      default:
      problem();
      }
  }
}

michael_x:
Schleifen innerhalb von loop sind in aller Regel falsch.

Diese Satz allerdings auch.

Gruß

Gregor

gregorss:
Diese Satz allerdings auch.

Dieser Satz ist falsch.
Der Vorhergehende nicht.

wie hast du das technisch beziehungsweise mechanisch gelöst?

Ich nehme an, es handelt sich um ein Motorrad mit Fusschaltung.

combie:
Dieser Satz ist falsch.
Der Vorhergehende nicht.

Ich nehme an, dass Du damit nicht meinen Tippfehler meinst, sondern dass wir „in aller Regel falsch“ unterschiedlich interpretieren.

Oder bist Du allen Ernstes der Meinung, dass man z. B. ein kleines Lauflicht ohne Schleife in loop() realisieren sollte?!

Gruß

Gregor

gregorss:
Ich nehme an, dass Du damit nicht meinen Tippfehler meinst, sondern dass wir „in aller Regel falsch“ unterschiedlich interpretieren.

Oder bist Du allen Ernstes der Meinung, dass man z. B. ein kleines Lauflicht ohne Schleife in loop() realisieren sollte?!

Ja, ich denke, dass Schleifen in loop() "unanständig" sind.
Ja, eine einzige lang laufende Schleife ist nötig!
Und die steckt in main() und ruft loop() auf.
Das reicht an langlaufenden Schleifen.

Spätestens wenn man einen WDT einsetzt ist sowieso Schluss damit!

Kurze, begrenzte, Schleifen, sind nicht das Problem.....

combie:
Ja, ich denke, dass Schleifen in loop() "unanständig" sind.
Ja, eine einzige lang laufende Schleife ist nötig!
Und die steckt in main() und ruft loop() auf.
Das reicht an langlaufenden Schleifen.
Spätestens wenn man einen WDT einsetzt ist sowieso Schluss damit!
Kurze, begrenzte, Schleifen, sind nicht das Problem.....

Dem kann ich problemlos zustimmen. Nur weiß ich nicht, was Du mit WDT meinst. Etwas Unanständiges wird’s nicht sein :slight_smile:

Gruß

Gregor