# Question
Title: I'm trying to make a game of life using an arduino nano and a 24x8 Led Matrix. When I try making area bigger it says not enough memory. What can I do?
I have a problem when changing `MAX_X` from 8 to 24. I know that the problem is that I am using to many global variables but I don't know how to fix it.

```
#include <LedControl.h>

#include "LedControl.h"

// "DIN" data in pin
#define DIN_PIN 12
// "CLK" clock pin
#define CLK_PIN 11
// "CS" pin
#define CS_PIN 10
// grid dimensions. should not be larger than 8x8
#define MAX_Y 8
#define MAX_X 24
// how many custom starting grid patterns
#define MAX_C 15
// time to wait between turns
#define TURN_DELAY 100
// how many turns per game before starting a new game
// you can also use the reset button on the board
#define TURNS_MAX 40
// how many turns to wait if there are no changes before starting a new game
#define NO_CHANGES_RESET 4

int TURNS = 0;       // counter for turns
int NO_CHANGES = 0;  // counter for turns without changes

// game state. 0 is dead cell, 1 is live cell
boolean grid[MAX_Y][MAX_X] = {
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
};

// custom starting grid patterns
boolean cgrids[MAX_C][MAX_Y][MAX_X] = {
  {
    {1, 1, 0, 0, 1, 1, 0, 0},
    {1, 1, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 0, 0, 0, 1, 1},
    {0, 0, 0, 0, 0, 0, 1, 1},
    {1, 1, 0, 0, 0, 0, 0, 0},
    {1, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 0, 1, 1},
    {0, 0, 1, 1, 0, 0, 1, 1},
  },
  {
    {1, 0, 1, 0, 0, 0, 1, 0},
    {0, 1, 1, 0, 0, 0, 1, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 1, 0, 0, 0, 1, 1, 0},
    {0, 1, 0, 0, 0, 1, 0, 1},
  },
  {
    {1, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {1, 0, 1, 0, 0, 0, 0, 0},
  },
  {
    {1, 0, 1, 0, 0, 1, 0, 1},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    {1, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 1, 1, 1},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 1, 0},
    {1, 1, 1, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 0, 0, 1, 0},
  },
  {
    // https://conwaylife.com/wiki/Mold
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 1, 0, 0, 1, 0},
    {0, 0, 1, 0, 1, 0, 1, 0},
    {0, 0, 1, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 1, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    // https://conwaylife.com/wiki/Octagon_2
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 1, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 1},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 0, 0, 1, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
  },
  {
    {1, 0, 1, 0, 0, 1, 0, 1},
    {1, 1, 0, 0, 0, 0, 1, 0},
    {1, 0, 0, 1, 1, 1, 0, 1},
    {0, 0, 1, 1, 0, 1, 0, 0},
    {1, 0, 0, 0, 1, 1, 0, 0},
    {1, 0, 0, 0, 1, 0, 0, 1},
    {0, 0, 0, 0, 0, 0, 1, 0},
    {1, 0, 1, 1, 0, 1, 1, 1},
  },
  {
    {1, 1, 1, 1, 1, 1, 1, 1},
    {1, 1, 0, 0, 0, 0, 1, 1},
    {1, 0, 0, 1, 1, 1, 0, 1},
    {1, 0, 1, 1, 0, 1, 0, 1},
    {1, 0, 1, 0, 1, 1, 0, 1},
    {1, 0, 1, 1, 1, 0, 0, 1},
    {1, 1, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1},
  },
  {
    {1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 1, 1},
    {1, 0, 0, 1, 1, 1, 0, 1},
    {1, 0, 1, 1, 0, 1, 0, 1},
    {1, 0, 1, 0, 1, 1, 0, 1},
    {1, 0, 1, 1, 1, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1},
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {1, 1, 0, 0, 1, 1, 1, 0},
    {1, 0, 1, 0, 1, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 1, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 0, 0, 0},
    {0, 0, 0, 1, 0, 0, 0, 0},
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    {1, 0, 0, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 0, 0, 1, 0, 1},
    {0, 0, 0, 1, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 0, 0, 0},
    {1, 0, 1, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 0, 0, 0, 0, 1},
  },
};

LedControl lc = LedControl(DIN_PIN, CS_PIN, CLK_PIN, 1);

void setup() {
  // seed random from unused analog pin
  randomSeed(analogRead(0));

  // initialise the LED matrix
  lc.shutdown(0, false);
  lc.setIntensity(0, 0);
  lc.clearDisplay(0);

  reset_grid();
  display_grid();

  // Serial.begin(9600);
  // debug_grid();
}

void loop() {
  delay(TURN_DELAY);

  play_gol();

  TURNS++;

  // reset the grid if no changes have occured recently
  // for when the game enters a static stable state
  if (NO_CHANGES > NO_CHANGES_RESET) {
    reset_grid();
  }
  // reset the grid if the loop has been running a long time
  // for when the game cycles between a few stable states
  if (TURNS > TURNS_MAX) {
    reset_grid();
  }

  display_grid();
}

// play game of life
void play_gol() {
  /*
    1. Any live cell with fewer than two neighbours dies, as if by loneliness.
    2. Any live cell with more than three neighbours dies, as if by
    overcrowding.
    3. Any live cell with two or three neighbours lives, unchanged, to the next
    generation.
    4. Any dead cell with exactly three neighbours comes to life.
  */

  boolean new_grid[MAX_Y][MAX_X] = {
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  };

  for (int y = 0; y < 8; y++) {
    for (int x = 0; x < 8; x++) {
      int neighboughs = count_neighboughs(y, x);
      if (grid[y][x] == 1) {
        if ((neighboughs == 2) || (neighboughs == 3)) {
          new_grid[y][x] = 1;
        } else {
          new_grid[y][x] = 0;
        }
      } else {
        if (neighboughs == 3) {
          new_grid[y][x] = 1;
        } else {
          new_grid[y][x] = 0;
        }
      }
    }
  }

  // update the current grid from the new grid and count how many changes
  // occured
  int changes = 0;
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (new_grid[y][x] != grid[y][x]) {
        changes++;
      }
      grid[y][x] = new_grid[y][x];
    }
  }

  // update global counter when no changes occured
  if (changes == 0) {
    NO_CHANGES++;
  }
}

// count the number of neighbough live cells for a given cell
int count_neighboughs(int y, int x) {
  int count = 0;

  // -- Row above us ---
  if (y > 0) {
    // above left
    if (x > 0) {
      count += grid[y - 1][x - 1];
    }
    // above
    count += grid[y - 1][x];
    // above right
    if ((x + 1) < 8) {
      count += grid[y - 1][x + 1];
    }
  }

  // -- Same row -------
  // left
  if (x > 0) {
    count += grid[y][x - 1];
  }
  // right
  if ((x + 1) < 8) {
    count += grid[y][x + 1];
  }

  // -- Row below us ---
  if ((y + 1) < 8) {
    // below left
    if (x > 0) {
      count += grid[y + 1][x - 1];
    }
    // below
    count += grid[y + 1][x];
    // below right
    if ((x + 1) < 8) {
      count += grid[y + 1][x + 1];
    }
  }

  return count;
}

// reset the grid
void reset_grid() {
  NO_CHANGES = 0;
  TURNS = 0;

  int grid_type = random(0, 4);
  int custom_grid_choice = random(0, MAX_C - 1);

  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (grid_type == 0) {
        // use a custom starting grid pattern
        grid[y][x] = cgrids[custom_grid_choice][y][x];
      } else {
        // create a random starting grid pattern
        if (random(0, MAX_X) <= 1) {
          grid[y][x] = 1;
        }
      }
    }
  }
}

// display the current grid to the LED matrix
void display_grid() {
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      lc.setLed(0, y, x, grid[y][x]);
    }
  }
}

/*
  // dump the state of the current grid to the serial connection
  void debug_grid() {
  for (int y = 0; y < MAX_Y; y++) {
    Serial.print("y(");
    Serial.print(y);
    Serial.print("): ");

    for (int x = 0; x < MAX_X; x++) {
      Serial.print(grid[y][x]);
      Serial.print(", ");
    }

    Serial.println("");
  }
  Serial.println("");
  }
*/

```

# Answer
The obvious “low hanging fruit” for memory optimization is `cgrids`. This is an array of 8×24×15 = 2880 booleans that you never modify. By making it `const` and storing it in PROGMEM, you should save that many bytes of RAM.

**Edit**: Augustus73 asked

> And how should I do that?

As explained in the documentation I linked to, using `PROGMEM` is a two-step procedure. First, you have to ask the compiler to put the array in `PROGMEM`:

```
PROGMEM const boolean cgrids[MAX_C][MAX_Y][MAX_X] = { ... };

```

Then, you have to use one of the `pgm_read_*()` macros when you want to retrieve the data, as in:

```
grid[y][x] = pgm_read_byte(&cgrids[custom_grid_choice][y][x]);

```
> 4 votes

# Answer
Your use of a byte per bit in your array is inefficient.

I have reworked the code to use a bit for each array item, as follows:

```
#include <LedControl.h>

// "DIN" data in pin
#define DIN_PIN 12
// "CLK" clock pin
#define CLK_PIN 11
// "CS" pin
#define CS_PIN 10
// grid dimensions. should not be larger than 8x8
#define MAX_Y 8
#define MAX_X 24
// how many custom starting grid patterns
#define MAX_C 15
// time to wait between turns
#define TURN_DELAY 1000
// how many turns per game before starting a new game
// you can also use the reset button on the board
#define TURNS_MAX 40
// how many turns to wait if there are no changes before starting a new game
#define NO_CHANGES_RESET 4

int TURNS = 0;       // counter for turns
int NO_CHANGES = 0;  // counter for turns without changes

// game state. 0 is dead cell, 1 is live cell

unsigned long grid[MAX_Y]; // Each unsigned long can hold 32 bits

// Added by Nick Gammon
void setBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x, const bool value)
  {
  if (value)
    whichGrid[y] |= (1U << x);
  else
    whichGrid[y] &= ~(1U << x);
  } // end of setBit

bool getBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x)
  {
  return whichGrid[y] & (1U << x);
  } // end of testBit

// custom starting grid patterns
unsigned long cgrids[MAX_C][MAX_Y] = {
  {
    0b11001100,
    0b11001100,
    0b00000011,
    0b00000011,
    0b11000000,
    0b11000000,
    0b00110011,
    0b00110011,
  },
  {
    0b10100010,
    0b01100010,
    0b01000010,
    0b00000000,
    0b00000000,
    0b01000010,
    0b01000110,
    0b01000101,
  },

  {
    0b10100000,
    0b01100000,
    0b01000000,
    0b00000000,
    0b00000000,
    0b01000000,
    0b01100000,
    0b10100000,
  },
  {
    0b10100101,
    0b01100110,
    0b01000010,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
  },
  {
    0b10100000,
    0b01100000,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
  },
  {
    0b01000000,
    0b01000111,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000010,
    0b11100010,
    0b00000010,
  },
  {
    // https://conwaylife.com/wiki/Mold
    0b00000000,
    0b00001100,
    0b00010010,
    0b00101010,
    0b00100100,
    0b01000000,
    0b00101000,
    0b00000000,
  },
  {
    // https://conwaylife.com/wiki/Octagon_2
    0b00011000,
    0b00100100,
    0b01000010,
    0b10000001,
    0b10000001,
    0b01000010,
    0b00100100,
    0b00011000,
  },
  {
    0b10100101,
    0b11000010,
    0b10011101,
    0b00110100,
    0b10001100,
    0b10001001,
    0b00000010,
    0b10110111,
  },
  {
    0b11111111,
    0b11000011,
    0b10011101,
    0b10110101,
    0b10101101,
    0b10111001,
    0b11000001,
    0b11111111,
  },
  {
    0b11111111,
    0b10000011,
    0b10011101,
    0b10110101,
    0b10101101,
    0b10111001,
    0b10000001,
    0b11111111,
  },
  {
    0b00000000,
    0b00100000,
    0b00100000,
    0b01100000,
    0b00000000,
    0b11001110,
    0b10101000,
    0b01100000,
  },
  {
    0b00000000,
    0b00000000,
    0b00000000,
    0b00010000,
    0b00110000,
    0b01000000,
    0b00110000,
    0b00010000,
  },
  {
    0b00000000,
    0b00000000,
    0b01100110,
    0b01100110,
    0b01100110,
    0b01100110,
    0b00000000,
    0b00000000,
  },
  {
    0b10000100,
    0b01000010,
    0b00100101,
    0b00010000,
    0b00001000,
    0b10100100,
    0b01000010,
    0b00100001,
  },

};

LedControl lc = LedControl(DIN_PIN, CS_PIN, CLK_PIN, 1);

void setup() {
  // seed random from unused analog pin
  randomSeed(analogRead(0));

  // initialise the LED matrix
  lc.shutdown(0, false);
  lc.setIntensity(0, 0);
  lc.clearDisplay(0);

  reset_grid();
  display_grid();

  Serial.begin(115200);
  debug_grid();
}

void loop() {
  delay(TURN_DELAY);

  play_gol();

  TURNS++;

  // reset the grid if no changes have occured recently
  // for when the game enters a static stable state
  if (NO_CHANGES > NO_CHANGES_RESET) {
    reset_grid();
  }
  // reset the grid if the loop has been running a long time
  // for when the game cycles between a few stable states
  if (TURNS > TURNS_MAX) {
    reset_grid();
  }

  display_grid();
}

// play game of life
void play_gol() {
  /*
    1. Any live cell with fewer than two neighbours dies, as if by loneliness.
    2. Any live cell with more than three neighbours dies, as if by
    overcrowding.
    3. Any live cell with two or three neighbours lives, unchanged, to the next
    generation.
    4. Any dead cell with exactly three neighbours comes to life.
  */

  unsigned long new_grid[MAX_Y]; // Each unsigned long can hold 32 bits

  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      int neighboughs = count_neighboughs(y, x);
      if (getBit (grid, y, x)) {
        if ((neighboughs == 2) || (neighboughs == 3)) {
          setBit (new_grid, y, x, 1);
        } else {
          setBit (new_grid, y, x, 0);
        }
      } else {
        if (neighboughs == 3) {
          setBit (new_grid, y, x, 1);
        } else {
          setBit (new_grid, y, x, 0);
        }
      }
    }
  }

  // update the current grid from the new grid and count how many changes
  // occured
  int changes = 0;
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (getBit (new_grid, y, x) != getBit (grid, y, x)) {
        changes++;
      }
      setBit (grid, y, x, getBit (new_grid, y, x));
    }
  }

  // update global counter when no changes occured
  if (changes == 0) {
    NO_CHANGES++;
  }
}

// count the number of neighbough live cells for a given cell
int count_neighboughs(int y, int x) {
  int count = 0;

  // -- Row above us ---
  if (y > 0) {
    // above left
    if (x > 0) {
      count += getBit (grid, y - 1, x - 1);
    }
    // above
    count += getBit (grid, y - 1, x);
    // above right
    if ((x + 1) < MAX_X) {
      count += getBit (grid, y - 1, x + 1);
    }
  }

  // -- Same row -------
  // left
  if (x > 0) {
    count += getBit (grid, y, x - 1);
  }
  // right
  if ((x + 1) < MAX_X) {
    count += getBit (grid, y, x + 1);
  }

  // -- Row below us ---
  if ((y + 1) < MAX_Y) {
    // below left
    if (x > 0) {
      count += getBit (grid, y + 1, x - 1);
    }
    // below
    count += getBit (grid, y + 1, x);
    // below right
    if ((x + 1) < MAX_X) {
      count += getBit (grid, y + 1, x + 1);
    }
  }

  return count;
}

// reset the grid
void reset_grid() {
  NO_CHANGES = 0;
  TURNS = 0;

  Serial.println("Resetting the grid");

  int grid_type = random(0, 4);
  int custom_grid_choice = random(0, MAX_C - 1);

  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (grid_type == 0) {
        // use a custom starting grid pattern
        setBit (grid, y, x, getBit (cgrids[custom_grid_choice], y, x));
      } else {
        // create a random starting grid pattern
        if (random(0, MAX_X) <= 1) {
          setBit (grid, y, x, 1);
        }
      }
    }
  }
}

// display the current grid to the LED matrix
void display_grid() {
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      lc.setLed(0, y, x, getBit (grid, y, x));
    }
  }
  debug_grid ();
}

// dump the state of the current grid to the serial connection
void debug_grid() {
  Serial.print ("      ");
  for (int x = 0; x < MAX_X; x++)
     Serial.print (".");
  Serial.println ();

  for (int y = 0; y < MAX_Y; y++) {
    Serial.print("y(");
    Serial.print(y);
    Serial.print("): ");

    for (int x = 0; x < MAX_X; x++) {
      if (getBit (grid, y, x))
        Serial.print ("*");
      else
        Serial.print (" ");
    }

    Serial.println("");
  }
  Serial.println("");
  }

```

Note, in particular, the functions setBit and getBit which are designed to test, set or clear a particular bit, as indexed in your earlier implementation of arrays of one byte.

I then reworked the code to use these new functions, and changed your declaration of the cgrids to match. Testing on the serial terminal seems to work. Your code didn't do anything useful for me on my LED display.

```
// Added by Nick Gammon
void setBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x, const bool value)
  {
  if (value)
    whichGrid[y] |= (1U << x);
  else
    whichGrid[y] &= ~(1U << x);
  } // end of setBit

bool getBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x)
  {
  return whichGrid[y] & (1U << x);
  } // end of testBit

```

I also fixed a few bugs in your code where you were testing for X or Y reaching 8 rather than MAX\_X or MAX\_Y which would have worked when MAX\_X and MAX\_Y were 8, but not if you make them bigger.

This version uses a lot less memory:

```
Sketch uses 4876 bytes (15%) of program storage space. Maximum is 32256 bytes.

```

I reworked your debugging display a bit since the LEDs didn't work for me. Example output:

```
      ........................
y(0):           ****
y(1):   **        * *
y(2):   **     ** * **
y(3):          *  * *
y(4):             *
y(5):
y(6):
y(7):

      ........................
y(0):            ***
y(1):   **     *    **
y(2):   **     ** * **
y(3):          ** * **
y(4):              *
y(5):
y(6):
y(7):

      ........................
y(0):             ***
y(1):   **     *     *
y(2):   **    *
y(3):          ** *  *
y(4):              **
y(5):
y(6):
y(7):

      ........................
y(0):              **
y(1):   **         **
y(2):   **    * *
y(3):          *   **
y(4):              **
y(5):
y(6):
y(7):

```

---

Just for interest, I made a Game of Life in 2011 for the Lots Of LEDs shield. It's a fun project.

*Edit* \- to be fair, I think the code was actually written by the author of the shield: "Created by Jimmie Rodgers on 12/30/2009".

However I do recall writing a Game of Life for the Apple II, many years ago. The source code for that is long gone. :)
> 0 votes

---
Tags: arduino-nano
---


# Question
Title: What prescaler to use for finer control?
I'm using a UNO to generate a 10 kHz PWM signal. I need finer duty cycle variation. The prescalers supported are 1, 8, 32, and 64.

```
void setup()
{
  pinMode(3,OUTPUT);
  TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on compare
  TCCR2B = bit (WGM22) | bit (CS22); // fast PWM, prescaler of 64
  OCR2A = 63; // prescaler 32 with 10Khz
  OCR2B = ((64 + 1)/2) - 1; // 50% duty cycle
}

void loop()
{
}

```

# Answer
The lower prescalers will give you finer control. The bigger prescalers necessarily have coarser control.

From my web page about timers is this table of prescalers:

```
  n  -- Prescale 1   --  -- Prescale 8   --  -- Prescale 64  --  -- Prescale 256 --  -- Prescale 1024--
     Freq (Hz) Per (µs)  Freq (Hz) Per (µs)  Freq (Hz) Per (µs)  Freq (Hz) Per (µs)  Freq (Hz) Per (µs)
  1: 8,000,000*   0.125  1,000,000    1.000    125,000    8.000     31,250   32.000      7,813  128.000
  2: 5,333,333    0.188    666,667    1.500     83,333   12.000     20,833   48.000      5,208  192.000
  3: 4,000,000    0.250    500,000    2.000     62,500   16.000     15,625   64.000      3,906  256.000
  4: 3,200,000    0.313    400,000    2.500     50,000   20.000     12,500   80.000      3,125  320.000
  5: 2,666,667    0.375    333,333    3.000     41,667   24.000     10,417   96.000      2,604  384.000
  6: 2,285,714    0.438    285,714    3.500     35,714   28.000      8,929  112.000      2,232  448.000
  7: 2,000,000    0.500    250,000    4.000     31,250   32.000      7,813  128.000      1,953  512.000
  8: 1,777,778    0.563    222,222    4.500     27,778   36.000      6,944  144.000      1,736  576.000
  9: 1,600,000    0.625    200,000    5.000     25,000   40.000      6,250  160.000      1,563  640.000
 10: 1,454,545    0.688    181,818    5.500     22,727   44.000      5,682  176.000      1,420  704.000
 11: 1,333,333    0.750    166,667    6.000     20,833   48.000      5,208  192.000      1,302  768.000
 12: 1,230,769    0.813    153,846    6.500     19,231   52.000      4,808  208.000      1,202  832.000
 13: 1,142,857    0.875    142,857    7.000     17,857   56.000      4,464  224.000      1,116  896.000
 14: 1,066,667    0.937    133,333    7.500     16,667   60.000      4,167  240.000      1,042  960.000
 15: 1,000,000    1.000    125,000    8.000     15,625   64.000      3,906  256.000        977 1024.000
 16:   941,176    1.063    117,647    8.500     14,706   68.000      3,676  272.000        919 1088.000
 17:   888,889    1.125    111,111    9.000     13,889   72.000      3,472  288.000        868 1152.000
 18:   842,105    1.187    105,263    9.500     13,158   76.000      3,289  304.000        822 1216.000
 19:   800,000    1.250    100,000   10.000     12,500   80.000      3,125  320.000        781 1280.000
 20:   761,905    1.313     95,238   10.500     11,905   84.000      2,976  336.000        744 1344.000
 21:   727,273    1.375     90,909   11.000     11,364   88.000      2,841  352.000        710 1408.000
 22:   695,652    1.438     86,957   11.500     10,870   92.000      2,717  368.000        679 1472.000
 23:   666,667    1.500     83,333   12.000     10,417   96.000      2,604  384.000        651 1536.000
 24:   640,000    1.562     80,000   12.500     10,000  100.000      2,500  400.000        625 1600.000
 25:   615,385    1.625     76,923   13.000      9,615  104.000      2,404  416.000        601 1664.000
 26:   592,593    1.688     74,074   13.500      9,259  108.000      2,315  432.000        579 1728.000
 27:   571,429    1.750     71,429   14.000      8,929  112.000      2,232  448.000        558 1792.000
 28:   551,724    1.813     68,966   14.500      8,621  116.000      2,155  464.000        539 1856.000
 29:   533,333    1.875     66,667   15.000      8,333  120.000      2,083  480.000        521 1920.000
 30:   516,129    1.938     64,516   15.500      8,065  124.000      2,016  496.000        504 1984.000
 31:   500,000    2.000     62,500   16.000      7,813  128.000      1,953  512.000        488 2048.000
 32:   484,848    2.062     60,606   16.500      7,576  132.000      1,894  528.000        473 2112.000
 33:   470,588    2.125     58,824   17.000      7,353  136.000      1,838  544.000        460 2176.000
 34:   457,143    2.188     57,143   17.500      7,143  140.000      1,786  560.000        446 2240.000
 35:   444,444    2.250     55,556   18.000      6,944  144.000      1,736  576.000        434 2304.000
 36:   432,432    2.313     54,054   18.500      6,757  148.000      1,689  592.000        422 2368.000
 37:   421,053    2.375     52,632   19.000      6,579  152.000      1,645  608.000        411 2432.000
 38:   410,256    2.438     51,282   19.500      6,410  156.000      1,603  624.000        401 2496.000
 39:   400,000    2.500     50,000   20.000      6,250  160.000      1,563  640.000        391 2560.000
 40:   390,244    2.563     48,780   20.500      6,098  164.000      1,524  656.000        381 2624.000
 41:   380,952    2.625     47,619   21.000      5,952  168.000      1,488  672.000        372 2688.000
 42:   372,093    2.687     46,512   21.500      5,814  172.000      1,453  688.000        363 2752.000
 43:   363,636    2.750     45,455   22.000      5,682  176.000      1,420  704.000        355 2816.000
 44:   355,556    2.812     44,444   22.500      5,556  180.000      1,389  720.000        347 2880.000
 45:   347,826    2.875     43,478   23.000      5,435  184.000      1,359  736.000        340 2944.000
 46:   340,426    2.938     42,553   23.500      5,319  188.000      1,330  752.000        332 3008.000
 47:   333,333    3.000     41,667   24.000      5,208  192.000      1,302  768.000        326 3072.000
 48:   326,531    3.063     40,816   24.500      5,102  196.000      1,276  784.000        319 3136.000
 49:   320,000    3.125     40,000   25.000      5,000  200.000      1,250  800.000        313 3200.000
 50:   313,725    3.188     39,216   25.500      4,902  204.000      1,225  816.000        306 3264.000
 51:   307,692    3.250     38,462   26.000      4,808  208.000      1,202  832.000        300 3328.000
 52:   301,887    3.313     37,736   26.500      4,717  212.000      1,179  848.000        295 3392.000
 53:   296,296    3.375     37,037   27.000      4,630  216.000      1,157  864.000        289 3456.000
 54:   290,909    3.437     36,364   27.500      4,545  220.000      1,136  880.000        284 3520.000
 55:   285,714    3.500     35,714   28.000      4,464  224.000      1,116  896.000        279 3584.000
 56:   280,702    3.562     35,088   28.500      4,386  228.000      1,096  912.000        274 3648.000
 57:   275,862    3.625     34,483   29.000      4,310  232.000      1,078  928.000        269 3712.000
 58:   271,186    3.688     33,898   29.500      4,237  236.000      1,059  944.000        265 3776.000
 59:   266,667    3.750     33,333   30.000      4,167  240.000      1,042  960.000        260 3840.000
 60:   262,295    3.813     32,787   30.500      4,098  244.000      1,025  976.000        256 3904.000
 61:   258,065    3.875     32,258   31.000      4,032  248.000      1,008  992.000        252 3968.000
 62:   253,968    3.938     31,746   31.500      3,968  252.000        992 1008.000        248 4032.000
 63:   250,000    4.000     31,250   32.000      3,906  256.000        977 1024.000        244 4096.000
 64:   246,154    4.063     30,769   32.500      3,846  260.000        962 1040.000        240 4160.000
 65:   242,424    4.125     30,303   33.000      3,788  264.000        947 1056.000        237 4224.000
 66:   238,806    4.188     29,851   33.500      3,731  268.000        933 1072.000        233 4288.000
 67:   235,294    4.250     29,412   34.000      3,676  272.000        919 1088.000        230 4352.000
 68:   231,884    4.313     28,986   34.500      3,623  276.000        906 1104.000        226 4416.000
 69:   228,571    4.375     28,571   35.000      3,571  280.000        893 1120.000        223 4480.000
 70:   225,352    4.437     28,169   35.500      3,521  284.000        880 1136.000        220 4544.000
 71:   222,222    4.500     27,778   36.000      3,472  288.000        868 1152.000        217 4608.000
 72:   219,178    4.563     27,397   36.500      3,425  292.000        856 1168.000        214 4672.000
 73:   216,216    4.625     27,027   37.000      3,378  296.000        845 1184.000        211 4736.000
 74:   213,333    4.688     26,667   37.500      3,333  300.000        833 1200.000        208 4800.000
 75:   210,526    4.750     26,316   38.000      3,289  304.000        822 1216.000        206 4864.000
 76:   207,792    4.813     25,974   38.500      3,247  308.000        812 1232.000        203 4928.000
 77:   205,128    4.875     25,641   39.000      3,205  312.000        801 1248.000        200 4992.000
 78:   202,532    4.938     25,316   39.500      3,165  316.000        791 1264.000        198 5056.000
 79:   200,000    5.000     25,000   40.000      3,125  320.000        781 1280.000        195 5120.000
 80:   197,531    5.062     24,691   40.500      3,086  324.000        772 1296.000        193 5184.000
 81:   195,122    5.125     24,390   41.000      3,049  328.000        762 1312.000        191 5248.000
 82:   192,771    5.188     24,096   41.500      3,012  332.000        753 1328.000        188 5312.000
 83:   190,476    5.250     23,810   42.000      2,976  336.000        744 1344.000        186 5376.000
 84:   188,235    5.312     23,529   42.500      2,941  340.000        735 1360.000        184 5440.000
 85:   186,047    5.375     23,256   43.000      2,907  344.000        727 1376.000        182 5504.000
 86:   183,908    5.438     22,989   43.500      2,874  348.000        718 1392.000        180 5568.000
 87:   181,818    5.500     22,727   44.000      2,841  352.000        710 1408.000        178 5632.000
 88:   179,775    5.563     22,472   44.500      2,809  356.000        702 1424.000        176 5696.000
 89:   177,778    5.625     22,222   45.000      2,778  360.000        694 1440.000        174 5760.000
 90:   175,824    5.687     21,978   45.500      2,747  364.000        687 1456.000        172 5824.000
 91:   173,913    5.750     21,739   46.000      2,717  368.000        679 1472.000        170 5888.000
 92:   172,043    5.813     21,505   46.500      2,688  372.000        672 1488.000        168 5952.000
 93:   170,213    5.875     21,277   47.000      2,660  376.000        665 1504.000        166 6016.000
 94:   168,421    5.937     21,053   47.500      2,632  380.000        658 1520.000        164 6080.000
 95:   166,667    6.000     20,833   48.000      2,604  384.000        651 1536.000        163 6144.000
 96:   164,948    6.063     20,619   48.500      2,577  388.000        644 1552.000        161 6208.000
 97:   163,265    6.125     20,408   49.000      2,551  392.000        638 1568.000        159 6272.000
 98:   161,616    6.188     20,202   49.500      2,525  396.000        631 1584.000        158 6336.000
 99:   160,000    6.250     20,000   50.000      2,500  400.000        625 1600.000        156 6400.000
100:   158,416    6.313     19,802   50.500      2,475  404.000        619 1616.000        155 6464.000
101:   156,863    6.375     19,608   51.000      2,451  408.000        613 1632.000        153 6528.000
102:   155,340    6.438     19,417   51.500      2,427  412.000        607 1648.000        152 6592.000
103:   153,846    6.500     19,231   52.000      2,404  416.000        601 1664.000        150 6656.000
104:   152,381    6.562     19,048   52.500      2,381  420.000        595 1680.000        149 6720.000
105:   150,943    6.625     18,868   53.000      2,358  424.000        590 1696.000        147 6784.000
106:   149,533    6.688     18,692   53.500      2,336  428.000        584 1712.000        146 6848.000
107:   148,148    6.750     18,519   54.000      2,315  432.000        579 1728.000        145 6912.000
108:   146,789    6.813     18,349   54.500      2,294  436.000        573 1744.000        143 6976.000
109:   145,455    6.875     18,182   55.000      2,273  440.000        568 1760.000        142 7040.000
110:   144,144    6.938     18,018   55.500      2,252  444.000        563 1776.000        141 7104.000
111:   142,857    7.000     17,857   56.000      2,232  448.000        558 1792.000        140 7168.000
112:   141,593    7.063     17,699   56.500      2,212  452.000        553 1808.000        138 7232.000
113:   140,351    7.125     17,544   57.000      2,193  456.000        548 1824.000        137 7296.000
114:   139,130    7.187     17,391   57.500      2,174  460.000        543 1840.000        136 7360.000
115:   137,931    7.250     17,241   58.000      2,155  464.000        539 1856.000        135 7424.000
116:   136,752    7.313     17,094   58.500      2,137  468.000        534 1872.000        134 7488.000
117:   135,593    7.375     16,949   59.000      2,119  472.000        530 1888.000        132 7552.000
118:   134,454    7.437     16,807   59.500      2,101  476.000        525 1904.000        131 7616.000
119:   133,333    7.500     16,667   60.000      2,083  480.000        521 1920.000        130 7680.000
120:   132,231    7.563     16,529   60.500      2,066  484.000        517 1936.000        129 7744.000
121:   131,148    7.625     16,393   61.000      2,049  488.000        512 1952.000        128 7808.000
122:   130,081    7.687     16,260   61.500      2,033  492.000        508 1968.000        127 7872.000
123:   129,032    7.750     16,129   62.000      2,016  496.000        504 1984.000        126 7936.000
124:   128,000    7.813     16,000   62.500      2,000  500.000        500 2000.000        125 8000.000
125:   126,984    7.875     15,873   63.000      1,984  504.000        496 2016.000        124 8064.000
126:   125,984    7.938     15,748   63.500      1,969  508.000        492 2032.000        123 8128.000
127:   125,000    8.000     15,625   64.000      1,953  512.000        488 2048.000        122 8192.000
128:   124,031    8.063     15,504   64.500      1,938  516.000        484 2064.000        121 8256.000
129:   123,077    8.125     15,385   65.000      1,923  520.000        481 2080.000        120 8320.000
130:   122,137    8.188     15,267   65.500      1,908  524.000        477 2096.000        119 8384.000
131:   121,212    8.250     15,152   66.000      1,894  528.000        473 2112.000        118 8448.000
132:   120,301    8.313     15,038   66.500      1,880  532.000        470 2128.000        117 8512.000
133:   119,403    8.375     14,925   67.000      1,866  536.000        466 2144.000        117 8576.000
134:   118,519    8.438     14,815   67.500      1,852  540.000        463 2160.000        116 8640.000
135:   117,647    8.500     14,706   68.000      1,838  544.000        460 2176.000        115 8704.000
136:   116,788    8.563     14,599   68.500      1,825  548.000        456 2192.000        114 8768.000
137:   115,942    8.625     14,493   69.000      1,812  552.000        453 2208.000        113 8832.000
138:   115,108    8.688     14,388   69.500      1,799  556.000        450 2224.000        112 8896.000
139:   114,286    8.750     14,286   70.000      1,786  560.000        446 2240.000        112 8960.000
140:   113,475    8.812     14,184   70.500      1,773  564.000        443 2256.000        111 9024.000
141:   112,676    8.875     14,085   71.000      1,761  568.000        440 2272.000        110 9088.000
142:   111,888    8.938     13,986   71.500      1,748  572.000        437 2288.000        109 9152.000
143:   111,111    9.000     13,889   72.000      1,736  576.000        434 2304.000        109 9216.000
144:   110,345    9.063     13,793   72.500      1,724  580.000        431 2320.000        108 9280.000
145:   109,589    9.125     13,699   73.000      1,712  584.000        428 2336.000        107 9344.000
146:   108,844    9.188     13,605   73.500      1,701  588.000        425 2352.000        106 9408.000
147:   108,108    9.250     13,514   74.000      1,689  592.000        422 2368.000        106 9472.000
148:   107,383    9.313     13,423   74.500      1,678  596.000        419 2384.000        105 9536.000
149:   106,667    9.375     13,333   75.000      1,667  600.000        417 2400.000        104 9600.000
150:   105,960    9.437     13,245   75.500      1,656  604.000        414 2416.000        103 9664.000
151:   105,263    9.500     13,158   76.000      1,645  608.000        411 2432.000        103 9728.000
152:   104,575    9.563     13,072   76.500      1,634  612.000        408 2448.000        102 9792.000
153:   103,896    9.625     12,987   77.000      1,623  616.000        406 2464.000        101 9856.000
154:   103,226    9.688     12,903   77.500      1,613  620.000        403 2480.000        101 9920.000
155:   102,564    9.750     12,821   78.000      1,603  624.000        401 2496.000        100 9984.000
156:   101,911    9.813     12,739   78.500      1,592  628.000        398 2512.000        100 10048.000
157:   101,266    9.875     12,658   79.000      1,582  632.000        396 2528.000         99 10112.000
158:   100,629    9.938     12,579   79.500      1,572  636.000        393 2544.000         98 10176.000
159:   100,000   10.000     12,500   80.000      1,563  640.000        391 2560.000         98 10240.000
160:    99,379   10.062     12,422   80.500      1,553  644.000        388 2576.000         97 10304.000
161:    98,765   10.125     12,346   81.000      1,543  648.000        386 2592.000         96 10368.000
162:    98,160   10.188     12,270   81.500      1,534  652.000        383 2608.000         96 10432.000
163:    97,561   10.250     12,195   82.000      1,524  656.000        381 2624.000         95 10496.000
164:    96,970   10.313     12,121   82.500      1,515  660.000        379 2640.000         95 10560.000
165:    96,386   10.375     12,048   83.000      1,506  664.000        377 2656.000         94 10624.000
166:    95,808   10.438     11,976   83.500      1,497  668.000        374 2672.000         94 10688.000
167:    95,238   10.500     11,905   84.000      1,488  672.000        372 2688.000         93 10752.000
168:    94,675   10.563     11,834   84.500      1,479  676.000        370 2704.000         92 10816.000
169:    94,118   10.625     11,765   85.000      1,471  680.000        368 2720.000         92 10880.000
170:    93,567   10.687     11,696   85.500      1,462  684.000        365 2736.000         91 10944.000
171:    93,023   10.750     11,628   86.000      1,453  688.000        363 2752.000         91 11008.000
172:    92,486   10.813     11,561   86.500      1,445  692.000        361 2768.000         90 11072.000
173:    91,954   10.875     11,494   87.000      1,437  696.000        359 2784.000         90 11136.000
174:    91,429   10.938     11,429   87.500      1,429  700.000        357 2800.000         89 11200.000
175:    90,909   11.000     11,364   88.000      1,420  704.000        355 2816.000         89 11264.000
176:    90,395   11.063     11,299   88.500      1,412  708.000        353 2832.000         88 11328.000
177:    89,888   11.125     11,236   89.000      1,404  712.000        351 2848.000         88 11392.000
178:    89,385   11.188     11,173   89.500      1,397  716.000        349 2864.000         87 11456.000
179:    88,889   11.250     11,111   90.000      1,389  720.000        347 2880.000         87 11520.000
180:    88,398   11.312     11,050   90.500      1,381  724.000        345 2896.000         86 11584.000
181:    87,912   11.375     10,989   91.000      1,374  728.000        343 2912.000         86 11648.000
182:    87,432   11.438     10,929   91.500      1,366  732.000        342 2928.000         85 11712.000
183:    86,957   11.500     10,870   92.000      1,359  736.000        340 2944.000         85 11776.000
184:    86,486   11.563     10,811   92.500      1,351  740.000        338 2960.000         84 11840.000
185:    86,022   11.625     10,753   93.000      1,344  744.000        336 2976.000         84 11904.000
186:    85,561   11.688     10,695   93.500      1,337  748.000        334 2992.000         84 11968.000
187:    85,106   11.750     10,638   94.000      1,330  752.000        332 3008.000         83 12032.000
188:    84,656   11.813     10,582   94.500      1,323  756.000        331 3024.000         83 12096.000
189:    84,211   11.875     10,526   95.000      1,316  760.000        329 3040.000         82 12160.000
190:    83,770   11.937     10,471   95.500      1,309  764.000        327 3056.000         82 12224.000
191:    83,333   12.000     10,417   96.000      1,302  768.000        326 3072.000         81 12288.000
192:    82,902   12.063     10,363   96.500      1,295  772.000        324 3088.000         81 12352.000
193:    82,474   12.125     10,309   97.000      1,289  776.000        322 3104.000         81 12416.000
194:    82,051   12.188     10,256   97.500      1,282  780.000        321 3120.000         80 12480.000
195:    81,633   12.250     10,204   98.000      1,276  784.000        319 3136.000         80 12544.000
196:    81,218   12.313     10,152   98.500      1,269  788.000        317 3152.000         79 12608.000
197:    80,808   12.375     10,101   99.000      1,263  792.000        316 3168.000         79 12672.000
198:    80,402   12.437     10,050   99.500      1,256  796.000        314 3184.000         79 12736.000
199:    80,000   12.500     10,000  100.000      1,250  800.000        313 3200.000         78 12800.000
200:    79,602   12.562      9,950  100.500      1,244  804.000        311 3216.000         78 12864.000
201:    79,208   12.625      9,901  101.000      1,238  808.000        309 3232.000         77 12928.000
202:    78,818   12.688      9,852  101.500      1,232  812.000        308 3248.000         77 12992.000
203:    78,431   12.750      9,804  102.000      1,225  816.000        306 3264.000         77 13056.000
204:    78,049   12.813      9,756  102.500      1,220  820.000        305 3280.000         76 13120.000
205:    77,670   12.875      9,709  103.000      1,214  824.000        303 3296.000         76 13184.000
206:    77,295   12.938      9,662  103.500      1,208  828.000        302 3312.000         75 13248.000
207:    76,923   13.000      9,615  104.000      1,202  832.000        300 3328.000         75 13312.000
208:    76,555   13.062      9,569  104.500      1,196  836.000        299 3344.000         75 13376.000
209:    76,190   13.125      9,524  105.000      1,190  840.000        298 3360.000         74 13440.000
210:    75,829   13.187      9,479  105.500      1,185  844.000        296 3376.000         74 13504.000
211:    75,472   13.250      9,434  106.000      1,179  848.000        295 3392.000         74 13568.000
212:    75,117   13.313      9,390  106.500      1,174  852.000        293 3408.000         73 13632.000
213:    74,766   13.375      9,346  107.000      1,168  856.000        292 3424.000         73 13696.000
214:    74,419   13.438      9,302  107.500      1,163  860.000        291 3440.000         73 13760.000
215:    74,074   13.500      9,259  108.000      1,157  864.000        289 3456.000         72 13824.000
216:    73,733   13.563      9,217  108.500      1,152  868.000        288 3472.000         72 13888.000
217:    73,394   13.625      9,174  109.000      1,147  872.000        287 3488.000         72 13952.000
218:    73,059   13.687      9,132  109.500      1,142  876.000        285 3504.000         71 14016.000
219:    72,727   13.750      9,091  110.000      1,136  880.000        284 3520.000         71 14080.000
220:    72,398   13.812      9,050  110.500      1,131  884.000        283 3536.000         71 14144.000
221:    72,072   13.875      9,009  111.000      1,126  888.000        282 3552.000         70 14208.000
222:    71,749   13.938      8,969  111.500      1,121  892.000        280 3568.000         70 14272.000
223:    71,429   14.000      8,929  112.000      1,116  896.000        279 3584.000         70 14336.000
224:    71,111   14.063      8,889  112.500      1,111  900.000        278 3600.000         69 14400.000
225:    70,796   14.125      8,850  113.000      1,106  904.000        277 3616.000         69 14464.000
226:    70,485   14.188      8,811  113.500      1,101  908.000        275 3632.000         69 14528.000
227:    70,175   14.250      8,772  114.000      1,096  912.000        274 3648.000         69 14592.000
228:    69,869   14.312      8,734  114.500      1,092  916.000        273 3664.000         68 14656.000
229:    69,565   14.375      8,696  115.000      1,087  920.000        272 3680.000         68 14720.000
230:    69,264   14.437      8,658  115.500      1,082  924.000        271 3696.000         68 14784.000
231:    68,966   14.500      8,621  116.000      1,078  928.000        269 3712.000         67 14848.000
232:    68,670   14.563      8,584  116.500      1,073  932.000        268 3728.000         67 14912.000
233:    68,376   14.625      8,547  117.000      1,068  936.000        267 3744.000         67 14976.000
234:    68,085   14.688      8,511  117.500      1,064  940.000        266 3760.000         66 15040.000
235:    67,797   14.750      8,475  118.000      1,059  944.000        265 3776.000         66 15104.000
236:    67,511   14.813      8,439  118.500      1,055  948.000        264 3792.000         66 15168.000
237:    67,227   14.875      8,403  119.000      1,050  952.000        263 3808.000         66 15232.000
238:    66,946   14.937      8,368  119.500      1,046  956.000        262 3824.000         65 15296.000
239:    66,667   15.000      8,333  120.000      1,042  960.000        260 3840.000         65 15360.000
240:    66,390   15.062      8,299  120.500      1,037  964.000        259 3856.000         65 15424.000
241:    66,116   15.125      8,264  121.000      1,033  968.000        258 3872.000         65 15488.000
242:    65,844   15.188      8,230  121.500      1,029  972.000        257 3888.000         64 15552.000
243:    65,574   15.250      8,197  122.000      1,025  976.000        256 3904.000         64 15616.000
244:    65,306   15.313      8,163  122.500      1,020  980.000        255 3920.000         64 15680.000
245:    65,041   15.375      8,130  123.000      1,016  984.000        254 3936.000         64 15744.000
246:    64,777   15.438      8,097  123.500      1,012  988.000        253 3952.000         63 15808.000
247:    64,516   15.500      8,065  124.000      1,008  992.000        252 3968.000         63 15872.000
248:    64,257   15.562      8,032  124.500      1,004  996.000        251 3984.000         63 15936.000
249:    64,000   15.625      8,000  125.000      1,000 1000.000        250 4000.000         63 16000.000
250:    63,745   15.687      7,968  125.500        996 1004.000        249 4016.000         62 16064.000
251:    63,492   15.750      7,937  126.000        992 1008.000        248 4032.000         62 16128.000
252:    63,241   15.812      7,905  126.500        988 1012.000        247 4048.000         62 16192.000
253:    62,992   15.875      7,874  127.000        984 1016.000        246 4064.000         62 16256.000
254:    62,745   15.937      7,843  127.500        980 1020.000        245 4080.000         61 16320.000
255:    62,500   16.000      7,813  128.000        977 1024.000        244 4096.000         61 16384.000

```

