Program will run on my Arduino Mega but not the Uno

I am looking for help with this code. I would prefer to use an Uno or nano for this project. I slowly added the code little by little to see what was preventing it from running on the uno.

Hardware:
4x4 keypad
I2C display
LED strip lights

Summary:
I have a string of addressable LED lights that run the perimeter of my poker table. Ultimately the code keeps track of which seats are occupied and lights up the dealer, small blind, and big blind seats. the code does the following:

  1. prompts the user to enter empty seats
  2. user enters empty seat numbers
  3. user hits * to proceed to game
  4. if the user presses '#' the code will advance the dealer seats to the next filled seat
  5. if the user presses 'D' it will remove a seat
    6 after each action. the code reloops (updates the LCD & LEDs)
#include <Keypad.h>
#include <Adafruit_NeoPixel.h>
#define PIN 13
#define NUMPIXELS 100
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//Constants
const int numS = 10;
const int numSLED = 10;
//Variables
int smallB;
int smallBE = false;
int bigB;
int dealerS = 0;
boolean seats[numS];
boolean setupComplete = false;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayt = 100;
int numm;
int deadBlind = false;

//keypad
const byte numRows = 4;  //number of rows on the keypad
const byte numCols = 4;  //number of columns on the keypad
char keymap[numRows][numCols] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};

//Code that shows the the keypad connections to the arduino terminals
byte rowPins[numRows] = { 9, 8, 7, 6 };  //Rows 0 to 3
byte colPins[numCols] = { 5, 4, 3, 2 };  //Columns 0 to 3


//initializes an instance of the Keypad class
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

void setup() {
  Serial.begin(9600);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Address 0x3D for 128x64
    Serial.println(F("failed"));
    for (;;)
      ;
  }
  delay(2000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  pixels.begin();
  resetSeats();
  promptEmptySeats();
  pixels.setBrightness(20);
}

//If key is pressed, this key is stored in 'keypressed' variable
//If key is not equal to 'NO_KEY', then this key is printed out
//if count=17, then count is reset back to 0 (this means no key is pressed during the whole keypad scan process

void loop() {
  display.clearDisplay();
  updateLCD();
  updateLEDs();
  char key = '\0';
  while (key == '\0') {
    key = myKeypad.getKey();
  }

  switch (key) {

    case 'D':

      key = '\0';

      display.clearDisplay();
      display.setCursor(0, 10);
      display.print("KO Seat?");
      display.display();
      delay(250);

      while (key == '\0') {
        key = myKeypad.getKey();
      }
      removeSeat(key);
      break;
    case '#':
      key = '\0';
      display.clearDisplay();
      display.setCursor(0, 10);
      display.print("next dealer");
      display.display();
      delay(250);
      advanceDealer();
      break;
    case 'B':
      key = '\0';
      display.clearDisplay();
      display.setCursor(0, 10);
      display.println("Blink Seat");
      display.display();
      delay(250);
      blinkSeat();
      break;
  }
}

void resetSeats() {
  for (int i = 0; i < numS; i++) {
    seats[i] = true;
  }
}

void promptEmptySeats() {
  display.clearDisplay();
  display.setCursor(0, 10);
  display.println("Remove ");
  display.print("Seat #s: ");
  display.display();
  while (!setupComplete) {
    char key = myKeypad.getKey();
    if (key != NO_KEY) {
      if (isdigit(key)) {
        removeSeat(key);

        display.clearDisplay();
        display.setCursor(0, 10);
        display.println("Remove ");
        display.print("Seat #: ");
        display.display();
      } else if (key == '*') {
        setupComplete = true;
        startGame();
      }
    }
  }

  while (!seats[dealerS]) {
    dealerS++;
  }

  smallB = dealerS + 1;
  while (!seats[smallB]) {
    smallB++;
  }

  bigB = smallB + 1;
  while (!seats[bigB]) {
    bigB++;
  }
}


void removeSeat(char seatNum) {
  char key = myKeypad.getKey();
  int seat;
  int displayS;
  if (seatNum == '0') {
    displayS = 10;  // Seat 10
  } else {
    displayS = seatNum - '0';
  }
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print(displayS);
  display.print(" removed");
  display.display();
  delay(1000);

  if (seatNum == '0') {
    seat = 9;  // Seat 10
  } else {
    seat = seatNum - '1';
  }
  if (seat >= 0 && seat < numS) {
    seats[seat] = false;
  }
  if (seatNum == smallB) {
    display.print("small B eliminated");
    display.display();
    smallBE = true;
  }
}

void advanceDealer() {

  do {
    dealerS++;
    if (dealerS + 1 > numS) {
      dealerS = 0;
    }
  } while (!seats[dealerS]);
  advanceSB();
  advanceBB();
}

