ISO C++ forbids comparison between pointer and integer

Hallo, liebe Community,

ich habe folgende Fehlermeldungen in meinem Programmcode:

C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino: In function 'void command()':
C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino:249:15: warning: comparison with string literal results in unspecified behavior [-Waddress]
  249 |       if(hash == "#") {                                           // Eingabe prüfen (Prüfzeichen)
      |          ~~~~~^~~~~~
C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino:249:15: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino:252:18: error: conversion from 'const char*' to 'int' in a converted constant expression
  252 |             case "s":   /* Messung Starten */
      |                  ^~~
C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino:252:18: error: could not convert '"s"' from 'const char [2]' to 'int'
  252 |             case "s":   /* Messung Starten */
      |                  ^~~
      |                  |
      |                  const char [2]
C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino:258:18: error: conversion from 'const char*' to 'int' in a converted constant expression
  258 |             case "b":   /* Messung Beenden */
      |                  ^~~
C:\Users\Azubi\Documents\Arduino\Send_And_Receive_URS_ADC_in_loop\Send_And_Receive_URS_ADC_in_loop.ino:258:18: error: could not convert '"b"' from 'const char [2]' to 'int'
  258 |             case "b":   /* Messung Beenden */
      |                  ^~~
      |                  |
      |                  const char [2]

exit status 1

Compilation error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

Leider stehe ich gerade richtig auf dem Schlauch, erst funktioniert es, dann schreibe ich weiteren Code und es funktioniert genau das nicht mehr was schon funktioniert hat.

void command(void) {
  if(SerialUSB.available() > 0) {

    String command = SerialUSB.readString();
    uint8_t size = sizeof(command);

    if(size == 4) {                                               // Prüfen ob Eingabe Richtige länge hat
      char hash = (char)command[0];                               // String Eingabe aufteilen in -> Prüfzeichen, Status(soll Messung starten oder beenden), Frequenz
      char status = (char)command[1];
      int freq = (char)command[2] + (char)command[3];
      if(hash == "#") {                                           // Eingabe prüfen (Prüfzeichen)
        if(freq >= 1 && freq <= 10) {                             // Eingabe prüfen (Frequenz)
          switch(status) {                                        // Eingabe prüfen (Status)
            case "s":   /* Messung Starten */
                        frequenz = (freq * 1000);
                        time = 1000000 / frequenz;                // Zeit in µs
                        start = true;
                        break;

            case "b":   /* Messung Beenden */
                        start = false;
                        break;

            default:    /* falsches Zeichen */
                        SerialUSB.print("e004");
                        break;
          }
        } else {
          /* Falsche frequenz */
          SerialUSB.print("e003");
        }
      } else {
        /* falsches Startzeichen */
        SerialUSB.print("e002");
      }
    } else {
      /* falsche Zeichenlänge */
      SerialUSB.print("e001");
    }
  } else {
    /* keine Daten im seriellen Buffer */
  }
}

Es geht im Grunde um die serielle Eingabe die als String ankommt.
Die einzelnen Zeichen werden gesplittet und char und int gewandelt.
Danach wird geprüft ob die Eingabewerte stimmen und Variablen gesetzt.

Die Variablen

uint32_t mytime;
bool start = false;
uint16_t frequenz;

sind globale Variablen.

Schon im voraus vielen lieben Dank für eure Hilfe!

Ein char kann nur mit char verglichen werden, also

      if(hash == '#') {                                           // Eingabe prüfen (Prüfzeichen)

weil "#" kein Zeichen sondern ein ganzer String ist.

das wird nicht gut gehen ...

Beachte auch, dass die ganzen Typecastings die du im Code hast im besten fall überflüssig sind, im schlimmsten Fall wird das Zeug compilieren aber nicht funktionieren.

ungetestet

void command(void)
{
  if (SerialUSB.available() > 0)
  {
    String command = SerialUSB.readString();
    uint8_t size = sizeof(command);
    if (size == 4)                                                // Prüfen ob Eingabe Richtige länge hat
    {
      char hash = (char)command[0];                               // String Eingabe aufteilen in -> Prüfzeichen, Status(soll Messung starten oder beenden), Frequenz
      char status = (char)command[1];
      int freq = byte(command[2]-'0')*10 + (byte(command[3]-'0');
//      if (hash == "#")                                            // ALT - Editiert:
      if (hash == '#')                                            // Eingabe prüfen (Prüfzeichen)
        {
        if (freq >= 1 && freq <= 10)                              // Eingabe prüfen (Frequenz)
        {
          switch (status)                                         // Eingabe prüfen (Status)
          {
            case 's':   /* Messung Starten */
              frequenz = (freq * 1000);
              time = 1000000 / frequenz;                // Zeit in µs
              start = true;
              break;
            case 'b':   /* Messung Beenden */
              start = false;
              break;
            default:    /* falsches Zeichen */
              SerialUSB.print("e004");
              break;
          }
        }
        else
        {
          /* Falsche frequenz */
          SerialUSB.print("e003");
        }
      }
      else
      {
        /* falsches Startzeichen */
        SerialUSB.print("e002");
      }
    }
    else
    {
      /* falsche Zeichenlänge */
      SerialUSB.print("e001");
    }
  }
  else
  {
    /* keine Daten im seriellen Buffer */
  }
}

Merge #2

1 Like

Und #3
2 + 3 = 4
Ich wollte schon immer mal eine falsche Gleichung aufstellen :grin:

Du redest in Rätseln. #2 fehlt in #4, #3 nicht.

Ich rechne das zusammen, was zusammen gehört.
Ach jetzt seh ichs - das '#' ist liegen geblieben :man_facepalming:

Hallo,

@ TO:

Du vermischt String und char Array. Das klappt nur fehlerfrei bei ganz bestimmten Dingen. Ansonsten stellt die Stringklasse viele Funktionen bereit, auch für Konvertierungen. Du solltest dich besser entscheiden. Entweder komplett mit Strings zu arbeiten oder komplett mit char Array.

Das was du hier beabsichtigst funktioniert so auch nicht.
int freq = (char)command[2] + (char)command[3];
Du gibts bspw. 72 ein. Dann wird 7 und 2 addiert zu 9 und nicht die Einzelindex zu 72. Dafür müßt die Zehnerstelle mit 10 multipliziert werden.

Das große Problem ist jedoch das String command jedesmal bei Aufruf der Funktion command() neu angelegt wird. Da bleibt nichts erhalten beim loop Durchlauf, weil lokal.

Meine Meinung.
Da du am Ende nur auf einzelne Zeichen vergleichst, baue alles auf char Array auf. Schreibe eine Leseroutine die erst mit \r und oder \n beendet wird oder vorher wenn die Bufferlänge/Arraygröße erreicht ist, bevor sie anschließend ausgewertet wird. Dann kannst du dir meinetwegen anschließend jeden Index einzeln zur Brust nehmen.

Ok, vielen lieben dank schon mal.

Hab jetzt schonmal gecheckt das ein char wie ein Int behandelt wird in der switch.

Wenn ich das in einem char Array speicher, wie lese ich dann am besten ein?
Weiter als SerialUSB.readString() oder ...read() oder ...readByte()?

Ich kann nebenbei kein delay() einbauen wie in vielen anderen Beispielen, das dauert viel zu lange!

'String command' darf nach einmaligem ausführen wieder neu angelegt werden. Das passiert ja dann nur, wenn die Messung wieder beendet wird.

Ich bin mir eh noch nicht ganz sicher, ob ich ein Kommandobereich zur Einstellung der Messparameter verwenden soll und ein Kommandobereich zum starten/beenden der Messung.
Ich glaube für die Zukunft machte es Sinn das zu separieren, so kann man zum Beispiel zwischen diverse Filtermöglichkeiten wechseln oder die Anzahl an Messungen in einem bestimmten Zeitraum ändern.

Hallo,

du musst erstmal deinen hoffentlich eigenen Code verstehen.
Was läuft hier mit jeden Aufruf von command() ab?

Sobald irgendein Zeichen im Buffer zur Verfügung liegt wird String command neu angelegt. Deswegen werden nie bis zu 4 Zeichen drin stehen die du erwartest. Lasse dir einmal nach readString() den Inhalt von command ausgeben. Also klassisch debuggen.

delay() verbietet sich von selbst wenn man immer bereit sein muss zum Einlesen. Brauchst du auch nicht.

Da Du ein "Startbyte" hast, lies einfach mit .read() ein, bis Du auf ein Control-Zeichen kommst.
sample - nicht funktinsfähig.

{
  myByte = Serial.read();
  if (myByte == '#')
  { idx = 0; }
  else if (isControl(myByte))
  {
    machwas();
  }
  else
  {
    zeichenkette[idx]=myByte;
    idx++;
  }
}

Dann gehen auch solche Sachen wie atoi() für Deinen zweistelligen Wert usw.
Theoretisch kannst Deine Variablen auch "onTheFly" schon während des Empfangs füllen, da Du ja nur 1 Zeichen und die Zahlenkombi bekommst.

Hallo,

ist das nicht etwas gefährlich in der Behandlung bzw. Auswertung?
Das könnte am Ende sehr verschachtelt werden, wenn immer einzelne Zeichen ausgewertet werden um das nächste Zeichen der Eingabe auszuwerten. Es erschwert auch die weitere Verarbeitung der Eingabe.

Ich sehe auch die Gefahr bei Fehleingaben mitten im "String". Dann hängt die Auswertung mittendrin fest und kommt nicht mehr raus.

Ich lese immer alles ein bis zum erkannten Endezeichen \r und/oder \n . Danach wird ausgewertet oder vorher alles verworfen.

serial-input-basics

Im deutschen Teil gibt es viele Threads von Serenifly zum Thema.
Das Grundgerüst ist immer gleich.

Wieso sollte?
Ich starte mit dem Startzeichen und ende genau so wie Du mit einenm \r oder/und \n

Hallo,

dafür ist dein Sample zu kurz. Ich sehe keine Abschlussprüfung auf \r oder \n.

Doch hier:

Und es sollte nur ein Anstoss sein. Ich habs extra dazu geschrieben, Unter anderem weil idx größer werden kann als _size des nicht aufgeführten CharArray.

Ich verstehe eure Diskussion nicht so ganz.. Der Original-Code ist fast perfekt. Verbessert so:

Hallo,

okay, die Methode kannte ich noch nicht. Man sollte dazu wissen das alle ASCII Zeichen unterhalb 32 gültig sind.

Weil der TO das erwähnte Problem bspw. mit der lokalen Variablen wie beschrieben noch nicht verstanden hat. Außerdem springe ich ungern von einem zu anderen ohne das erste Problem aufzuzeigen. Man kann hier sicherlich Hunderte Lösungen anbieten, deswegen weiß der TO aber noch nicht was an seinem Code das Problem ist. Ich halte mich mal raus.

Also wenn ich das teste,

if(SerialUSB.available() > 0) {
  if(test == true) {
    String command = SerialUSB.readString();
    SerialUSB.println(command);
    test = false;
  } 
}
bool test = true;        // Globale variable

,dann kommt bei der Eingabe von "Hallo" auch "Hallo" auf dem Seriellen Monitor an.
Es sind also alle 5 Zeichen in dem String command gespeichert die ich erwarte.

print(command) kann ja nur einmal in der loop ausgeführt werden in diesem Beispiel.

Dennoch habe ich jetzt mal das char Array ausprobiert.

#include <USBSerial.h>

char buffer[4];
int8_t length = 4;

void setup() {
  // put your setup code here, to run once:
  SerialUSB.begin();

}

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

void command(void) {
  
  if(SerialUSB.available() > 0) {
    int8_t anzahlZeichen = Serial.readBytes(buffer, length);

    for (int i = 0; i < anzahlZeichen; i++) {
      SerialUSB.print(buffer[i]);
    }
  } 
}

Das Scheint soweit zu klappen, jetzt muss ich noch testen ob das auch in meinem Programm funktioniert.

Das von dir [my_xy_projekt] scheint ähnlich zu sein, wie das was auch unter dem Link den [Doc_Arduino] geteilt hat steht.

Das werde ich mir mal durchlesen und austesten.

Vielen lieben dank euch drei Doc_Arduino, my-xy-projekt und Dr.Diettrich.

Auch deinen Code Dr.Diettrich werde ich mal testen.
Ich werde die verschieden Codes alle mit dem Oszi testen und mal schauen was schneller ist.

Ich bin euch sehr dankbar, ihr habt mir damit sehr geholfen und ich konnte mein Verständnis für die Probleme die mit der Anwendung einer solchen Ansteuerung einhergehen erweitern.

PS.: Ich verwende einen BlackPill und hab eine Library Namens <UrsSTM32F411-fast-ADC.h>. Die speichert die Werte gleich im DMA-Register und ist somit rasend schnell in der Auswertung, da kein analogRead() verwendet werden muss. Eine Wandlung dauert nur etwa 2µs. Genug Zeit für mehrere Messungen, filtern der Werte und Ausgabe bei bis zu 20kHz.