A prescaler of one, being the finest, will not be adequate because you cannot get a frequency of 10 kHz (from the above table). In other words, dividing the Uno clock of 16 MHz by 256 only gives you a frequency of 62500 Hz (16000000 / 256).

Using a prescaler of 8 and a counter of 199 gives you 10 kHz: 16000000 / 8 / 200 = 10000. I say a counter of 199, and not 200, because the counters are zero-relative.

This is the finest prescaler, and thus would give you the finest duty cycle control. You still only have 256 steps of duty cycle because this is an 8-bit timer. For finer control use Timer 1, which is a 16-bit timer.
> 1 votes

---
Tags: arduino-uno, pwm
---


# Question
Title: I need a 10KHZ PWM signal from pin 3 and 11 using timer 2
The op of pin 11 should be inverse of pin 3. I used digitalreadfast and digitalwritefast and used simple if else. But the delay is high as 10us. What should i do?

I found this code in forum but its form timer 1. I need it for timer 2.

```
void setup()
  {
  // Defining PB1 and PB2 as outputs by setting PORTB1 and PORTB2
  // Setting DDB1 and DDB2
  DDRB |= bit (DDB1) | bit (DDB2);

  // stop timer 1
  TCCR1A = 0;
  TCCR1B = 0;

  TCCR1A = bit (COM1B0) | bit (COM1B1)  // Set OC1B on Compare Match, clear
                                        // OC1B at BOTTOM (inverting mode)
         | bit (COM1A1)                 // Clear OC1A on Compare Match, set
                                        // OC1A at BOTTOM (non-inverting mode)
         | bit (WGM11);                 // Fast PWM, top at ICR1
  TCCR1B = bit (WGM12)  | bit (WGM13)   //       ditto
         | bit (CS11);                  // Start timer, prescaler of 8

  // Initialize OCR1A = 300 (pulse_width = 150us), OCR1B, and ICR1
  ICR1 = 0xFFFF;
  OCR1B = 299;
  OCR1A = ICR1 - OCR1B;

  }  // end of setup

void loop()
  {
  }

```

