Something is wrong with Serial and larger data types

So...

This has been bugging me (hah) for a WHILE.
And it has been super annoying to deal with.

I am using an ATTiny 1627, Arduino IDE 2.0 rc9 (this happens across various RCs), the latest megaTinyCore 2.5.11.
I have no idea if the issue is with Arduino IDE, megaTinyCore, or somewhere else.

I used to encounter issues like that as well still using Arduinos, so I assume it is not megaTinyCore, or the bug is copied over if it is used in the same serial stuff.

Bug:
If you use the serial output with anything beyond 16 bits, you're in for a treat.

Mind you, "value" and "data" are being declared earlier in the code as an "unsigned long" (32 bits).

#ifdef DEBUG
    Serial.println(data, BIN);
    Serial.flush();
    //Output: 11111111111111111100000100100101
    
    for(int i = 31; i >= 0; i--)
    {
      if(bytesRaw[i])
      {
        Serial.print("1");
      }
      else
      {
        Serial.print("0");
      }
    }

    Serial.println();
    Serial.flush();
    //Output: 00000000000100101100000100100101
#endif

How the variables are populated:

  bool bit = analogRead(PINCALDATA) > 50;

  [...]

  if(bit)
  {
    value |= (1 << bytePos);
  }

  bytesRaw[bytePos] = bit;

  bytePos++;

  if(bytePos == 24)
  {
      data = value;
      value = 0;
      bytePos = 0;
      [Resetting stuff etc...]

I have zero idea what is going on here. But you can imagine my surprise trying to debug a piece of code where bits are set to 1 which I am actually not setting in the code (as my bytePos limit is at 24).
Yes, value is reset to "0" during that reset phase.

I have had this with other code snippets doing similar things.
The serial output will just screw me over, and I don't know why.

Again, zero idea what is going on here, but I am merely leaving this here in case someone has the same issue, starts to question his or her sanity, and then stumbles upon this.

That said, I have no idea where this topic is best put. So please move this however you see fit.

what do you think is the type of 1 in (1 << bytePos)?

āžœ it's an int, so signed and on a UNO or similar would be 16 bits only and will go negative and your binary OR will do stupid things
āžœ try with 1ul if value is an unsigned long (or 1ull if you want 64 bits but print can't print that)

try this code if you want to convince yourself of what's going on:

void setup() {
  uint32_t value;
  Serial.begin(115200);

  Serial.println("GARBAGE BECAUSE OF MISMATCH IN TYPES AND SIZE");
  value = 0;
  for (byte bitPos = 0; bitPos < 24; bitPos++) {
    value |= (1 << bitPos);
    Serial.print(bitPos); Serial.write('\t'); Serial.println(value, BIN);
  }

  Serial.println("\n\nDONE THE RIGHT WAY");
  value = 0;
  for (byte bitPos = 0; bitPos < 24; bitPos++) {
    value |= (1ul << bitPos);
    Serial.print(bitPos); Serial.write('\t'); Serial.println(value, BIN);
  }
}

void loop() {}

Serial Monitor (@ 115200 bauds) will show

GARBAGE BECAUSE OF MISMATCH IN TYPES AND SIZE
0	1
1	11
2	111
3	1111
4	11111
5	111111
6	1111111
7	11111111
8	111111111
9	1111111111
10	11111111111
11	111111111111
12	1111111111111
13	11111111111111
14	111111111111111
15	11111111111111111111111111111111
16	11111111111111111111111111111111
17	11111111111111111111111111111111
18	11111111111111111111111111111111
19	11111111111111111111111111111111
20	11111111111111111111111111111111
21	11111111111111111111111111111111
22	11111111111111111111111111111111
23	11111111111111111111111111111111


DONE THE RIGHT WAY
0	1
1	11
2	111
3	1111
4	11111
5	111111
6	1111111
7	11111111
8	111111111
9	1111111111
10	11111111111
11	111111111111
12	1111111111111
13	11111111111111
14	111111111111111
15	1111111111111111
16	11111111111111111
17	111111111111111111
18	1111111111111111111
19	11111111111111111111
20	111111111111111111111
21	1111111111111111111111
22	11111111111111111111111
23	111111111111111111111111

f...

Okay, so I corrected this, and it actually works.
Thank you so much.

disappears in shame

we have all been there.... hope it helped

PS: on a 32 bit platform you would not have seen the issue as an int would be 32 bits and this it would have worked fine;

PS2: the bitSet() macro could also be used to set a bit and there is also bitClear()

There is no shame in that. You could always check sketch.ino - Wokwi ESP32, STM32, Arduino Simulator

It is very worthwhile to spend some time reading HOW numeric data types and numeric espressions actually operate in c/c++. There are hard and fast rules that define precisely how expressions are evaluated, what data types are used for arithmetic operations. Not taking the time to learn at least the basics will cost you a great deal of time, and a great many bugs.

What makes this hurt (more) is that I found the 16 bit thing very suspicious and checked all data types making sure that I don't run into exactly this.
Just didn't see this. Hence the f.

yeah, it's a subtle one. The good news is once you've been bitten by this and banged your head on the wall for some time, you are likely not going to do that mistake again :slight_smile:

that's how we learn