OLED seems to deactivate (?) serial monitor

I'm trying to program a little "game" (if you can call it that) to get warm with OLED displays and input triggers. I have a IR remote controller and a 1.3" OLED screen connected to the Arduino (Mega 2560). I need the serial monitor to print the button presses while the OLED is also running to be able to debug the stuff i code. This is the code i have so far:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>
#include <IRremote.h>

const byte COLS = 4;
const byte ROWS = 4;

int IRpin = 2;

#define OLED_RESET 4
Adafruit_SH1106 display(OLED_RESET);

#if (SH1106_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SH1106.h!");
#endif


int trigstat = 0;

void setup()   {
  randomSeed(random(127));
  Serial.begin(9600);
  IrReceiver.begin(IRpin);
  display.clearDisplay();
  display.fillScreen(0);
  display.display();          
  display.begin(SH1106_SWITCHCAPVCC, 0x3C);  
}

void loop() {
  if (IrReceiver.decode())
  {
    delay(20);
    IrReceiver.resume();
    if (IrReceiver.decodedIRData.command > 0 && IrReceiver.decodedIRData.command < 95)
    {
      Serial.print("Button value: ");
      Serial.print(IrReceiver.decodedIRData.command);
      Serial.print(" -> ");
      if (IrReceiver.decodedIRData.command == 21) Serial.println("Arrow down");
    }

  }
  display.clearDisplay();
  //player();
  display.display();
}

void player() {
    int XPOS = 0;
    int YPOS = 0;
  while (1) {
      display.writeFillRect(XPOS, YPOS,5,5,1);
      display.display();
      }
  if (IrReceiver.decodedIRData.command == 21){      
      YPOS += 1;
      display.clearDisplay();
      display.writeFillRect(XPOS, YPOS,5,5,1);
      display.display();
    }
   }

//random(display.width()) für Zufallsposition

The serial monitor works fine and shows which button i press on the remote.
But if i integrate player()* to the loop the rectangle is positioned on the OLED as it should be, but there are no lines printed on the serial monitor anymore when i press a button, so i am stuck here. I can't figure out if the code is wrong or if for some reason using OLED and the serial monitor exclude each other.

The question is tough to google, because a lot of people want the Serial to be printed on OLED, which is not what i want obviously.

*i know its not working, but this isn't my question right now.

Thanks in advance

nope. Do it all the time. Will look further at your code in a minute. Welcome, by the way, and thank you profusely for reading the How To and doing so nicely on your first post.

1 Like

Not sure if any of these are reasons, but:
In setup, you're doing various display actions before your display.begin(). Was that intentional?
You're clearing the display on every iteration of the loop, many thousand times per second. Doesn't 'seem' right.

Haha i didn't read anything. I hope i didn't do anything wrong and that was a sarcastic way to point that out. The rules are basically the same everywhere and it comes all down to understanding that others don't understand you when you leave out important details. Basic empathy if you want to call it that.

1 Like

No sarcasm, 99% of new posts don't use code tags. Seriously. I'd advise reading the how-to anyway, there are other landmines you can avoid, but you're off to a good start.

The forum is particularly 'touchy' about multiple threads on the same project; if you have different issues within the same project, keep it all in one thread so that design content is accessible for any discussion. Firing up a new thread will get you a new set of listeners, who will then ask for all the same info already provided elsewhere, which is messy and frustrating.

1 Like

deleted

1 Like

I deleted the following lines in setup() now, but that didn't change anything about my initial problem.

  display.clearDisplay();
  display.fillScreen(0);
  display.display(); 

I started with the example file from the Adafruit_SH1106 library and reduced it more and more to understand what the single lines do. That's why there where some unneccesary lines left in setup().

But i'm also a little confused about a detail in your answer:

You're clearing the display on every iteration of the loop, many thousand times per second.

isn't the setup()-funcion only called once to initialize stuff and the loop() is the one being iterated?

Ok i got it now. The problem was the while-loop in player(). For some reason it prevents the serial.print() to show up. I can see the button presses now.

Just for the sake of completeness:

void player() {
  int XPOS = 0;
  int YPOS = 0;
  display.writeFillRect(XPOS, YPOS, 5, 5, 1);
  display.display();
  if (IrReceiver.decodedIRData.command == 21) {
    YPOS += 1;
    display.clearDisplay();
    display.writeFillRect(XPOS, YPOS, 5, 5, 1);
    display.display();
  }
}

This gives you a 5x5 rectangle that starts to jump up and down 1px in the upper left corner as soon as you press button 21 on your remote (which is arrow down on my one). Progress! :slight_smile:

edit: if anyone has an idea why the while-loop hindered the print i'd still be happy about an explanation.

 while (1) {
      display.writeFillRect(XPOS, YPOS,5,5,1);
      display.display();
      }

Executes forever.

1 Like
void loop() {
//IR code omitted for clarity
  display.clearDisplay();
  //player();
  display.display();
}

This is what's going on in your main loop, when nothing's pressed and you're not locked within player(). Constant wipe and redisplay, many thousand times per second. Was that your intent?

No idea :slight_smile:
I thought the rectangle that is produced in player() needed to be deleted before calling player() again and the display needed to be updated after that.

Doesn't make sense as all this already happens in player(), so it's gone now.

I'm already able to move the rectangle around, but everything that could come now is off-topic. So i'll post the code one last time for the other noobs:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>
#include <IRremote.h>

const byte COLS = 4;
const byte ROWS = 4;

int IRpin = 2;

#define OLED_RESET 4
Adafruit_SH1106 display(OLED_RESET);

#if (SH1106_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SH1106.h!");
#endif

  int XPOS = display.width() / 2;
  int YPOS = display.height() / 2;

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(IRpin);
  display.begin(SH1106_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.writeFillRect(XPOS, YPOS, 5, 5, 1);
  display.display();
}

void loop() {
  if (IrReceiver.decode()) {
    delay(20);
    IrReceiver.resume();
    if (IrReceiver.decodedIRData.command > 0 && IrReceiver.decodedIRData.command < 95) {
      Serial.print("Button value: ");
      Serial.print(IrReceiver.decodedIRData.command);
      Serial.print(" -> ");
      if (IrReceiver.decodedIRData.command == 21) Serial.println("Arrow down");
    }
  }
  player();
}

void player() {
  if (IrReceiver.decodedIRData.command == 21) {
    YPOS += 1;
    display.clearDisplay();
    display.writeFillRect(XPOS, YPOS, 5, 5, 1);
    display.display();
  }
  if (IrReceiver.decodedIRData.command == 68) {
    XPOS -= 1;
    display.clearDisplay();
    display.writeFillRect(XPOS, YPOS, 5, 5, 1);
    display.display();
  }
  if (IrReceiver.decodedIRData.command == 67) {
    XPOS += 1;
    display.clearDisplay();
    display.writeFillRect(XPOS, YPOS, 5, 5, 1);
    display.display();
  }
  if (IrReceiver.decodedIRData.command == 70) {
    YPOS -= 1;
    display.clearDisplay();
    display.writeFillRect(XPOS, YPOS, 5, 5, 1);
    display.display();
  }
}

This one will place a 5x5 rectangle in the middle of your screen (no matter the size) which will be movable with the key-presses you define in each if(IrReceiver.decodedIRData.command ==...) -line.

This is not how its supposed to work because the movement doesn't stop at the moment, but its already a huge leap forward and i'm gonna figure out the next steps by myself. Btw: if you press any other than the defined buttons the rectangle will stop (which makes sense, because IrReceiver.decodedIRData.command will not be one of the four defined ones anymore).

As soon as i have a "working" code, that includes moving the rectangle 1px per button-press and stops the rectangle at the display-borders, i'm gonna post it in a new thread so people can learn along if they want to.

A long-term aim could be a tiny jump-and-run that includes collecting points on platforms that are generated randomly or something. Maybe even have some form of gravity and a jumping-function (which is, afaik, a lot tougher task than you'd think).

Thanks a lot @camsysca, all you wrote really helped.

A minor observation.
One of the best, and most underused and misunderstood, operators in C/C++ is the ternary; great for this sort of thing.

In your case,

YPOS -= 1;

For example this line, could be changed to:

YPOS = YPOS > YMIN? YPOS -= 1 : YMIN;
to enforce your minimum boundary; I'll let you apply that to the other three movement cases.

1 Like
if (IrReceiver.decodedIRData.command == 21) {
    display.writeFillRect(XPOS, YPOS, playerSize, playerSize, 0);
    if (YPOS < bottomBorder-playerSize-1) YPOS += 1;
    display.writeFillRect(XPOS, YPOS, playerSize, playerSize, 1);
  }

My movement-blocks look like this now. I added a rectangle: display.drawRect(leftBorder,upperBorder,rightBorder,bottomBorder,1)*, so i need to add/substract 1 from each side. Because the whole display was reset before, the rectangle was deleted after the first button-press, so i had to change that line to delete the players previous position only by overwriting it with a black square with the same size.
I understand the ternary syntax, but would it really add anything compared to my solution?

*the variables are defined in the beginning, because i'm sure i'm gonna need them multiple times.

It's more style than substance. You're good to go.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.