# Answer
> 3 votes
You can't do it with Timer 2 without external hardware. This code will generate a 10 kHz signal on pin 3, however it uses both of the timer's registers to do that:

* OCR2A is used to set the period (ie. the frequency)
* OCR2B is used to set the duty cycle

#

```
const byte OUTPUT_PIN = 3;  // Timer 2 "B" output: OC2B

const byte n = 199;  // 10 kHz

void setup()
 {
  pinMode (OUTPUT_PIN, OUTPUT);

  TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2A on compare
  TCCR2B = bit (WGM22) | bit (CS21);         // fast PWM, prescaler of 8
  OCR2A =  n;                                // period
  OCR2B = ((n + 1) / 2) - 1;                 // 50% duty cycle
  }  // end of setup

void loop() { }

```

# Answer
> 2 votes
As explained in Nick Gammon's answer, you cannot really generate two PWM signals at 10 kHz from Timer 2: the register OCR2A will be used to set the frequency, and you won't have independent control of the duty cycle of the OC2A output.

You can, however, make two 10 kHz complementary signals at 50% duty cycle. This is not really PWM (pulse width *modulation*), as you cannot actually *modulate* the pulse width. If this fits your needs, the solution is to configure the outputs in *toggle* mode. Writing the “force output compare B” bit creates an extra toggle of OC2B, which ensures that the outputs have then opposing phases. Here is the code to do that:

```
void setup() {
    TCCR2B = 0;           // stop Timer 2
    TCNT2  = 0;           // reset timer
    TCCR2A = _BV(COM2A0)  // toggle OC2A on compare match
           | _BV(COM2B0)  // toggle OC2B on compare match
           | _BV(WGM21);  // mode 2 = CTC, TOP = OCRA
    OCR2A  = 99;          // timer period = 100 * 2 * 8 / C_CPU
    OCR2B  = 99;          // toggle OC2A and OC2B simultaneously
    TCCR2B = _BV(CS21)    // clock @ F_CPU/8
           | _BV(FOC2B);  // force output compare B: invert OC2B signal
    DDRB  |= _BV(PB3);    // OC2A = PB3 = digital 11 as output
    DDRD  |= _BV(PD3);    // OC2B = PD3 = digital 3 as output
}

void loop(){}

```

---
Tags: arduino-uno, pwm, timers, timing
---


# Question
Title: How are "unique IDs" generated for 1wire devices?
If I wanted to make my own 1wire device, I would need to give it a "globally unique" 48-bit identifier.

How are these identifiers generated? How can we guarantee no identifier conflicts with another brand's devices?

# Answer
Interesting question. After searching for a while I have not found a definite answer, but some good hints.

The 1-wire protocol was created by Dallas, which as later bought by Maxim Integrated. Thus the company Maxim has now control over it. They market the protocol with the explicit feature, that each device, that they manufacture, has a unique ID/serial number. They are the ones controlling it. I'm not sure how it works with other manufacturers, though this uniqueness probably only covers Maxims devices and the ones, where the respective manufacturer has a corresponding agreement with Maxim.

So you cannot be sure, that any ID you generate is unique in the group of all other devices. You can try to use a different family code in the device address (the 48bit is only a part of the actual address, together with 8 bit family code and 8 bit checksum), specifically one, that is currently not in use by Maxim. I've found this technical article with a list of 1-wire device families. It states, that it may not include all device families, but it is the only list, that I found.

As you wrote "we": Creating IDs unique to a whole industry can only be guaranteed by going into an agreement with major industry players (provided they want to do such agreements). Otherwise your guarantees are always limited. You can stay away from the most common devices (with an unused family code) and make sure, that your organization gives out each device ID only ones.
> 2 votes

---
Tags: 1-wire
---


# Question
Title: Problem in AT+CIPSEND(CTRL-Z) GPRS GMS A6
I am using GPRS GSM A6 with arduino uno to post data to web server. After sending AT commands to module I get OK response after every command,

```
AT+CIPMUX=0

OK
AT+CGATT=1

OK
AT+CSTT="internet","",""

OK
AT+CIICR

OK
AT+CIFSR

10.65.87.210

OK
AT+CIPSTART="TCP","xxx.xxx.xxx.xxx", 80

CONNECT OK

OK
AT+CIPSEND

> POST http://xxx.xxx.xxx.xxx/Code/ HTTP/1.1
Host: xxx.xxx.xxx.xxx
Content-Type: application/x-www-form-urlencoded
Content-Length: 18

Data=GPS Data Sent
AT+CIPCLOSE

>

```

To terminate AT+CIPSEND you have to send CTRL-Z. I am sending CTRL-Z using this statement in code,

```
Serial.write(0x1A)

```

But the module doesnot respond to this, and treats the next command (AT+CIPCLOSE) as data.

Please Help... Thanks in Advance!!!

# Answer
> 1 votes
RTFM: https://github.com/espressif/esp8266\_at/wiki/CIPSEND

You need to close the input steam with "+++" to return to command mode.

# Answer
> 0 votes
To terminate AT + CIPSEND just apply the next command:

```
Serial.write(26);

```

or

```
gsm.write(26);

```

where gsm is the UART channel of gsm module.

# Answer
> 0 votes
You can use AT+CIPSEND= instead of AT+CIPSEND

---
Tags: arduino-uno, serial, gsm
---


# Question
Title: Interfacing 8 ohm speaker ouput with ESP32
I'm trying to use an ISD1820 recording module with the ESP32, except I want to store the recordings and send them over Wifi rather than playing them back. The ISD1820 has an output for an 8-ohm speaker, which can be used in feedthrough mode (meaning the mic input goes directly to the output). I want to connect the 8-ohm speaker output to the ESP32 analog input, then store the recordings. How can I do that?

Please don't mention any other chips or modules. (e.g. saying "just buy a sparkfun recording module, etc.)

Thanks

# Answer
> 1 votes
Connect the output of the ISD1820 (which is connected to the 8-ohm speaker) to one of the analog input pins of the ESP32.Set up the ESP32's analog-to-digital converter (ADC) to sample the audio input from the ISD1820. Write code on the ESP32 to continuously sample the audio input from the ISD1820 using the ADC. You'll need to buffer the audio samples in memory to store them temporarily before transmission. Here is a tutorial that you may find useful:https://www.instructables.com/NodeMcu-Speak-With-ISD1820-Module/

---
Tags: esp32, electronics, input, sound, speaker
---


# Question
Title: Arduino Nano RP2040 Connect does not work with Nano Ethernet ENC28J60 shield
I modified a Robotdyn ENC28J60 shield for a 3.3 V Nano by removing the logic level conversion IC and bridging its contacts (2-3 for INT and 5-6 for MISO).

But the Nano RP2040 doesn’t start the sketch with the shield on it.

# Answer
> 1 votes
The Nano RP2040 Connect has the RP2040 BOOT pin instead of the classic's pinout RESET pin next to 5 V pin. The pin is labeled as REC.

The shield connects both RESET pins together so the RP2040 will always go into boot mode with the shield. You have to cut the pin or the PCB trace on the shield to disconnect the reset line from the BOOT pin.

pinout from www.arduino.cc

---
Tags: arduino-nano-rp2040, enc28j60
---


# Question
Title: Incorrect IP address when using Ethernet library with Arduino Uno and WizNet 5500 ethernet module
I'm trying to get an ethernet module with the W5500 chipset to connect to my network on an Arduino Uno, but whatever I do, I always get an incorrect IP address.

The module is connected as default SPI, with the CS pin on pin 10.

Initially I was using the wrong libraries (those meant for the ENC28J60), until Juraj pointed out to me that I had the W5500 chipset.

So I loaded the Ethernet WebServer example sketch in my Arduino IDE (1.8.13), changed the IP value, compiled it, and tried to run it. In my code, I set the IP to 192.168.123.225, but the serial monitor showed me IP 192.80.239.132 .

