Uno: warning: comparison between signed and unsigned integer expressions - weg

Hi
bekomme die Warnung nicht mehr - Näheres steht unten drunter

Momentan bekomme ich eine Warnung, sehe aber nicht, wo der Kompiler Da ein signed drin findet.
Arduino Uno (Klon) - die LEDs blinken schön asyncron zueinander.
Wer noch einen Link zu ‘normalen’ Blinkmustern hat, gerne gesehen!

Der Code (soll später 4 LED-Streifen an einem E-Quad, Kinderspielzeug, an den 4 Fahrzeug-Ecken, blinken lassen)

//Pins, an Denen die LEDs hängen (später die FETs für die 12V LED-Streifen, wasserdicht)
const byte ledpin1 = 4;
const byte ledpin2 = 5;
const byte ledpin3 = 6;
const byte ledpin4 = 7;

//Blinkmuster Anzahl AN-Zeit AUS-Zeit
uint16_t blink1[] = {
  3, 5, 80,
  1, 10, 503,
  3, 5, 80,
  1, 10, 500,
  3, 5, 80,
  1, 10, 500,
  2, 100, 200,
  1, 100, 500,
};

uint16_t blink2[] = {
  5, 5, 91,
  1, 10, 590,
  2, 100, 200,
  1, 100, 500,
};

uint16_t blink3[] = {
  2, 5, 90,
  1, 10, 590,
  2, 5, 90,
  1, 10, 590,
  1, 10, 597,
  2, 100, 200,
  1, 100, 500,
};

uint16_t blink4[] = {
  3, 5, 90,
  1, 10, 190,
  1, 10, 590,
  2, 100, 200,
  1, 100, 500,
};

struct {
  byte _pin;  //Pin-Nummer der LED
  byte _schritt;  //Schritt der Blink-Sequenz
  byte _muster;   //Muster-Nummer in der Blink-Sequenz
  uint32_t nextset; //wann ist der aktuelle Schritt abgelaufen?
  const byte _maxSequenz;   //Anzahl der vorhandenen Sequenzen
  const uint16_t* blinkarray; //Adresse der Blinkfolge
} led[] {
  {ledpin1, 0, 0, 0, sizeof(blink1) / sizeof(blink1[0]) / 3, blink1}, //3 Elemente pro Blink-Zyklus
  {ledpin2, 0, 0, 0, sizeof(blink2) / sizeof(blink2[0]) / 3, blink2},
  {ledpin3, 0, 0, 0, sizeof(blink3) / sizeof(blink3[0]) / 3, blink3},
  {ledpin4, 0, 0, 0, sizeof(blink4) / sizeof(blink4[0]) / 3, blink4},
};