void advanceSB() {
  int nextSB = dealerS;

  do {
    nextSB++;
    if (nextSB + 1 > numS) {
      nextSB = 0;
    }
  } while (!seats[nextSB]);
  smallB = nextSB;
}

void advanceBB() {
  int nextBB = smallB;

  do {
    nextBB++;
    if (nextBB + 1 > numS) {
      nextBB = 0;
    }
  } while (!seats[nextBB]);
  bigB = nextBB;
}


void addSeat() {
  display.clearDisplay();
  display.print("add seat");
  display.display();
}

void blinkSeat() {
  display.clearDisplay();
  display.setCursor(0, 10);
  display.print("Start");
  display.display();
}

void startGame() {
  display.clearDisplay();
  display.setCursor(0, 10);
  display.print("Start");
  display.display();
}

void updateLCD() {
  display.clearDisplay();
  display.setCursor(0, 10);
  display.print("D:");
  display.print(dealerS + 1);
  display.print(" ");
  display.print("Sm:");
  display.print(smallB + 1);
  display.print(" ");
  display.print("Big:");
  display.println(bigB + 1);
  display.display();


  for (int i = 0; i < numS; i++) {
    if (seats[i]) {
      display.print(i + 1);
      display.display();
    }
  }
}

void updateLEDs() {
  pixels.clear();
  Serial.println(dealerS);
  int Dstart = numSLED * (dealerS);
  int Dend = Dstart + (numSLED - 1);
  for (int j = Dstart; j <= Dend; j++) {
    pixels.setPixelColor(j, pixels.Color(255, 255, 255));
    Serial.print(j);
    pixels.show();
  }

  int Sstart = numSLED * (smallB);
  int Send = Sstart + (numSLED - 1);
  for (int j = Sstart; j <= Send; j++) {
    pixels.setPixelColor(j, pixels.Color(0, 0, 255));
  }

  int Bstart = numSLED * (bigB);
  int Bend = Bstart + (numSLED - 1);
  for (int j = Bstart; j <= Bend; j++) {
    pixels.setPixelColor(j, pixels.Color(255, 100, 0));
  }

  display.display();
  pixels.show();
}

What does the IDE report about memory usage?

For example:
Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.

1 Like

Below is what I get when uploading the whole sketch to the UNO. I don't get any errors and it says "done uploading".
Thanks in advance.... This is my first "big" project, for me.

I've tried to add small chunks of the code at a time and it will work, but then it gets to the point where if I add one additional letter to a prompt it stops running.

Sketch uses 18158 bytes (56%) of program storage space. Maximum is 32256 bytes.
Global variables use 811 bytes (39%) of dynamic memory, leaving 1237 bytes for local variables. Maximum is 2048 bytes.

The LED strip uses 300 bytes (3x100) and the display uses 1024 bytes. Total is 1324 bytes.
Add the 811, that's 2135. You only have 2048 on the UNO.

Oh.. Thanks I appreciate it. This was driving me insane.
I know this is a subjective question, but does the Mega make sense for this project?

Not really, no. You don't need all those pins.

Consider Nano Every.

How? I can't see where 800+ bytes have been allocated...

Try using the F() macro whatever you see Serial.print/ln() or display.print/ln() being used. For example

display.print("Start");

becomes

display.print(F("Start"));

But only where a fixed string like "xyz" is printed. You can't use F() in this line, for example

display.print(displayS);

I honestly don't know. I'm new to this so i'm just copying and pasting what it tells me. I'm sure this could be written more efficiently if i knew what i was doing, but it does work on the Mega.

To be honest, I wasn't really asking you. :wink: More asking the more experienced Arduino forum experts.

We know that the Adafruit libraries allocate memory for buffers (like for the OLED screen or the Neopixel strip) only when the code executes. This means that the required memory won't be included in the messages you see in the IDE when you click Verify/Upload.

But somehow those libraries are using hundreds of bytes of dynamic RAM, and I am surprised about that. Your own code uses only a few tens of bytes.

I went through and did this to all of my strings. and i got it down to 721 bytes. I also noticed that it will run if I set the number of LEDs to 20, but when I set them to 100, which is how many i need, it stops working.

Sketch uses 18340 bytes (56%) of program storage space. Maximum is 32256 bytes.
Global variables use 721 bytes (35%) of dynamic memory, leaving 1327 bytes for local variables. Maximum is 2048 bytes.

Ok... I suggest replacing the Adafruit SD1306 and GFX libraries with the U8G2 or the U8X8 library (actually they come in the same download). These will use far less dynamic memory, and hopefully get your code running. They will require some changes to your code, unfortunately.

It looks like you only print text to the display, so U8X8 may be ok. You don't get as wide a choice of fonts or sizes, but hopefully you can get the OLED screen looking how you need it to look.

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