After some Googling I found a post called Ethernet library not initializing IP correctly, as well as several other pages each stating that the Ethernet2 library should be used for the W5500 chipset instead of Ethernet.

I've tried installing the Ethernet2 library from within the Arduino IDE, with the exact same result. I loaded the example sketch of this library, same result. After downloading the library from GitHub (as found on another page describing the same problem), I got some errors and commented out some sections as seen in my code below, but still with the same result.

In the commented code you can also see that I've added a check to see whether my module is actually recognized as a W5500, and it is...

So my question, while elaborate, is very simple: how can I set the IP correctly on a W5500 chipset module connected to an Arduino Uno?

Here is my code (I've left out the loop, obviously):

```
#include <SPI.h>
#include <Ethernet2.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 123, 225);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup()
{
  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);  // Most Arduino shields

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Ethernet WebServer Example");

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);

  // Check for Ethernet hardware present
  /*
  if (Ethernet.hardwareStatus() == EthernetNoHardware)
  {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true)
    {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  else
  {
    if (Ethernet.hardwareStatus() == EthernetW5500)
    {
      Serial.println("Ethernet shield is a W5500");
    }
  }

  if (Ethernet.linkStatus() == LinkOFF)
  {
    Serial.println("Ethernet cable is not connected.");
  }
  */

  // start the server
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

```

# Answer
> -1 votes
I had the same issue: a strange IP was shown. Also the LEDs of the Lan connection had a rather strange blinking: green went on for a second then off and then orange did the same. The solution for me: an external power supply with 7 V at the Vin. Apparently the Lan shield is drawing too much power for the usb power supply...

Also it is working with the standard ethernet library

---
Tags: arduino-uno, ethernet
---


title: Where can I store secret keys?

text:
# Question
Title: Where can I store secret keys?
I want to store a password in my ESP8266 program, but I can't figure out a way to do it that makes it inaccessible to hackers. Even if I encrypt it, I'd still need to store the private key for the encryption process somewhere. I only have two ideas and both have issues:

1. **As a const in program code**
The compiled binary will be publicly available, so anyone who is able to spend some time interpreting the compiled file would eventually be able to find the password stored in it.
2. **In EEPROM**
This is at least safe from people who aren't users, but any user would still be able to upload their own program and read the EEPROM to find the password.

Surely this is a common issue, especially in commercial products. What is the solution that I'm not thinking of?

# Answer
The ESP8266 is the wrong device for this. You cannot store anything inside it with protection against read-out.

Any user software is in external memory, so even hobbyists can read all of it. If you provide the binary for download (because of updates, or a DIY build), it even simplifies the read-out.

If you apply asymmetric encryption, for example via a key from an external server, you cannot stop a hacker to apply the same algorithm.

Final note: There is no such thing as absolute security. You can reach some degree, but it is hard.
> 1 votes

# Answer
As @the busybee already said, the ESP8266 is the wrong chip for such applications. Since you always have the possibility to change the firmware. You could write your own bootloader that only accepts your firmware, but this is a huge project by itself.

Encrypting the data should normally be totally ok, if the encryption algorithm is sufficiently strong.

But since you have a ESP8266, you could also transfer the data encrypted to a cloud server which manages/holds the data for you.

But with the hardware you have, it's going to be difficult to lock or hide the data in the EEPROM.

Regards Dario
> 1 votes

---
Tags: esp8266, security
---


# Question
Title: Code logic to measure values stored in buffer and created nested array
I am having a difficult time creating some logic in my code. I have a potentiometer connected to an ESP32 to simulate a load cell and a range sensor. The value for the force is between 0 and 400 newton and for the range between 50 and 0 mm. In the code I have a function that, when the position 40 mm is reached, starts the measure procedure where evenly depending on the position, the force and the correspondent position would need to be stored in a buffer. When reaching 0 mm a JSON would need to be created with the 5 measure points. If `NUM_SAMPLES` would be 5, we would start the first measure at 40 mm, the second at 30 mm, the third at 20 mm and so on. Reaching 0 mm the JSON would need to be created from the values from the buffer and printed out. The end result would need to be:

`{"range_array":[40,30,20,10,0],"force_array":[82,163,241,322,400]}.`

But now I get the JSON created and printed out continuously at 40 mm.

`{"range_array":[40,30,20,10,0],"force_array":[82,82,82,82,82]}`

If I go out from 40 mm it stops. Code follows. Thanks in advance for some help.

```
#include <Arduino.h>            // Required by platformIO
#include <ArduinoJson.h>        // JSON library for embedded C++
#include <WebSocketsServer.h>   // WebSocketServer Bibliothek

const int potPin = 14; // Analog pin connected to the potentiometer
const int rangeMin = 0; // Minimum range of the simulated sensor in mm
const int rangeMax = 50; // Maximum range of the simulated sensor in mm
const int forceMin = 0; // Minimum force of the simulated sensor in newton
const int forceMax = 400; // Maximum force of the simulated sensor in newton

int rangeValue = 0;
int range_reading = 0;
int forceValue = 0;
int force_reading = 0;

unsigned long previousMillis = 0;
const long interval = 100;

WebSocketsServer webSocket = WebSocketsServer(81);

int NUM_SAMPLES = 5;

void setup() {
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMillis = millis();

  Read_Range_Sensor();
  Read_Loadcell();

  // Check if position is 40mm, then start measurement
  if (range_reading == 40) {
    performMeasurement();
  }

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    Serial.print("Range: ");
    Serial.print(range_reading);
    Serial.print(" mm, Force: ");
    Serial.print(force_reading);
    Serial.println(" N");
  }
}

void Read_Range_Sensor() {
  rangeValue = analogRead(potPin);
  range_reading = map(rangeValue, 0, 4095, rangeMax, rangeMin);
}

void Read_Loadcell() {
  forceValue = analogRead(potPin);
  force_reading = map(forceValue, 0, 4095, forceMin, forceMax);
}

void performMeasurement() {
  // Arrays to store positions and forces
  int range_array[NUM_SAMPLES];
  int force_array[NUM_SAMPLES];

  // Start measuring from 40mm to 0mm
  for (int i = 0; i < NUM_SAMPLES; i++) {
    range_array[i] = 40 - i * (40 / (NUM_SAMPLES - 1));
    force_array[i] = map(analogRead(potPin), 0, 4095, forceMin, forceMax);
  }

  // Create JSON object
  StaticJsonDocument<200> doc;
  JsonArray rangeJson = doc.createNestedArray("range_array");
  JsonArray forceJson = doc.createNestedArray("force_array");

  // Populate JSON arrays
  for (int i = 0; i < NUM_SAMPLES; i++) {
    rangeJson.add(range_array[i]);
    forceJson.add(force_array[i]);
  }
  // Serialize JSON to string
  String jsonString;
  serializeJson(doc, Serial);
  serializeJson(doc, jsonString);
}

```

# Answer
Let me start of with a few assumptions, because this information / context is missing:

* The force will be measured across a *non-negligible* amount of time (order of milliseconds, seconds)
* The potmeter is controlled by either a human or a motor that takes some time to turn (milliseconds to seconds) it from the simulated 0N to 400N.

The codes in its current state, is just measuring the potmeter 5 times in "an instant" (a few microseconds).

I suggest that additional logic be implemented to change the potmeter to the wanted value, and *then* measure.

I also see a few more inconsistencies / illogical actions in this program, i.e. the same potmeter is used as the force and as the range. `Read_Range_Sensor` and `Read_Loadcell` perform exactly the same functionality, as `potPin` never changes.

The intention is not quite clear here (what needs to be achieved, how).
> 1 votes

---
Tags: programming
---


title: Arduino Uno/Nano + ML

text:
# Question
Title: Arduino Uno/Nano + ML
I couldn't find any clear answers elsewhere, hence I'm asking here. I have a TensorFlow/TensorFlow Lite model which I have already trained on some sensor data. Now, how can I utilize this model on my Arduino Nano/Uno to perform some other functions like moving a motor?

Any help would be appreciated!

Thanks

# Answer
> 0 votes
The documentation of Tensorflow lite states:

> The core runtime just fits in 16 KB on an Arm Cortex M3 and can run many basic models.

So the Tensorflow lite runtime itself needs 16kB of - I guess - RAM. That would be 8 times of what the Uno/Nano actually has. If they mean program memory, then it would fit, since Uno/Nano has 32kB of flash.

Though it would still not work:

> TensorFlow Lite for Microcontrollers is written in C++ 17 and requires a 32-bit platform.

The Uno/Nano uses the Atmega328p, which is an 8-bit microcontroller.

So all in all: No, you cannot use Tensorflow lite on an Uno/Nano. You should look at the "Supported Platforms" section of the linked Tensorflow Lite documentation to choose a board, that fits your needs.

---
Tags: arduino-uno, arduino-nano, sensors
---


# Question
Title: What module can I use for receiving 433.42 MHz transmissions with ASK/OOK modulation?
I am looking for a module that would be able to receive communication in the 433.42 (ch01) range with ASK/OOK modulation. Can someone recommend anything that would work and not be an expensive general purpose SDR module?

Long story: I have tried using the cheap RF 433MHz modules(picture below). I was able to modify the transmitter by de-soldering 433.92 crystal & soldering-in 433.42 one (picture two).

Now I have no way of testing this, as I am not receiving any communication while using the standard receiver that is tuned to 433.92 MHz. There doesn't seem to be any obvious way to tune the receiver to 433.42 MHz.

Reference ebay example for the crystal oscillator.

# Answer
It turns out that:

* the receiver DOES work with the different frequency when the range is sufficiently small (a couple centimetres at most)
* the library that I was using was expecting different kinds of transmissions so it wasn't showing anything useful
* only low level interrupt service routine is actually giving me access to the actual data from the module
* the issue that is complicating things with those modules is that in the absence of actual transmission noise is getting amplified and the module is outputting gibberish, so serious thinking needs to go into recognising when actual transmission starts & ends
> 0 votes

---
Tags: rf
---


# Question
Title: USART, SPI or Bit-Bang for the continuous transfer of bytes without inserted extra bits
I have heard that

1. The SPI hardware introduces a 9th, HIGH bit between bytes
2. USART still uses start and stop bits when in synchronous mode

Are both these statements true? Can I modify the built-in SPI library to avoid #1? Or will I have to bit-bang the protocol needed?

# Answer
> 1 votes
> Are both these statements true?

Neither of those statements are true.

SPI never inserts extra bits. That would break everything if it did. What you are probably seeing (or think you are seeing) is a delay between bytes being sent. That delay is irrelevant, since the data is only ever sampled on an edge of the clock signal (which edge depends on the mode of the SPI communication) and with no clock edge in that delay period there is no data.

USART in synchronous mode is SPI. There are no start or stop bits in synchronous mode, since the clock is used to synchronise the communication rather than needing start or stop bits.

# Answer
> 1 votes
The SPI peripheral on the ATMega328 cannot continuously send data without a brief pause after every byte, as it does not sample the input buffer immediately after clocking the last bit, no matter what settings are used. At best, you can clock out bytes at the speed you expect +2 clocks when using assembler. The UART does allow continuous streaming of data, and should be used for maximum speed if you do not also need the clock signal. I have tested this with cycle-counted code, setting the SPI peripheral to 8Mhz (its maximum speed with a 16Mhz crystal, as the Arduino UNO uses). With the UART, using a 16 cycle loop in ASM, it's possible to load it with data continuously (I have used this to generate composite video). With the SPI peripheral, you need to add 2 clocks after the peripheral finishes, before it can load the next byte. So at 8Mhz, you can load data into it every 18 clock cycles. This is why it may appear to be clocking out 9 bits instead of 8, if you don't take account of the clock signal.

---
Tags: atmega328, spi, uart
---


# Question
Title: interrupt from a button and wait until serial port 1 has a message
I'm a little bit loss because I'm learning how to use the interruptions on Arduino. I'm creating a program to read an RFID code that arrives if an RFID transmitter is close to the antenna (a little antenna board RFID). I have two operating modes: one where I associate my board to an RFID, so I will act only where my RFID code is identified ( I save the RFID code on the board). and another mode where I read all the RFID codes and I save it.

I have one configuration step where if the user push a button, I want to wink a led to indicate that we are waiting for the presentation of the RFID code to associate to the board. I try to make a code and I have some problems to get out of the condition where I'm waiting for the RFID code (serial1).

Here is my code:

```
#include <Wire.h>

//const int reception_rfid = 15;
const int btnAssociation = 2; // bouton pour indiquer que l'on souhaite faire l'appareillage des RFID (interruption)
const int SwitchModeConfig = 4;
const int LedAssociationEnCours = A0;

int compteurLedAsso;

const int BUFFER_SIZE_RFID = 13;
char buf[BUFFER_SIZE_RFID];

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(SwitchModeConfig, INPUT_PULLUP);
  pinMode(btnAssociation, INPUT_PULLUP);
  pinMode(LedAssociationEnCours, OUTPUT);
  ConfigurationAssociation();
  digitalWrite(LedAssociationEnCours, HIGH);
}

void loop() {
  delay(100);
}

void ConfigurationAssociation(){
  int stateSwitch = digitalRead(SwitchModeConfig);
  if(stateSwitch == LOW){
      attachInterrupt(digitalPinToInterrupt(btnAssociation), InterruptAssociation, RISING);
      Serial.println("Mode association");
    }else{
      detachInterrupt(digitalPinToInterrupt(btnAssociation));
      Serial.println("Mode aleatoire");
    }
}

void InterruptAssociation(){
  compteurLedAsso = 0;
    Serial.println("Ouverture de l'Association d'un code RFID");
    while (Serial1.available() == 0 && compteurLedAsso <= 600)
    {
      // clignoter la led rouge sur A0
      digitalWrite(LedAssociationEnCours, LOW);
      delay(5000);
      digitalWrite(LedAssociationEnCours, HIGH);
      delay(5000);
      compteurLedAsso++;
      Serial.println(compteurLedAsso);
    }

    if(Serial1.available() > 0){
      int codeRFID = Serial1.readBytes(buf, BUFFER_SIZE_RFID);
      Serial.println("CodeRFID: ");
      for(int i = 0; i < codeRFID; i++)
        Serial.print(buf[i]);
    }
      //Serial.println(compteurLedAsso);
      //compteurLedAsso++;
    Serial.println("Fin de l'attente code RFID");
}

void requestEvent() {

}

```
1. First problem: I know that when we are inside a interruption we can't count the time pass on a while, I would like to wink the led 2 minutes: waiting the presentation of the RFID code to save and once the 2 minutes pass away I get out of the interruption. How make to wait 2 minutes for RFID code on serial1 port inside an interruption? my reception RFID board works fine and TX is connected to RX1 (pin 19) of Arduino mega (I verify on another code where reading RFID works)
2. Second problem: when my board is inside the interruption that comes from a push button (connected on pin 2) I stay always on the while loop even when my RFID transmitter is reading an RFID code, I can't get out of and I don't know why! maybe you can help to understand and find a solution please?

# Answer
> 3 votes
The thing is: Inside an ISR (Interrupt Service Routine) not only does time measuring with `millis()` not work, `delay()` also won't work (it uses the same interrupt mechanism as `millis()` in the background). Neither does anything else, that depends on their own ISR to execute - like receiving serial data. The hardware Serial interface can receive single bytes without depending on interrupts, but to get these bytes into the buffer (and to actually use them via `Serial`) you need to let other ISRs execute.

You should NEVER write an ISR, which executes for a long time. Keep it in the microseconds, maximum in the very low millisecond range. How long you can get here until you see negative effects depends on other factors. You really should only do minimal work in an ISR and the rest in the main code.

A common code structure for this looks as follows:

* In your main code you don't use any `delay()` calls. Everything timed should be done with `millis()` (like in the `BlinkWithoutDelay` example that comes with the Arduino IDE), so that it won't block execution. Also no long loops inside of `loop()`. Make sure, that your `loop()` function can iterate freely and fast.
* In global scope you define a flag variable. A simple one byte variable, marked as `volatile`.
* In your ISR you are doing nothing but setting this variable. Depending on your situation you might wanna set it depending on an digital input via `digitalRead()`, which is still fast, so OK to do.
* In your main code you use an `if` statement to check for this flag variable to be set. On most `loop()` iterations this won't be executed. Only, if the flag variable got set inside the ISR, it will get executed. This is the place where you write the code handling the event. At the end of the block you then only need to reset the flag variable, so that you are ready for the next interrupt to happen.

This would look somewhat like this:

```
int button_pin = 2;
volatile bool button_flag = false;

void setup(){
  pinMode(button_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(button_pin), button_ISR, RISING);
}

void loop(){
  if(button_flag){
    // Handle interrupt here
    button_flag = false; // Reset flag variable to be ready for next interrupt
  }
}

void button_ISR(){
  button_flag = true;
}

```

Note, that the `button_flag` variable is defined as `volatile`, so that the compiler doesn't cache its value is some register and instead always reads the actual current value of it (not optimizing it).

In your code you should probably use another coding concept named Finite State Machine (FSM). This is the easiest method to implement a code with different states/stages while still keeping it non-blocking. You can read up about FSMs on the web (or for example in my answer to this question).

The gist is, that you use a variable, that represents the state, that your code is currently in. In `loop()` you then only ever execute the code for the current state. Changing to a different state is done by setting the state variable. The state, that your current code needs, are probably `CHECK_FOR_SINGLE_RFID_TAG` and `ASSOCIATE_SINGE_RFID_TAG` (though you can name these like you want). A simple FSM with this can look like the following:

```
#define CHECK_FOR_SINGLE_RFID_TAG 0
#define ASSOCIATE_SINGLE_RFID_TAG 1

// single byte variable so that we don't need to bother about atomic reads/writes
uint8_t state = CHECK_FOR_SINGLE_RFID_TAG;

void loop(){
  switch(state){
    case CHECK_FOR_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here, check the RFID tag ID against the saved one
        // and execute code accordingly
      }
      break;

    case ASSOCIATE_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here and save the new RFID tag ID in a variable
        // then reset the state variable to automatically go back to check mode
        // after the new RFID tag is enrolled
        state = CHECK_FOR_SINGLE_RFID_TAG;
      }
      // Use the BlinkWithoutDelay idiom to blink your LED non-blocking
      // something like
      // if(millis() - led_timestamp > led_interval){
      //   digitalWrite(led, !digitalRead(led));
      // }
      break;
  }
}

```

You see, how we define out possible states, save the current one in a variable and act according to it inside of `loop()`? This concept is really powerful, so it is totally worth it to learn.

---

Note: I've used a variable of type `uint8_t` (a single byte) to keep this interrupt safe (you can read up about this by searching for something like `arduino interrupt atomic read` or `arduino interrupt safe variable`) for the next part and the defines to give each value a readable name. You could use an `enum` for that, though while writing this I got on a tangent about the size of an `enum`, which seems 16 bits on AVR (like the Arduino Mega), unless you use a specific compiler flag, according to this blog article. This explanation is not that important for you right now, but I also wanted to explain, why this doesn't use enums.

---

Now we can combine this with our interrupt code from above. In this case we don't need a seperate flag variable anymore. We can directly set the `state` variable inside the ISR:

```
#define CHECK_FOR_SINGLE_RFID_TAG 0
#define ASSOCIATE_SINGLE_RFID_TAG 1

volatile uint8_t state = CHECK_FOR_SINGLE_RFID_TAG;

int button_pin = 2;

void setup(){
  pinMode(button_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(button_pin), button_ISR, RISING);
  Serial.begin(115200);
  Serial1.begin(115200);
}

void button_ISR(){
  state = ASSOCIATE_SINGLE_RFID_TAG;
}

void loop(){
  switch(state){
    case CHECK_FOR_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here, check the RFID tag ID against the saved one
        // and execute code accordingly
      }
      break;

    case ASSOCIATE_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here and save the new RFID tag ID in a variable
        // then reset the state variable to automatically go back to check mode
        // after the new RFID tag is enrolled
        state = CHECK_FOR_SINGLE_RFID_TAG;
      }
      // Use the BlinkWithoutDelay idiom to blink your LED non-blocking
      // something like
      // if(millis() - led_timestamp > led_interval){
      //   digitalWrite(led, !digitalRead(led));
      // }
      break;
  }
}

```

You can see, the `button_ISR()` is very small, thus very fast. And our `loop()` also runs unblocked, so the next iteration of it will come very fast and it will then execute the state, that we set in the ISR.

Note: When reading from `Serial`, make sure, that you don't use functions, that block for a long time. For example `Serial.readString()` will take 1s to execute (since that is the default timeout), which would block the non-blocking code (no good).

# Answer
> 3 votes
chrisl's answer brings many excellent points, and I highly recommend you study it in detail. There are just a few points I would personally add or amend:

* an ISR should probably not last more than a few tens of microseconds, and many bad things could happen during a 1 ms ISR (missed clock tics, lost serial input...)
* a `loop()` iteration should not take more than a few milliseconds
* there is no point in using an interrupt for reading a button: the user will keep the button pressed for many milliseconds, and you will have many opportunities for catching it in `loop()`; interrupts bring complexity that is only worth it when you have to deal with sub-millisecond timings
* do not worry about the size of an `enum` unless you need to care about sub-**micro**second timings

Now, my take at this problem. The first step is to define the state machine. I may call the states `NORMAL` and `ASSOCIATION`. The transitions would be:

* `NORMAL``ASSOCIATION` when a button press is detected
* `ASSOCIATION``NORMAL` when either an RFID code is read or after a timeout

My tentative implementation:

```
// Attempt to read an RFID without blocking.
// Returns the found RFID code as a pointer to a NUL-terminated buffer,
// or nullptr if no RFID is available right now.
char *read_rfid() {
    // Implementation left as an exercise to the reader.
}

void loop() {
    static enum {NORMAL, ASSOCIATION} state;
    static uint32_t started_association;  //  association start time

    char *rfid = read_rfid();
    switch (state) {
        case NORMAL:
            if (rfid) {
                Serial.print("Read RFID code: ");
                Serial.println(rfid);
            }
            if (digitalRead(btnAssociation) == LOW) {
                Serial.println("Starting association");
                mode = ASSOCIATION;
                started_association = millis();
            }
            break;
        case ASSOCIATION:
            if (rfid) {
                assocate_rfid(rfid);
                Serial.println("Association successful, code: ");
                Serial.println(rfid);
                mode = NORMAL;
            }
            if (millis() - started_association >= assocation_timeout) {
                Serial.println("Association timeout");
                mode = NORMAL;
            }
            break;
    }
}

```

There are a few things I left out here, most notably:

* The LED blinking, which should be done in the style of the Blink Without Delay example
* The function `read_rfid()` that reads the serial port in a non-blocking fashion. For this, you will need to have a rule for deciding when a message is complete. This could be a message terminator (if the reader does send one) or a timeout.

Finally, I would recommend you read a couple of blog posts by Majenko:

---
Tags: serial, arduino-mega, interrupt
---


# Question
Title: Bad symbols in the serial monitor when connected via USB 3.0
I tested DHT11 + Arduino Uno with a very basic example sketch. The Arduino board was connected to USB 3.0 and sometimes I saw incorrect symbols in the serial monitor, e. g. "Humidit?: \_7%" instead of "Humidity: 37%". This strange effect disappears when I connected the board to USB 2.0. Baudrate in code was always same as baudrate in the terminal settings.

When I increase baudrate I see less bad symbols but they not disappear while Arduino connected to USB 3.0.

The OS is Ubuntu 20, this was the first time I connect the board to USB 3.0. Is this behavior normal?

The sketch:

```
/**
 * DHT11 Sensor Reader
 * This sketch reads temperature and humidity data from the DHT11 sensor and prints the values to the serial port.
 * It also handles potential error states that might occur during reading.
 *
 * Author: Dhruba Saha
 * Version: 2.1.0
 * License: MIT
 */

// Include the DHT11 library for interfacing with the sensor.
#include <DHT11.h>

// Create an instance of the DHT11 class.
// - For Arduino: Connect the sensor to Digital I/O Pin 2.
// - For ESP32: Connect the sensor to pin GPIO2 or P2.
// - For ESP8266: Connect the sensor to GPIO2 or D4.
DHT11 dht11(4);

void setup() {
  // Initialize serial communication to allow debugging and data readout.
  // Using a baud rate of 9600 bps.
  Serial.begin(9600);

  // Uncomment the line below to set a custom delay between sensor readings (in milliseconds).
  // dht11.setDelay(1500); // Set this to the desired delay. Default is 500ms.
}

void loop() {
  int temperature = 0;
  int humidity = 0;

  // Attempt to read the temperature and humidity values from the DHT11 sensor.
  int result = dht11.readTemperatureHumidity(temperature, humidity);

  // Check the results of the readings.
  // If the reading is successful, print the temperature and humidity values.
  // If there are errors, print the appropriate error messages.
  if (result == 0) {
    Serial.print("Temperature: ");
    Serial.print(temperature);
    Serial.print(" °C\tHumidity: ");
    Serial.print(humidity);
    Serial.println(" %");
  } else {
    // Print error message based on the error code.
    Serial.println(DHT11::getErrorString(result));
  }
}

```

# Answer
> -1 votes
Please check if there is any baud rate mismatch. I mean, you have defined serial.begin(9600) in your code. Open the serial monitor selecting the same baud rate please. If that is not the problem, please check the cable. If you have any other operating system, like windows, please check your whole setup with that too.

---
Tags: arduino-uno, serial, usb
---


# Question
Title: if statement for changing serial output breaks the integer used for rest of code
I want to get back in to coding so i am re-teaching myself some basics before i tackle a bigger project. This fault is confusing the *.* out of me.

I have modified the fading LED code from the beginner pages to now include a dual colour led and now serial and lcd screen output of the current state of the led. (My project will include all of these hence the combo).

All was well with the fading led. It starts off, fades up in green, when at max brightness, turns off green, switches to red then fades down. Switches back to green and repeats.

Then i added serial and LCD output and now, the led colour part of the code breaks when ever i try and reference the currently active led pin to write that colour (As a string) to serial.

My code is below.

```
#include <LiquidCrystal_I2C.h> ///LCD library

int ledr = 6;         // the PWM pin the red LED is attached to
int ledg = 5;         // the PWM pin the green LED is attached to
int led;              // the active LED pin
int brightness = 0;   // how bright the LED is
int fadeAmount = 10;  // how many points to fade the LED by
//char colour;           // to use for displaying led colour as string in serial and lcd
LiquidCrystal_I2C lcd(0x27, 20, 4); //I2C LCD display address 0x27 with 20 cells x 4 rows display

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  pinMode(led, OUTPUT);                                   // setup pin for led
  Serial.begin(9600);                                     // start serial
  analogWrite(13, 0);                                     // turn off led 13
//  Serial.println("Green fade up - Red fade down");       // write this to serial
//  delay(1000);                                           // wait 1 sec to see it in serial
  led = ledg;                                             // set led active pin to ledg

  }

void loop() {
  if (brightness <= 0) {                // if brightness <= 0,
  led = ledg;                           // set active led to ledg (green)
//  colour = 'Green';
 };

  if (brightness >= 255) {              // if brightness >=255, turn off last led (ledg, green), acivate ledr (red) with one cycle crossover.
  led = ledr ;                          // set active led to ledr (red)
  analogWrite(led, 255);                // set active led (ledr, red) to 100%
  led = ledg;                           // set active led to ledg (green)
 analogWrite(led, 0);                   // set active led ledg (green) to off
 led = ledr;
// colour = 'Red';                            // set led to ledr (red)

 };

  analogWrite(led, brightness);         // set active led to current brightness

  brightness = brightness + fadeAmount; // change the brightness for next time through the loop:

  if (brightness <= 0 || brightness >= 255) {   // reverse the direction of the fading at the ends of the fade:
    fadeAmount = -fadeAmount;
  };

                                   // below is outout to serial
  Serial.print(led);               // print the current active led pin and brightness to serial in the format (pin" - "brightness")
  Serial.print("  -  ");           // print " - "
//  Serial.print(colour);            // print the current colour of the led

// if (led = 5); {
//  Serial.print("Green");
//   };

//if (led = 6); {
// Serial.print("Red");
//  };

  Serial.print("  -  ");          // print " - "
  Serial.println(brightness);     // print the brightnesss of the led

                                  // below is outout to LCD
  lcd.setCursor(0, 0);            // move cursor the first row
  lcd.print("LED Pin + Colour");  // print message on the first row
  lcd.setCursor(0, 1);            // move cursor to the second row
  lcd.print(led);                 // print active led pin on the second row then
  lcd.print(" : ");               // print "+" then
//  led.print(colour);              // print the colour of the currently active led
  lcd.setCursor(0, 2);            // move cursor to the third row
  lcd.print("LED PWM (0-255)");   // print message on the third row
  lcd.setCursor(0, 3);            // move cursor to the fourth row

  if (brightness <= 99) {         // if to check for <100 brightness value and clear 3rd cell if true.
    lcd.setCursor(2, 3)  ;        // move cursor to line 4, cell 3
    lcd.print(" ");               // clear cell
    };                            // end if

  lcd.setCursor(0,3);             //move cursor back to start of row 4
  lcd.print(brightness);          // print message the fourth row
  delay(50);                      // wait for (x) milliseconds to slow the dimming effect
}

```

Please ignore the references to **char colour**. thats a different issue i'm having :(

When i un-comment either or both of the if statements below \** Serial.print(colour); \** it breaks. the led still fades in and out but the colour change stops working and it will only fade using the colour of the if statement i'm using.

Below is a good led switch without either if statements active Led 6 (red) fades out and led 5 (green) fades up

```
6  -    -  40
6  -    -  30
6  -    -  20
6  -    -  10
6  -    -  0
5  -    -  10
5  -    -  20
5  -    -  30
5  -    -  40

```

Below is with the first if active active

```
5  -  Green  -  40
5  -  Green  -  30
5  -  Green  -  20
5  -  Green  -  10
5  -  Green  -  0
5  -  Green  -  10
5  -  Green  -  20
5  -  Green  -  30
5  -  Green  -  40

```

(green (string) is now shown as the if is active). Green (5) was on when it should have been red. Same thing with only the other if active but it would have been Red.

with both active,

```
6  -  GreenRed  -  40
6  -  GreenRed  -  30
6  -  GreenRed  -  20
6  -  GreenRed  -  10
6  -  GreenRed  -  0
5  -  GreenRed  -  10
6  -  GreenRed  -  20
6  -  GreenRed  -  30
6  -  GreenRed  -  40

```

Now, both colours are displayed despite the if statements and apart from the brief switch from 6 to 5 and back to 6 (It is supposed to, see code), the led is stuck on pin 6 (red)

I have tried if/else and two if statements and it has no effect. from what i can tell, it is just the reference to (led = 5) or (led = 6) that causes the issue.

please help. I've spent 2 days trying to work it out and i am not very very confused.

Thanks.

# Answer
You have an issue with = vs. ==. One equal sign for assignment, two for comparison. You also shouldn't have a semicolon on an if statement. That semicolon acts as the only thing controlled by the if. It translates to "if this then do nothing". You want the stuff in brackets to be controlled by the if statement. So no semicolon.

```
 if (led == 5) {
  Serial.print("Green");
 }

```
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Can I make this changes to this diagram of a ESP32-CAM?
Have a good day! I am kinda new with electronics circuits, and therefore I got some doubts about this diagram of a ESP32-CAM

I want to use a 5V instead of 3.3V. Do i need to add some resistors or capacitors to do so?

If the on-off switch is for turn on/off the device? the push switch. Its a button that when GPIO13 receaves changes on his signal activate a code (I mean, does it act like a button code activator) If its not how can I put a button so the ESP32-CAM start /stop filming?

Thank you

I got the image from this source http://technoreview85.blogspot.com/2019/08/ESP32spycam.html

# Answer
> 0 votes
The ESP32-CAM can be powered via the 3.3V or 5V pins. It is safe to apply 5V to the ESP32 Vcc pin. Just make sure that no other ESP32 pin is exposed to a voltage over 3.3V.

---
Tags: esp32, camera
---


# Question
Title: Translating analogWrite() into PWM duty cycle formula
We can use the function `analogWrite(int x)` for digital pins which support PWM because any microcontroller has a built in PWM generator.For given `x` and for Arduino Uno which is the formula to calculate the duty cycle of the generated PWM signal?Thanks

# Answer
> 4 votes
On pins 5 and 6 (those controlled by Timer 0):

* duty cycle = (x+1)/256, except for x = 0, which gives a duty cycle of 0.

On the other PWM pins:

* duty cycle = x/255

The difference comes from the fact that Timer 0, which provides the timing for `millis()`, `micros()` and `delay()`, is configured in “fast PWM” mode, while the other timers are in “phase correct PWM”

# Answer
> 0 votes
Duty Cycle= (x/255)×100%

x is the value passed to the analogWrite() function, ranging from 0 to 255. Duty Cycle is expressed as a percentage, representing the fraction of time the signal is on compared to the total period of the PWM signal.

---
Tags: arduino-uno, pwm
---


# Question
Title: Whats the MPPZ 3610 on Arduino nano every
I'm curious what's the MPPZ chip on my Arduino nano everu

# Answer
From Arduino Nano Every datasheet:

> MPM3610 (DC-DC)
>
> * Regulates input voltage from up to 21V with a minimum of 65% efficiency @minimum load
> * More than 85% efficiency @12V
> 1 votes

---
Tags: arduino-nano-every
---