void setup() {
  Serial.begin(9600);
  Serial.println("Start");

  for (auto &element : led)           //ohne das & können die Werte nicht im Struct geändert werden
  { //da mit Kopien geschafft wird - mit & wird per Referenz auf das Struct
    Serial.print("Ausgangspin ");     //zugegriffen
    Serial.println(element._pin);
    Serial.print("Sequenzen ");
    Serial.println(element._maxSequenz);

    pinMode(element._pin, OUTPUT);    //Pin auf Ausgang
    digitalWrite(element._pin, HIGH); //und einschalten
    element.nextset = millis() + element.blinkarray[1];   //Endzeit des ersten Hell-Impuls
    Serial.print("Endzeit:");
    Serial.println(element.nextset);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  byte anz = 0;
  for (auto &element : led)
  {
    anz++;
    //hier prüfen, ob die Laufzeit des aktuellen Schritt abgelaufen ist
    if (millis() >= element.nextset) {                    //Es ist unwahrscheinlich, daß die Schaltung >47 Tage an Stück läuft
      byte schritt = element._schritt;                    //da das angedachte Ziel, ein E-Quad, wohl nur für 30 Min Saft hat
      byte muster = element._muster;
      digitalWrite(element._pin, schritt & 0x01); //unterste Bit von Schritt bestimmt, ob AN oder AUS geschaltet wird
      //element._schritt Anzahl der Durchläufe
      //element.muster Anzahl der verschiedenen Blink-Rythmen
      schritt ++;
      if (schritt >> 1 >= element.blinkarray[muster * 3]) {       //< -- wirft die Warnung
        //Blink-Sequenz oft genug wiederholt
        muster++;   //nächste Muster
        schritt = 0; //Wiederholungen auf 0 zurück setzen
        if (muster >= element._maxSequenz) {
          muster = 0; //von Vorne anfangen
        }
        element._muster = muster;
      }
      element._schritt = schritt;
      element.nextset = millis() + element.blinkarray[muster * 3 + (schritt % 2) + 1];
      //.muster * 3 + .schritt + 1 = nächste Laufzeit
      //.muster * 3 = Anzahl an Wiederholungen
    }
  }
}

Die Fehlermeldung:

C:\Users\postmaster-ino\AppData\Local\Temp\arduino_modified_sketch_187355\4xBlinker_Quad.ino: In function 'void loop()':

C:\Users\postmaster-ino\AppData\Local\Temp\arduino_modified_sketch_187355\4xBlinker_Quad.ino:92:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       if (schritt>>1 >= element.blinkarray[muster*3]){
                      ^

Sowohl schritt ist undigned wie auch die Werte in dem Array.
Hätte jetzt eher mit 16<->32 gerechnet, da ich die Werte für Laufzeiten benutze und millis() 32 Bit lang ist.

Und weg ist die Warnung
Ich habe NUR den Datentyp von byte schritt=0; auf uint32_t geändert (16 klappt auch).
Warum bekomme ich bei Byte (oder uint8_t) eine Warnung und drüber (16 oder 32 Bit, ebenfalls unsigned) nicht mehr?
Geändert hatte ich Das, weil ich sonst bei 127 Blitzen ‘am Stück’ begrenzt bin (und Speicherplatz derzeit keine Rolle spielt).
Mit uint16_t wäre die Grenze 32767 Blitze ‘am Stück’ oder pro Zeile im Array - Das sollte aber reichen.

Also: Die Warnung ist weg - nur warum kommt Sie beim Typ byte/uint8_t?

MfG

Dein ursprüngliches Schritt >>1 wird als int ausgeführt.

Gruß Tommy

Eigentlich ganz einfach…

Erstmal reduziere ich den Code auf ein minimal Beispiel:

void setup() 
{
  Serial.begin(9600);
  Serial.println("Start");

  int a = 1;
  unsigned int b = 1; 
  if (a  >= b ){}
}
void loop() 
{
}

Das entspricht genau deinem Problem!

Momentan bekomme ich eine Warnung, sehe aber nicht, wo der Kompiler Da ein signed drin findet.

In meinem Beispiel ist das klar, mein a ist mit Vorzeichen.

Aber bei dir wird schritt >> 1 zu einem int…
Zum Beweis dessen:

using TestType = decltype(byte(32)>>1);
Irgendwo unter bringen, es meldet dann:

warning: typedef 'using TestType = int' locally defined but not used [-Wunused-local-typedefs]
   10 |   using TestType = decltype(byte(32)>>1);
      |         ^~~~~~~~

Klar, unused…
Aber wichtiger 'using TestType = int’

Merksatz:
Schiebeoperatoren nehmen bei AVRs nur Operanden in 16 Bit Abstufungen!
Darum wird dein Byte implizit zum int gecasted, und dann erst geschoben.
Dieser Cast wird vom Standard so gefordert.

Der darauf folgende Vergleich liefert dann deine Warnung.

Abhilfe:

  byte a = 1;
  unsigned int b = 1; 
  if (static_cast<uint16_t>(a) >> 1  >= b ){}

Hi

Besten Dank - wieder was gelernt.
Dann wird die Warnung nicht geworfen beim 16-bit Versuch, weil >> diese 16bit 'wie sie sind' nutzen kann - bei 32 wird's wohl auf 2x 16 hinauslaufen.

Ok, nun muß ich mir Das nur merken :wink:

MfG

Bei 32 bleibt es 32.

Gruß Tommy

Hey, heute ist ja ein sehr lehrreicher Tag zum Thema "Bit-Schupfen"*. :slight_smile:
Besten Dank!


*) Schupfen: österreichisch für "Schieben oder Werfen"

postmaster-ino:

  • bei 32 wird's wohl auf 2x 16 hinauslaufen.

Nee, habe mich oben wohl unklar ausgedrückt.
Schon korrigiert.....
Schieben geht in 16, 32 und 64 Bit.

Hi

Ok, Doppel-Missverständnis :wink:
Komme ja aus der Richtung ASM, bitweises Schieben ist mir somit schon Mal unter gekommen.
Ich meinte damit, daß Dann wohl zwei (vier) 16-Bit ‘Container’ (… Platz) nebeneinander gestellt werden, um die Grundzahl darin einzukopieren und dort dann x Mal zu shiften.
Rotiere Carry Links - RCL sollte der passende Befehl gewesen sein.

Fehlerquelle: Zum Schieben/Shiften werden MINDESTENS 16 Bit benötigt, wenn der Typ nicht passt, wird ein int draus, Das ist signed und Da kommt dann der Vergleich signed<->unsigned her.

So - Genug Klarheiten für Heute beseitigt :wink:

Danke Euch und MfG