message:
Locally declared variable takes up global variable space in dynamic memory/SRAM

I'm trying to make my Arduino Uno control the air conditioner by recording the raw IR signal of several of the AC remotes temperatures using AnalysisIR. However these IR codes are quite long (array with 343 items).

Declaring more than one IR code in a variable shows me the error:
"Global variables use 2064 bytes (100%) of dynamic memory, leaving -16 bytes for local variables. Maximum is 2048 bytes."

However, as seen in my code, I have declared the IR codes locally in a separate function to send them to the air conditioner. I don't understand why i get the error saying the global variables are taking up too much dynamic memory.

Isn't the space taken up by the local variable supposed to be freed up from the SRAM once the functions runs because I have declared the variable locally?

Thanks in advance.

Code:

<!-- language-all: c++ -->

    #include <IRremote.h>

    IRsend irsend;

    int khz = 38;

    void send23()
    {

      unsigned int irSignal[]= {9048, 4496, 620, 1636, 620, 1636, 620, 520, 620, 520, 620, 524, 624, 524, 620, 532, 620, 1648, 620, 508, 620, 1640, 620, 1644, 620, 520, 620, 528, 616, 528, 620, 532, 624, 516, 620, 1636, 620, 516, 616, 520, 620, 520, 620, 524, 620, 528, 616, 536, 620, 520, 620, 508, 620, 1640, 620, 520, 620, 520, 620, 1648, 620, 1656, 620, 1656, 616, 524, 620, 508, 620, 516, 616, 520, 620, 520, 624, 520, 620, 528, 620, 532, 620, 520, 620, 508, 624, 508, 624, 516, 616, 520, 624, 524, 620, 524, 620, 532, 620, 504, 620, 7956, 616, 512, 620, 1640, 616, 520, 620, 520, 620, 524, 620, 528, 620, 528, 624, 1644, 620, 1636, 616, 1640, 624, 1640, 620, 1648, 616, 528, 620, 1652, 620, 532, 620, 520, 620, 512, 620, 512, 620, 516, 620, 524, 620, 524, 616, 528, 620, 532, 620, 520, 620, 508, 620, 512, 624, 512, 620, 520, 620, 520, 620, 528, 620, 532, 620, 520, 620, 508, 620, 516, 620, 516, 620, 520, 620, 524, 620, 524, 624, 528, 624, 516, 620, 508, 620, 512, 624, 512, 624, 516, 624, 520, 624, 524, 624, 528, 620, 520, 624, 504, 624, 512, 620, 516, 624, 516, 620, 524, 620, 524, 624, 528, 620, 520, 624, 504, 624, 1636, 624, 1640, 624, 1640, 624, 1648, 620, 524, 624, 1656, 624, 1624, 624, 7952, 616, 512, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 624, 524, 624, 520, 624, 504, 624, 1636, 624, 512, 624, 516, 624, 520, 624, 524, 624, 524, 628, 516, 624, 504, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 620, 528, 628, 512, 624, 508, 624, 508, 624, 512, 620, 520, 620, 524, 624, 520, 624, 528, 624, 516, 620, 508, 624, 508, 624, 512, 624, 1640, 624, 520, 624, 524, 624, 528, 624, 512, 628, 504, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 624, 528, 624, 516, 620, 508, 624, 1632, 628, 508, 628, 1640, 624, 520, 624, 524, 620, 528, 624, 500, 608};
      irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); //Note the approach used to automatically calculate the size of the array.
    }

    void send22()
    {

      unsigned int irSignal[]=  {8988, 4548, 572, 1688, 572, 1688, 600, 532, 572, 568, 572, 572, 576, 572, 572, 580, 572, 1724, 544, 556, 576, 1684, 600, 1660, 608, 532, 604, 540, 608, 540, 600, 548, 608, 536, 604, 1652, 608, 520, 616, 524, 608, 532, 612, 532, 612, 532, 620, 532, 616, 524, 620, 512, 616, 1644, 624, 508, 628, 516, 624, 520, 628, 1676, 596, 1648, 632, 508, 632, 500, 632, 500, 632, 504, 636, 504, 636, 512, 628, 516, 632, 524, 628, 508, 636, 496, 632, 504, 628, 508, 632, 508, 632, 512, 632, 516, 632, 516, 632, 496, 628, 7948, 628, 500, 632, 1656, 600, 508, 628, 508, 632, 512, 632, 516, 632, 524, 628, 1636, 632, 496, 632, 504, 632, 504, 632, 508, 632, 1672, 600, 1672, 600, 520, 632, 508, 632, 500, 652, 480, 632, 504, 632, 512, 628, 512, 632, 516, 632, 520, 632, 508, 632, 496, 632, 504, 632, 504, 632, 508, 632, 516, 628, 520, 628, 520, 656, 484, 632, 500, 656, 476, 656, 480, 632, 508, 632, 516, 632, 512, 656, 496, 632, 508, 632, 500, 652, 480, 632, 504, 656, 484, 656, 488, 632, 516, 632, 520, 632, 508, 632, 500, 656, 476, 632, 508, 656, 484, 656, 488, 656, 492, 632, 520, 656, 484, 656, 1632, 624, 476, 632, 508, 656, 484, 656, 1620, 652, 488, 656, 1656, 600, 1648, 604, 7948, 656, 472, 656, 476, 660, 480, 632, 508, 656, 488, 652, 496, 656, 492, 656, 484, 632, 500, 656, 1608, 628, 504, 656, 484, 656, 488, 656, 492, 656, 496, 656, 484, 632, 496, 656, 480, 632, 504, 656, 484, 656, 488, 632, 516, 656, 496, 628, 508, 660, 472, 656, 480, 656, 480, 652, 488, 656, 488, 656, 492, 652, 496, 660, 484, 656, 472, 632, 504, 652, 484, 652, 1644, 624, 488, 656, 492, 656, 492, 632, 512, 628, 500, 664, 468, 656, 480, 656, 488, 652, 488, 656, 492, 656, 492, 632, 512, 652, 476, 656, 1632, 624, 484, 652, 1644, 620, 492, 656, 488, 628, 524, 652, 472, 608};
      irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); //Note the approach used to automatically calculate the size of the array.
    }

    void setup()
    {
      Serial.begin(9600);
      pinMode(13,OUTPUT);
      delay(2000);
      send23();
      delay(2000);
      send22();
    }

    void loop() {

    }

EDIT 05/07:

Here is my new code with the use of PROGMEM.

As you can see, i have initialized the progmem arrays globally at the top of the program. When i do this, my SRAM is not full anymore but sendraw in the functions does not work anymore.

Weirdly however, when i declare the progmem variable INSIDE the send23() function (IN COMMENTS), the sendraw works! But the variable takes up space in the SRAM again and it says that Global variables have used 100% of dynamic memory.

Why does this happen and what can i do to work around it?

PROGMEM updated code:

    #include <IRremote.h>

    const unsigned int irSignal23[] PROGMEM = {9048, 4496, 620, 1636, 620, 1636, 620, 520, 620, 520, 620, 524, 624, 524, 620, 532, 620, 1648, 620, 508, 620, 1640, 620, 1644, 620, 520, 620, 528, 616, 528, 620, 532, 624, 516, 620, 1636, 620, 516, 616, 520, 620, 520, 620, 524, 620, 528, 616, 536, 620, 520, 620, 508, 620, 1640, 620, 520, 620, 520, 620, 1648, 620, 1656, 620, 1656, 616, 524, 620, 508, 620, 516, 616, 520, 620, 520, 624, 520, 620, 528, 620, 532, 620, 520, 620, 508, 624, 508, 624, 516, 616, 520, 624, 524, 620, 524, 620, 532, 620, 504, 620, 7956, 616, 512, 620, 1640, 616, 520, 620, 520, 620, 524, 620, 528, 620, 528, 624, 1644, 620, 1636, 616, 1640, 624, 1640, 620, 1648, 616, 528, 620, 1652, 620, 532, 620, 520, 620, 512, 620, 512, 620, 516, 620, 524, 620, 524, 616, 528, 620, 532, 620, 520, 620, 508, 620, 512, 624, 512, 620, 520, 620, 520, 620, 528, 620, 532, 620, 520, 620, 508, 620, 516, 620, 516, 620, 520, 620, 524, 620, 524, 624, 528, 624, 516, 620, 508, 620, 512, 624, 512, 624, 516, 624, 520, 624, 524, 624, 528, 620, 520, 624, 504, 624, 512, 620, 516, 624, 516, 620, 524, 620, 524, 624, 528, 620, 520, 624, 504, 624, 1636, 624, 1640, 624, 1640, 624, 1648, 620, 524, 624, 1656, 624, 1624, 624, 7952, 616, 512, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 624, 524, 624, 520, 624, 504, 624, 1636, 624, 512, 624, 516, 624, 520, 624, 524, 624, 524, 628, 516, 624, 504, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 620, 528, 628, 512, 624, 508, 624, 508, 624, 512, 620, 520, 620, 524, 624, 520, 624, 528, 624, 516, 620, 508, 624, 508, 624, 512, 624, 1640, 624, 520, 624, 524, 624, 528, 624, 512, 628, 504, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 624, 528, 624, 516, 620, 508, 624, 1632, 628, 508, 628, 1640, 624, 520, 624, 524, 620, 528, 624, 500, 608};
    const unsigned int irSignal22[] PROGMEM = {8988, 4548, 572, 1688, 572, 1688, 600, 532, 572, 568, 572, 572, 576, 572, 572, 580, 572, 1724, 544, 556, 576, 1684, 600, 1660, 608, 532, 604, 540, 608, 540, 600, 548, 608, 536, 604, 1652, 608, 520, 616, 524, 608, 532, 612, 532, 612, 532, 620, 532, 616, 524, 620, 512, 616, 1644, 624, 508, 628, 516, 624, 520, 628, 1676, 596, 1648, 632, 508, 632, 500, 632, 500, 632, 504, 636, 504, 636, 512, 628, 516, 632, 524, 628, 508, 636, 496, 632, 504, 628, 508, 632, 508, 632, 512, 632, 516, 632, 516, 632, 496, 628, 7948, 628, 500, 632, 1656, 600, 508, 628, 508, 632, 512, 632, 516, 632, 524, 628, 1636, 632, 496, 632, 504, 632, 504, 632, 508, 632, 1672, 600, 1672, 600, 520, 632, 508, 632, 500, 652, 480, 632, 504, 632, 512, 628, 512, 632, 516, 632, 520, 632, 508, 632, 496, 632, 504, 632, 504, 632, 508, 632, 516, 628, 520, 628, 520, 656, 484, 632, 500, 656, 476, 656, 480, 632, 508, 632, 516, 632, 512, 656, 496, 632, 508, 632, 500, 652, 480, 632, 504, 656, 484, 656, 488, 632, 516, 632, 520, 632, 508, 632, 500, 656, 476, 632, 508, 656, 484, 656, 488, 656, 492, 632, 520, 656, 484, 656, 1632, 624, 476, 632, 508, 656, 484, 656, 1620, 652, 488, 656, 1656, 600, 1648, 604, 7948, 656, 472, 656, 476, 660, 480, 632, 508, 656, 488, 652, 496, 656, 492, 656, 484, 632, 500, 656, 1608, 628, 504, 656, 484, 656, 488, 656, 492, 656, 496, 656, 484, 632, 496, 656, 480, 632, 504, 656, 484, 656, 488, 632, 516, 656, 496, 628, 508, 660, 472, 656, 480, 656, 480, 652, 488, 656, 488, 656, 492, 652, 496, 660, 484, 656, 472, 632, 504, 652, 484, 652, 1644, 624, 488, 656, 492, 656, 492, 632, 512, 628, 500, 664, 468, 656, 480, 656, 488, 652, 488, 656, 492, 656, 492, 632, 512, 652, 476, 656, 1632, 624, 484, 652, 1644, 620, 492, 656, 488, 628, 524, 652, 472, 608};
    const unsigned int irSignal21[] PROGMEM = {9044, 4496, 624, 1628, 628, 1592, 668, 508, 628, 512, 628, 516, 628, 520, 628, 524, 628, 1636, 632, 500, 628, 1632, 624, 1636, 628, 512, 628, 520, 628, 516, 628, 524, 628, 512, 628, 1628, 628, 512, 620, 512, 624, 516, 628, 516, 628, 520, 628, 524, 628, 512, 628, 500, 632, 1628, 628, 512, 628, 512, 628, 1644, 628, 520, 628, 1648, 628, 512, 628, 504, 624, 508, 628, 508, 632, 508, 628, 516, 632, 516, 628, 524, 628, 512, 628, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 500, 624, 7948, 628, 504, 628, 1628, 628, 512, 624, 516, 624, 516, 628, 520, 628, 524, 628, 1636, 628, 504, 624, 1632, 628, 508, 628, 512, 628, 1640, 628, 1648, 628, 520, 628, 512, 628, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 516, 628, 524, 628, 512, 628, 500, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 520, 628, 512, 628, 500, 632, 504, 628, 508, 628, 512, 624, 520, 624, 520, 628, 524, 624, 516, 624, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 520, 628, 512, 628, 504, 628, 504, 628, 508, 624, 516, 628, 512, 628, 520, 628, 524, 624, 516, 628, 1624, 628, 1632, 628, 508, 628, 512, 628, 516, 628, 1644, 628, 1648, 628, 1620, 628, 7944, 628, 500, 628, 504, 628, 512, 624, 512, 628, 516, 628, 520, 628, 520, 628, 512, 628, 504, 624, 1636, 624, 508, 632, 508, 628, 516, 628, 520, 628, 520, 632, 512, 624, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 516, 628, 500, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 512, 628, 504, 624, 508, 628, 508, 628, 1640, 624, 516, 628, 520, 628, 524, 624, 516, 624, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 512, 628, 504, 628, 1632, 624, 512, 628, 1640, 624, 516, 628, 520, 628, 524, 628, 492, 612};

    IRsend irsend;

    int khz = 38;

    void send23()
    {

    //  const unsigned int irSignal23[] PROGMEM = {9048, 4496, 620, 1636, 620, 1636, 620, 520, 620, 520, 620, 524, 624, 524, 620, 532, 620, 1648, 620, 508, 620, 1640, 620, 1644, 620, 520, 620, 528, 616, 528, 620, 532, 624, 516, 620, 1636, 620, 516, 616, 520, 620, 520, 620, 524, 620, 528, 616, 536, 620, 520, 620, 508, 620, 1640, 620, 520, 620, 520, 620, 1648, 620, 1656, 620, 1656, 616, 524, 620, 508, 620, 516, 616, 520, 620, 520, 624, 520, 620, 528, 620, 532, 620, 520, 620, 508, 624, 508, 624, 516, 616, 520, 624, 524, 620, 524, 620, 532, 620, 504, 620, 7956, 616, 512, 620, 1640, 616, 520, 620, 520, 620, 524, 620, 528, 620, 528, 624, 1644, 620, 1636, 616, 1640, 624, 1640, 620, 1648, 616, 528, 620, 1652, 620, 532, 620, 520, 620, 512, 620, 512, 620, 516, 620, 524, 620, 524, 616, 528, 620, 532, 620, 520, 620, 508, 620, 512, 624, 512, 620, 520, 620, 520, 620, 528, 620, 532, 620, 520, 620, 508, 620, 516, 620, 516, 620, 520, 620, 524, 620, 524, 624, 528, 624, 516, 620, 508, 620, 512, 624, 512, 624, 516, 624, 520, 624, 524, 624, 528, 620, 520, 624, 504, 624, 512, 620, 516, 624, 516, 620, 524, 620, 524, 624, 528, 620, 520, 624, 504, 624, 1636, 624, 1640, 624, 1640, 624, 1648, 620, 524, 624, 1656, 624, 1624, 624, 7952, 616, 512, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 624, 524, 624, 520, 624, 504, 624, 1636, 624, 512, 624, 516, 624, 520, 624, 524, 624, 524, 628, 516, 624, 504, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 620, 528, 628, 512, 624, 508, 624, 508, 624, 512, 620, 520, 620, 524, 624, 520, 624, 528, 624, 516, 620, 508, 624, 508, 624, 512, 624, 1640, 624, 520, 624, 524, 624, 528, 624, 512, 628, 504, 624, 508, 624, 512, 624, 516, 624, 520, 624, 524, 624, 528, 624, 516, 620, 508, 624, 1632, 628, 508, 628, 1640, 624, 520, 624, 524, 620, 528, 624, 500, 608};
      irsend.sendRaw(irSignal23, sizeof(irSignal23) / sizeof(irSignal23[0]), khz); //Note the approach used to automatically calculate the size of the array.
    }

    void send22()
    {
    //  const unsigned int irSignal22[] PROGMEM = {8988, 4548, 572, 1688, 572, 1688, 600, 532, 572, 568, 572, 572, 576, 572, 572, 580, 572, 1724, 544, 556, 576, 1684, 600, 1660, 608, 532, 604, 540, 608, 540, 600, 548, 608, 536, 604, 1652, 608, 520, 616, 524, 608, 532, 612, 532, 612, 532, 620, 532, 616, 524, 620, 512, 616, 1644, 624, 508, 628, 516, 624, 520, 628, 1676, 596, 1648, 632, 508, 632, 500, 632, 500, 632, 504, 636, 504, 636, 512, 628, 516, 632, 524, 628, 508, 636, 496, 632, 504, 628, 508, 632, 508, 632, 512, 632, 516, 632, 516, 632, 496, 628, 7948, 628, 500, 632, 1656, 600, 508, 628, 508, 632, 512, 632, 516, 632, 524, 628, 1636, 632, 496, 632, 504, 632, 504, 632, 508, 632, 1672, 600, 1672, 600, 520, 632, 508, 632, 500, 652, 480, 632, 504, 632, 512, 628, 512, 632, 516, 632, 520, 632, 508, 632, 496, 632, 504, 632, 504, 632, 508, 632, 516, 628, 520, 628, 520, 656, 484, 632, 500, 656, 476, 656, 480, 632, 508, 632, 516, 632, 512, 656, 496, 632, 508, 632, 500, 652, 480, 632, 504, 656, 484, 656, 488, 632, 516, 632, 520, 632, 508, 632, 500, 656, 476, 632, 508, 656, 484, 656, 488, 656, 492, 632, 520, 656, 484, 656, 1632, 624, 476, 632, 508, 656, 484, 656, 1620, 652, 488, 656, 1656, 600, 1648, 604, 7948, 656, 472, 656, 476, 660, 480, 632, 508, 656, 488, 652, 496, 656, 492, 656, 484, 632, 500, 656, 1608, 628, 504, 656, 484, 656, 488, 656, 492, 656, 496, 656, 484, 632, 496, 656, 480, 632, 504, 656, 484, 656, 488, 632, 516, 656, 496, 628, 508, 660, 472, 656, 480, 656, 480, 652, 488, 656, 488, 656, 492, 652, 496, 660, 484, 656, 472, 632, 504, 652, 484, 652, 1644, 624, 488, 656, 492, 656, 492, 632, 512, 628, 500, 664, 468, 656, 480, 656, 488, 652, 488, 656, 492, 656, 492, 632, 512, 652, 476, 656, 1632, 624, 484, 652, 1644, 620, 492, 656, 488, 628, 524, 652, 472, 608};
      irsend.sendRaw(irSignal22, sizeof(irSignal22) / sizeof(irSignal22[0]), khz); //Note the approach used to automatically calculate the size of the array.
    }

    void send21()
    {
    //  const unsigned int irSignal21[] PROGMEM = {9044, 4496, 624, 1628, 628, 1592, 668, 508, 628, 512, 628, 516, 628, 520, 628, 524, 628, 1636, 632, 500, 628, 1632, 624, 1636, 628, 512, 628, 520, 628, 516, 628, 524, 628, 512, 628, 1628, 628, 512, 620, 512, 624, 516, 628, 516, 628, 520, 628, 524, 628, 512, 628, 500, 632, 1628, 628, 512, 628, 512, 628, 1644, 628, 520, 628, 1648, 628, 512, 628, 504, 624, 508, 628, 508, 632, 508, 628, 516, 632, 516, 628, 524, 628, 512, 628, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 500, 624, 7948, 628, 504, 628, 1628, 628, 512, 624, 516, 624, 516, 628, 520, 628, 524, 628, 1636, 628, 504, 624, 1632, 628, 508, 628, 512, 628, 1640, 628, 1648, 628, 520, 628, 512, 628, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 516, 628, 524, 628, 512, 628, 500, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 520, 628, 512, 628, 500, 632, 504, 628, 508, 628, 512, 624, 520, 624, 520, 628, 524, 624, 516, 624, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 520, 628, 512, 628, 504, 628, 504, 628, 508, 624, 516, 628, 512, 628, 520, 628, 524, 624, 516, 628, 1624, 628, 1632, 628, 508, 628, 512, 628, 516, 628, 1644, 628, 1648, 628, 1620, 628, 7944, 628, 500, 628, 504, 628, 512, 624, 512, 628, 516, 628, 520, 628, 520, 628, 512, 628, 504, 624, 1636, 624, 508, 632, 508, 628, 516, 628, 520, 628, 520, 632, 512, 624, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 516, 628, 500, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 512, 628, 504, 624, 508, 628, 508, 628, 1640, 624, 516, 628, 520, 628, 524, 624, 516, 624, 504, 628, 504, 628, 508, 628, 512, 628, 516, 628, 520, 628, 524, 624, 512, 628, 504, 628, 1632, 624, 512, 628, 1640, 624, 516, 628, 520, 628, 524, 628, 492, 612};
      irsend.sendRaw(irSignal21, sizeof(irSignal21) / sizeof(irSignal21[0]), khz); //Note the approach used to automatically calculate the size of the array.
    }

    void setup()
    {
      Serial.begin(9600);
      pinMode(13, OUTPUT);
      send23();
      Serial.println("done");
      delay(4000);
      send22();
      Serial.println("done");
      delay(4000);
      send21();
      Serial.println("done");
    }

    void loop() {
    }

body:
> Isn't the space taken up by the local variable supposed to be freed up
> from the SRAM once the functions runs because I have declared the
> variable locally?

This is correct. The local arrays you have take up RAM only while the
corresponding function is executing. They do not consume any static RAM
(i.e. .data and .bss, what the Arduino IDE improperly calls “Global
variables”).

The problem is not the arrays themselves, but rather the data used to
initialize them. As an experiment, you can try to change the array
definitions as follows:

<!-- language-all: lang-c++ -->

    unsigned int irSignal[343];

You will see the memory consumption reported by the IDE drop by
4×343 bytes. The local arrays are still there. They use RAM (from
the stack) when the functions execute. Only you have removed the
matching initializers.

I disassembled a slightly modified copy of your program just to see how
the compiler handles it. I will not post the assembly code here, as I
guess not many people here are fluent in AVR assembly. Instead, I will
attempt to translate the assembly back to C in the most straightforward
way. The compiler interpreted the function `send23()` as follows:

    static const unsigned int anonymous_array_1[343] = {9048, ...};

    void send23()
    {
        unsigned int irSignal[343];
        for (int i = 0; i < 343; i++)
            irSignal[i] = anonymous_array_1[i];
        irsend.sendRaw(irSignal, 343, khz);
    }

What is taking up static RAM is not the local arrays, it's the global
anonymous arrays that hold the initialization data. You may notice that
making the arrays local has actually worsened the problem: while
`send23()` executes, you have _two copies_ of the data in RAM.

The solution, as Jot and Juraj said in comments, is to put the arrays in
`PROGMEM`. If it doesn't work, then you have a bug. You should fix the
bug instead of trying to avoid `PROGMEM`.


sender: user

sender: assistant

body:
You must declare the array in global space or `static`, and make sure the function you pass the buffer pointer to knows it is in PROGMEM.

    void send22()
    {

      static unsigned int irSignal[] PROGMEM=  {8988, 4548, 572, 1688, 572, 1688, 600, 532, 572, 568, 572, 572, 576, 572, 572, 580, 572, 1724, 544, 556, 576, 1684, 600, 1660, 608, 532, 604, 540, 608, 540, 600, 548, 608, 536, 604, 1652, 608, 520, 616, 524, 608, 532, 612, 532, 612, 532, 620, 532, 616, 524, 620, 512, 616, 1644, 624, 508, 628, 516, 624, 520, 628, 1676, 596, 1648, 632, 508, 632, 500, 632, 500, 632, 504, 636, 504, 636, 512, 628, 516, 632, 524, 628, 508, 636, 496, 632, 504, 628, 508, 632, 508, 632, 512, 632, 516, 632, 516, 632, 496, 628, 7948, 628, 500, 632, 1656, 600, 508, 628, 508, 632, 512, 632, 516, 632, 524, 628, 1636, 632, 496, 632, 504, 632, 504, 632, 508, 632, 1672, 600, 1672, 600, 520, 632, 508, 632, 500, 652, 480, 632, 504, 632, 512, 628, 512, 632, 516, 632, 520, 632, 508, 632, 496, 632, 504, 632, 504, 632, 508, 632, 516, 628, 520, 628, 520, 656, 484, 632, 500, 656, 476, 656, 480, 632, 508, 632, 516, 632, 512, 656, 496, 632, 508, 632, 500, 652, 480, 632, 504, 656, 484, 656, 488, 632, 516, 632, 520, 632, 508, 632, 500, 656, 476, 632, 508, 656, 484, 656, 488, 656, 492, 632, 520, 656, 484, 656, 1632, 624, 476, 632, 508, 656, 484, 656, 1620, 652, 488, 656, 1656, 600, 1648, 604, 7948, 656, 472, 656, 476, 660, 480, 632, 508, 656, 488, 652, 496, 656, 492, 656, 484, 632, 500, 656, 1608, 628, 504, 656, 484, 656, 488, 656, 492, 656, 496, 656, 484, 632, 496, 656, 480, 632, 504, 656, 484, 656, 488, 632, 516, 656, 496, 628, 508, 660, 472, 656, 480, 656, 480, 652, 488, 656, 488, 656, 492, 652, 496, 660, 484, 656, 472, 632, 504, 652, 484, 652, 1644, 624, 488, 656, 492, 656, 492, 632, 512, 628, 500, 664, 468, 656, 480, 656, 488, 652, 488, 656, 492, 656, 492, 632, 512, 652, 476, 656, 1632, 624, 484, 652, 1644, 620, 492, 656, 488, 628, 524, 652, 472, 608};
      irsend.sendRaw_P(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz);
      // _P postfix is often used to mark functions taking in PROGMEM pointers
    }

You can adjust the library to allow it to take PROGMEM buffers, with a quick search for the implementation of `IRsend::sendRaw` it gave me:

    void  IRsend::sendRaw (const unsigned int buf[],  unsigned int len,  unsigned int hz)
    {
     // Set IR carrier frequency
     enableIROut(hz);

     for (unsigned int i = 0;  i < len;  i++) {
      if (i & 1)  space(buf[i]) ;
      else        mark (buf[i]) ;
     }

     space(0);  // Always end with the LED off
    }

To make it work with progmem you can create:

    void  IRsend::sendRaw_P (const unsigned int buf[],  unsigned int len,  unsigned int hz)
    {
     // Set IR carrier frequency
     enableIROut(hz);

     for (unsigned int i = 0;  i < len;  i++) {
            unsigned int word = pgm_read_word_near(buf + i);
      if (i & 1)  space(word) ;
      else        mark (word) ;
     }

     space(0);  // Always end with the LED off
    }


message:
Connecting Arduino to a Peltier Module

I am trying to make a cooler using Peltier Modules, the Peltier Modules and the fans switch on when the Temperature sensor attached to the circuit reads above a certain threshold. But I know that Arduino can only handle a couple of MilliAmps as its functionality, in such a case, how can I control my 480W circuitry (12V/40A) using Arduino?

I'm very new to all this and will appreciate a detailed answer.

**EDIT: To the best of my knowledge, this is not a duplicate of another question as the other question says *I'm currently working on several projects that each require controlling devices ranging from 800mA to 2A from an Arduino Uno.*, whereas my application requires much larger current than that.**

body: You are correct the Arduino can only handle a few mA at 5V.  In order to do what you want you need to use the Arduino to switch relays that can handle the current.


body:
There are solid-state relays ([such as this one][1]) capable of switching the currents - 40A - you're talking about and may be a better choice than a mechanical one. Note that it will probably need to be mounted to a heat-sink.

You're Arduino then only needs to drive enough current to switch the relay. The example I gave above is not a recommendation as I've never used it; it's just the first one I found that is spec'd for enough more than 40 Amps to not be operating at its limit. I'm sure there are others as well.

The current it will draw from the Arduino is not specified; this is something you will need to find out about whatever relay you choose, to be sure it won't exceed the Arduino's 20 mA pin-driver spec. It *is* spec'd to require a heat sink.

  [1]: https://www.amazon.com/100A-Solid-State-Relay-SSR/dp/B00KO46YCU/ref=pd_sim_328_5?_encoding=UTF8&pd_rd_i=B00KO46YCU&pd_rd_r=4b333d0d-7f8f-11e8-8042-83a887e2fe6a&pd_rd_w=Fvady&pd_rd_wg=q5eaE&pf_rd_i=desktop-dp-sims&pf_rd_m=ATVPDKIKX0DER&pf_rd_p=7967298517161621930&pf_rd_r=BF7KSJ9443M6RVCHP2QC&pf_rd_s=desktop-dp-sims&pf_rd_t=40701&psc=1&refRID=BF7KSJ9443M6RVCHP2QC


message:
Attach Interrupt with Library

I am trying to make a library for Arduino, which requires an interruption, but the problem is that when I try the `attachInterrupt` function inside my library, there's a problem about attachInterrupt is static. Right now, in the library I have this in the header file:

    #ifndef RegletaCMA_h
    #define RegletaCMA_h

    #include "Arduino.h"

    class DimmerGlider {
    public:
        DimmerGlider(int min, int max, int increase);

        int getMin() { return _min; }

        int getMax() { return _max; }

        int getIncrease() { return _increase; }

        void setMin(int min) { _min = min; }

        void setMax(int max) { _max = max; }

        void setIncrease(int increase) { _increase = increase; }

    private:
        int _min, _max, _increase;
    };

    class Dimmer {

    public:
        Dimmer(DimmerGlider &glider, int outputPin, int t3);

        void Dimmer::begin() {
            pinMode(_outputPin, OUTPUT);
            digitalWrite(_outputPin, false);
        }

        void Dimmer::dim() {
            delayMicroseconds(_DIMMER_counter);
            digitalWrite(_outputPin, true);  // Turn _DIMMER_pinDimmer on
            delayMicroseconds(_t3);
            digitalWrite(_outputPin, false); // Turn _DIMMER_pinDimmer off

            if (_DIMMER_dir) _DIMMER_counter += _glider.getIncrease(); // If dir is negative add _DIMMER_increase
            else _DIMMER_counter -= _glider.getIncrease();                  // If dir is negative substract _DIMMER_increase

            if (_DIMMER_counter > _glider.getMax()) _DIMMER_dir = false; // Change dir if reached bottom
            if (_DIMMER_counter < _glider.getMin()) _DIMMER_dir = true;  // Change dir if reached top

            _DIMMER_lastExecutionTime_micros = micros(); // Reset timer
        }

        void Dimmer::force(bool status) {
            digitalWrite(_outputPin, status);
        }

    private:
        DimmerGlider &_glider;

        int _outputPin;

        int _DIMMER_counter = 1000;
        bool _DIMMER_dir = true;

        unsigned long long _DIMMER_lastExecutionTime_micros = 0;

        int _t3;
    };

    class DimmerImplementor {
    public:
        DimmerImplementor(Dimmer dimmerList[], int optoPin);

        void DimmerImplementor::begin(){
            attachInterrupt(_optoPin, dimAll, RISING);
        }

        void DimmerImplementor::dimAllDimmers() {
            for (int c = 0; c < sizeof(_dimmerList); c++)
                _dimmerList[c].dim();
        }

        void DimmerImplementor::dimAll() {
            DimmerImplementor::dimAllDimmers();
        }

    private:
        int _optoPin;
        Dimmer _dimmerList[];
    };

    #endif

and this in the cpp file:

    #include "Arduino.h"
    #include "RegletaCMA.h"

    DimmerGlider::DimmerGlider(int min, int max, int increase) :
            _min(min),
            _max(max),
            _increase(increase) {
    }

    Dimmer::Dimmer(DimmerGlider &glider, int outputPin, int t3) :
            _glider(glider),
            _outputPin(outputPin),
            _t3(t3) {
    }

    DimmerImplementor::DimmerImplementor(Dimmer *dimmerList, int optoPin) :
            _dimmerList(dimmerList),
            _optoPin(optoPin) {
        for(int c = 0; c < sizeof(dimmerList); c++){
            DimmerImplementor::dimmers[c] = dimmerList[c];
        }

        for (int c = 0; c < sizeof(dimmers); c++) {
            Dimmer dimmer = dimmers[c];

            dimmer.begin();
        }
    }

and when I try to run the library with the Arduino IDE, with this code:

    DimmerGlider dimmer1Glider = DimmerGlider(_DIMMER_1_tempMin, _DIMMER_1_tempMax, _DIMMER_1_increase);
    Dimmer dimmer1 = Dimmer(
                       dimmer1Glider,
                       _DIMMER_1_pin,
                       _DIMMER_t3
                     );
    DimmerGlider dimmer2Glider = DimmerGlider(_DIMMER_2_tempMin, _DIMMER_2_tempMax, _DIMMER_2_increase);
    Dimmer dimmer2 = Dimmer(
                       dimmer2Glider,
                       _DIMMER_2_pin,
                       _DIMMER_t3
                     );
    DimmerGlider dimmer3Glider = DimmerGlider(_DIMMER_3_tempMin, _DIMMER_3_tempMax, _DIMMER_3_increase);
    Dimmer dimmer3 = Dimmer(
                       dimmer3Glider,
                       _DIMMER_3_pin,
                       _DIMMER_t3
                     );

    Dimmer dimmers[] = {
      dimmer1, dimmer2, dimmer3
    };

    DimmerImplementor implementor = DimmerImplementor(dimmers, _DIMMER_pinOpto);

    void Dimmer_Init() {
      implementor.begin();
    }

It throws the following error:

    C:\Users\Arnym\Documents\Arduino\libraries\RegletaCMA/RegletaCMA.h: In member function 'void DimmerImplementor::begin()':

    C:\Users\Arnym\Documents\Arduino\libraries\RegletaCMA/RegletaCMA.h:73:44: error: invalid use of non-static member function

             attachInterrupt(_optoPin, dimAll, 3); // 3 is the same as RISING

                                                ^

I have been messing around with this problem for some days and I can't find an answer, so I would be really pleased if you can help me.
If you need any more info, don't doubt on asking.
Thanks in advance.

body:
The error message says, that in the constructor of `Dimmer` it cannot find a matching constructor of `DimmerGlider`. The problem here is that you pass the parameters by value, which will create a new variable of the given type and content for the function/constructor call. So when you create a new `Dimmer` variable you are calling the constructor of the class. Since the parameters of the constructor contain a `DimmerGlider` instance, it also has to be created for you, which means calling the constructor. When passing variables by value the default constructor (without any parameters) is used. But the `DimmerGlider` doesn't have a default constructor (as you didn't define it). The compiler then tells you, that is needs some parameters for the constructor to create a `DimmerGlider` instance.

I don't know a way to pass these parameters for the `DimmerGlider` constructor directly through the `Dimmer` constructor. Also I don't think this is desirable for you. You are creating the `DimmerGlider` first and sure want the `Dimmer` objects to refer to exactly this instance, not a different (cloned) instance, that was created with the `Dimmer` constructor.

So my suggestion is the following: Pass the `DimmerGlider` by reference, meaning you only pass a pointer to the `DimmerGlider` object. In the constructor definition of `Dimmer` change to the following:

    Dimmer::Dimmer(DimmerGlider *glider, int outputPin, int t3);

The `*` says, that this variable will not hold an instance of the `DimmerGlider` class, but only a pointer to one. A pointer is simple to create, because it is basically an `unsigned int` (a 16 bit memory address).

Then in your sketch you are passing not the variable itself, but only the address in memory (a pointer to the object) by using the `&`:

    Dimmer dimmer1 = Dimmer(
                       &dimmer1Glider,
                       _DIMMER_1_pin,
                       _DIMMER_t3
                     );

Now the constructor of `Dimmer` doesn't have to create an instance of `DimmerGlider`, but only a simple pointer of the type `Dimmerglider`. The `&` retrieves the memory address (the pointer) of an object instance. The constructor now simply writes the pointer, that it got as a parameter, into the `glider` variable of type `DimmerGlider`-pointer.

If you don't understand, how pointers work, please google for a tutorial on this. This isn't something, that can be easily explained in the short question-answer format of this site.


body:
In C++, you need to distinguish between two separate copies of an object, or having a reference to an existing object. @chrisl got it right when he identified that you were trying to create a second copy of `DimmerGlider`, so he suggested using a reference - and then showed using a pointer (`*`) instead.

He was right: `Dimmer` should hold a *reference* to the `DimmerGlider` object, but that is done with `&`. You need to make the following changes to the given code:

In the `.h`:

    class Dimmer {

    public:
        Dimmer(DimmerGlider &glider, int outputPin, int t3);
    .
    .
    .
    private:
        DimmerGlider &_glider;
    .
    .

And in the final `.cpp`:

    DimmerGlider::DimmerGlider(int min, int max, int increase) :
                  _min(min),
                  _max(max),
                  _increase(increase) {
    }

    Dimmer::Dimmer(DimmerGlider &glider, int outputPin, int t3) :
            _glider(glider),
            _outputPin(outputPin),
            _t3(t3) {
    }

The syntax for the `Dimmer` constructor had to change. You were *assigning* the class members the values from the constructor parameters. References need to be ***initialised***, not assigned. This is the syntax you need (note how they’re before the `{`?)

I fixed the `DimmerGlider` constructor code while I was at it...

Also, note the difference between using a reference versus using a pointer. A pointer needs to be dereferenced, so you need to use `*ptr` and `ptr->_min` to refer to the original object. A reference is *already* dereferenced, so you can simply use it like the original object: `ref` and `ref._min`.

----

Edit: If you want to use the function `dimAll()` as an interrupt handler function, then it cannot be a (non-`static`) member of a `class`. All `class` functions have a hidden `this` pointer as the first parameter in the argument list, since it has to know *which* `DimmerImplementor`'s members to modify. Thus you have to declare the function as `static`. And as soon as you do that, you cannot call `dimAllDimmers()`, because that functions accesses an instance of `DimmerImplementor`'s variables. Luckily, you have a global object called `implementor`, so you could use that:

    static void DimmerImplementor::dimAll() {
        implementor.dimAllDimmers();
    }

But it's usual to make that variable a `static` member of the class itself:

    class DimmerImplementor {
        .
        .
    public: // Static variables
        static DimmerImplementor implementor;
        .
        .
    }; // DimmerImplementor

You'd initialise that as follows:

    DimmerImplementor DimmerImplementor::implementor(dimmers, _DIMMER_pinOpto);


message:
Different voltage sources across Vin and DC jack

So I understand that the USB VBUS circuitry turns off provided there is a high enough vin voltage using the PFET and comparator.

I can see that the DC jack is connected to the Vin pin via a diode.
However, what is to stop someone from plugging a voltage source across the Vin and at the same time putting across a voltage on the DC jack.

If I incorrectly plugged in a voltage source of a low voltage like a coin cell battery across the VIN pin and also powered the device using the 9 V DC jack, wouldn't that then send current through the VIN pin and back to the coin cell battery?

Is that what would happen in this instance? And if so then shouldn't there be a design feature to prevent users from damaging it like that? Fool/fail safe?

body:
> wouldnt that then send current through the Vin pin and back to the coin cell battery? Is that what would happen in this instance?

Yep, that's right.

> shouldn't there be a design feature to prevent users from damaging it like that? Fool/fail safe?

No. VIN can also be VOUT. You can use it to power other things that want a higher voltage.


message:
Can Bus to receive and transmit on the same mcu

So I've been working on a project over the last few month using homemade boards on a CAN bus. It's working well when using a board as a sender and another one as receiver.
I now have 3 boards and on which there are several sensor.
My purpose here is to be able for every board to share data and use other from another mcu.

An quick overview of the project for a better understanding :
I'm trying to automate a RC plane.

MCU-1 : Potentiometers + GPS

MCU-2 : 1 accelerometer + 1 barometer

MCU-3 : 1 differential pressure transmitter + 1 radio transmitter

I'd like to be able, for MCU-1 to receive and use data from MCU-2 and in the same time to transmit data to MCU-3. (They both have many more components and tasks to achieved, that why I don't have all the sensors on the same board)

I don't think it's important but MCU1 and 3 are ATmega328p (the one from the nano board) and MCU2 is an ATmega2560

My question :
Is it possible ? I mean is it possible to have a MCU running as a Sender and a Receiver at the same time ? and how to do it ? :)

Also is it possible to have a MCU running as a receiver, let's say 90% of the time and sender 10% (or after an update) ? If the first situation isn't possible this one could be a solution for my project.

Thank you

Undeadguy

body:
Yes, it is possible.

> CAN is a multi-master serial bus standard for connecting Electronic Control Units [ECUs] also known as nodes. Two or more nodes are required on the CAN network to communicate. The complexity of the node can range from a simple I/O device up to an embedded computer with a CAN interface and sophisticated software.
>
> -- *[Wikipedia](https://en.wikipedia.org/wiki/CAN_bus)*

You should understand how collision detection works in a multi-master CAN bus and ensure that you implement it (or it is implemented in your chosen CAN library) to allow reliable operation:

> The CAN specifications use the terms "dominant" bits and "recessive" bits where dominant is a logical 0 (actively driven to a voltage by the transmitter) and recessive is a logical 1 (passively returned to a voltage by a resistor). The idle state is represented by the recessive level (Logical 1). If one node transmits a dominant bit and another node transmits a recessive bit then there is a collision and the dominant bit "wins". This means there is no delay to the higher-priority message, and the node transmitting the lower priority message automatically attempts to re-transmit six bit clocks after the end of the dominant message. This makes CAN very suitable as a real time prioritized communications system.
>
> The exact voltages for a logical 0 or 1 depend on the physical layer used, but the basic principle of CAN requires that each node listens to the data on the CAN network including the transmitting node(s) itself (themselves). If a logical 1 is transmitted by all transmitting nodes at the same time, then a logical 1 is seen by all of the nodes, including both the transmitting node(s) and receiving node(s). If a logical 0 is transmitted by all transmitting node(s) at the same time, then a logical 0 is seen by all nodes. If a logical 0 is being transmitted by one or more nodes, and a logical 1 is being transmitted by one or more nodes, then a logical 0 is seen by all nodes including the node(s) transmitting the logical 1. When a node transmits a logical 1 but sees a logical 0, it realizes that there is a contention and it quits transmitting. By using this process, any node that transmits a logical 1 when another node transmits a logical 0 "drops out" or loses the arbitration. A node that loses arbitration re-queues its message for later transmission and the CAN frame bit-stream continues without error until only one node is left transmitting. This means that the node that transmits the first 1 loses arbitration. Since the 11 (or 29 for CAN 2.0B) bit identifier is transmitted by all nodes at the start of the CAN frame, the node with the lowest identifier transmits more zeros at the start of the frame, and that is the node that wins the arbitration or has the highest priority.
>
> For example, consider an 11-bit ID CAN network, with two nodes with IDs of 15 (binary representation, 00000001111) and 16 (binary representation, 00000010000). If these two nodes transmit at the same time, each will first transmit the start bit then transmit the first six zeros of their ID with no arbitration decision being made.


message:
How can I create a battery level circuit

Im trying to create a circuit so that I can monitor the voltage drop on my battery and send an message when the voltage drop reaches the drop out. But I'm having some problems with my voltage divisions.

I created this circuit to enable a flow so that it does not flow (drain the battery) while not necessary. But as I understand it analog input must not be above 1 volts.

[![enter image description here][1]][1]

The +3.3V represent the MCU (ESP-12, arduino with wifi) turning the circuit on, letting battery flow to the analog input (red circled ground). However, at analog input, the volt is 2,24V, which is more than the 1V it should be. Do I just divide it again? If I divide it again ill be at 1,12 so I need to divide it yet again. I don't think Im doing it right.

The maximum voltage of the analog pin on the ESP-12 is 1V. How can I get there?

  [1]: https://i.stack.imgur.com/xPEb6.png

body:
Firstly, if I understand your schematic right, you're not "dividing" anything there. If the ringed red symbol is where you are connecting the ADC then either you will see near 4V on there (if it's *only* connected to the ADC), or 0V (if it's connected to ground).

You should be connecting the ADC *between* the resistors to get a reading.

Secondly, you should be using a P-channel MOSFET, not a PNP transistor. You *can* use a PNP transistor, but you will have to subtract the voltage drop imposed by the transistor from your calculations to get any meaningful reading. With a P-channel MOSFET, the on-resistance would be (or should be if you choose a sensible one) negligible compared to the resistance of the voltage divider.

You are right that you can't exceed 1V on the ADC, so you will have to size your resistors accordingly. You aren't restricted to just using a pair of 10K resistors - you can choose any values you like that yield the correct result.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/GMlkS.png)

<!-- End schematic -->

In this example, 10K and 2.2K give you no more than 0.9V from a 5V input. (Tip: choose an input voltage slightly higher than you expect to give a small safety margin).

I calculated those by:

1. Use the voltage divider formula `R2 = R1×(1/((VIN/VOUT)-1))` to calculate the lower resistor (2500Ω).
2. Choose the next lowest "common" resitor (2200Ω)
3. Re-calculate the new output using the chosen resistor values using `VOUT = (R2/(R1+R2))×VIN` (0.9V)


message:
Make system with ultrasonic sensor and servo

I want to create a system where the servo will make the ultrasonic sensor move and detect the area in front of it. I have made the program but when run the ultrasonic sensor can not detect as usual.

Does anyone have another program or why my program is not running as planned?

This is the source code :

    #include <Servo.h>

    const int trigPin = 10;
    const int echoPin = 9;
    int lampu = 13 ;

    // membuat nama objek servo untuk pengontrolan servo
    Servo myservo;
    // variable untuk menyimpan posisi servo
    int pos = 0;
    long duration, inches, cm;
    void setup() {
      Serial.begin(9600);
      pinMode(lampu, OUTPUT);
      myservo.attach(7);
    }

    void loop() {
      pinMode(trigPin, OUTPUT);
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
      inches = microsecondsKeInchi(duration);
      cm = microsecondsKeCenti(duration);
      Serial.print(inches);
      Serial.print(" in, ");
      Serial.print(cm);
      Serial.print(" cm");
      Serial.println();

      lampuNyala() ;
      servo();
      delay(10);
    }

    // start dari 0 derajar sampai 180 derajat
    long microsecondsKeInchi(long microseconds)
    {
      return microseconds / 74 / 2;
    }

    long microsecondsKeCenti(long microseconds)
    {
      return microseconds / 29 / 2;
    }

    void servo(){
      for(pos = 0; pos < 180; pos += 1)
      {
        // pada posisi 1 derajat
        // memberitahu servo untuk pergi ke posisi  'pos'
        myservo.write(pos);
        // tunggu 15ms untuk pencapaian  posisi servo
        delay(30);
      }
      // start dari 180 derajat ke 0 derajat
      for(pos = 180; pos>=1; pos-=1)
      {
        // memberitahu servo untuk pergi ke posisi  'pos'
        myservo.write(pos);
        // tunggu 15ms untuk pencapaian  posisi servo
        delay(30);
      }
    }

    void lampuNyala(){
      if(cm > 0 && cm <=30){
        digitalWrite(lampu,HIGH) ;
      }
      else{
        digitalWrite(lampu,LOW) ;
      }
    }

body:
Look at your code sequence. An ultrasonic measurement is only taken, when you use `pulseIn()`. At the end of the `loop()` function you call your `servo()` function. In it you tell the Arduino to first go from 0° to 180° and then back to 0°. AFTER THAT (!) the function exits and the `loop()` function continues. This means, that nothing else happens during the servo motion. The measurement only takes place between the motions, meaning about every 10s.

To solve this problem you need to make the servo code non-blocking. It is mostly a bad thing to use `delay()`, since you cannot do anything else during waiting. Think about how you are backing a pizza. You are not sitting in front of the oven the whole time, until the pizza is ready. Instead you are looking at your clock regularily and check, if it is time to take the pizza out of the oven.

You can do the same thing on an Arduino with the `millis()` function. It will return the milliseconds since the last reset/powerup of the Arduino. This has to be used as a clock. To do something after a specific time you first save the current time in a timestamp:

    unsigned long timestamp=0;
    ...
    timestamp = millis();

Then in the `loop()` function you are regularly (on every loop iteration) checking, if the difference between the timestamp and the current time is above your set interval:

    if(millis() - timestamp > 30){
        // do something here, like moving a servo
        timestamp = millis(); //update timestamp for next event
    }

The Arduino will not do the things simultaneously, but will switch between the different code parts so fast, that it will seem simultaneous. Also refer to the `BlinkWithoutDelay` example of the Arduino library.

Note: The current delay between two consecutive servo values is ok. If you want to go way faster with the servo, you have to watch out, that the rest of the code in `loop()` doesn't take to long. If this happens and you cannot make the other code parts non-blocking too, you can also do the servo part in an interrupt routine from a timer.


message:
Arduino Uno Motor control using 2 Relays, 2 Limit switches and Bluetooth. Forward Reverse Stop

Modified existing project from this link:  https://arduino.stackexchange.com/questions/47731/problem-trigger-limit-switch-to-stop-dc-motor

I modified this code to control two relays which are wired to motor poles for Forward or Reverse movements until they physically reach a limit switch on either side.

 - Serial input of 'A' turns on one relay. If `Limitswitch1` is pressed, this relay switches off.
 - It detects the current state of the system and awaits the Serial input of 'B' which then turns on the second relay. If `Limitswitch2` is pressed, this relay switches off.

The issues are:

 1. Please help with code - I require option where the two relays switch off on the serial input of letter 'S' and to add the corresponding state machine. Essentially to add a Stop function.

 2. The limit switches work intermittently, sometimes they respond flawlessly, sometimes not at all. I have bought three different brands of switches to test but all have the same behaviour. I have pulled switches up and down with resistors in vain. I have performed button count test using code from this forum and confirm that the switch also behaves erratically. Can changes to code improve switch feedback?

Suggestions will be greatly appreciated.

    const byte RELAY1 = 2;
    const byte RELAY2 = 3;

    const byte LimitSwitch1 = A1;
    const byte LimitSwitch2 = A2;

    const byte State_Idle = 0;
    const byte State_Forward = 1;
    const byte State_Reverse = 2;
    byte currentState;

    void setup(){
    pinMode(RELAY1,OUTPUT);
    pinMode(RELAY2,OUTPUT);

    pinMode(LimitSwitch1, INPUT);
    pinMode(LimitSwitch2, INPUT);

    Serial.begin(9600);
    currentState = 0xFF; // Force a change to enter the idle state
     }

    void loop(){
    // Check if we need to change state
    byte nextState = currentState;
    switch (currentState)
    {
    case State_Idle:
        { // If we received a valid command, start the operation
            if(Serial.available() > 0)
            {
                switch (Serial.read())
                {
                case 'A':
                    nextState = State_Forward;
                    break;
                case 'B':
                    nextState = State_Reverse;
                    break;
                default:
                    break;
                }
            }
        }
        break;
    case State_Forward:
        if(digitalRead(LimitSwitch2))
            nextState = State_Idle;
        break;
    case State_Reverse:
        if(digitalRead(LimitSwitch1))
            nextState = State_Idle;
        break;
    default:
        nextState = State_Idle;
        break;
    }

    // If there was a change, switch state and trigger enter condition
    if (nextState != currentState)
    {
        currentState = nextState; // Move in the new state
        switch (currentState)
        { // Entering the new state
        case State_Idle:
            // Switch both Relays OFF
            digitalWrite(RELAY1, HIGH);
            digitalWrite(RELAY2, HIGH);
            break;
        case State_Forward:
            // Move Forward
            digitalWrite(RELAY1, LOW);
            digitalWrite(RELAY2, HIGH);
            break;
        case State_Reverse:
            // Move Reverse
            digitalWrite(RELAY1, HIGH);
            digitalWrite(RELAY2, LOW);
            break;
        }
    }
    }

  [1]: https://arduino.stackexchange.com/questions/47731/problem-trigger-limit-switch-to-stop-dc-motor#/

body:
Here I am again for another exciting episode of "Fun with StateMachines".. ;)

Ok, basically you modified the code well, but you thought of the modification in the wrong way.

First of all describe what you want to do in simple words. Let's say you want that

> When I'm moving in one direction and I receive the letter 'S', I immediately stop without waiting for the endstop

Consequently, you know that

 1. you will have to add something when you are moving in one direction
 1. this "something" will top you, which is what the endstop does

So, to implement this, you can do something like this:

    switch (currentState)
    {
    case State_Idle:
        { // If we received a valid command, start the operation
            if(Serial.available() > 0)
            {
                switch (Serial.read())
                {
                case 'A':
                    nextState = State_Forward;
                    break;
                case 'B':
                    nextState = State_Reverse;
                    break;
                default:
                    break;
                }
            }
        }
        break;
    case State_Forward:
        if(digitalRead(LimitSwitch2))
            nextState = State_Idle;
        else  if((Serial.available() > 0) && (Serial.read() == 'S'))
            nextState = State_Idle;
        break;
    case State_Reverse:
        if(digitalRead(LimitSwitch1))
            nextState = State_Idle;
        else  if((Serial.available() > 0) && (Serial.read() == 'S'))
            nextState = State_Idle;
        break;
    default:
        nextState = State_Idle;
        break;
    }

Now, your second problem is a bit harder to understand. When I read it, I immediately thought what chrisl already pointed out, which is switch bounces. But when I was halfway into completing this part of the answer I found out that.. no, the bounces are not what can give problems here, unless you are constantly writing 'A' or 'B' on the serial. So for the second part of the question please post your schematic and/or photos of the setup, so we can see if there is something not normal


message:
Does blinking an LED with no resistor for a few seconds harm my Arduino?

I am new to Arduino and I just made my first LED blink. I connected the LED to ground and digital pin 13 without resistance (for only a few seconds). Does this harm my Arduino?

Hilmi

body: If you try it again with the proper resistor in place, and the pin still works, then no, you probably haven't damaged it. It may have stressed the pin driver some but if it passes the above test, I think you're still good to go.


message:
Arduino reads string from another Arduino only if the string is in a loop why?

In my setup I have connected two arduino's Serially. An Arduino Mega is the on that is sending the string and a Arduino Uno is the one receiving it.

- Arduino Mega : RX1(19),TX1(18) - Serial1
- Arduino Uno : RX(10),TX(11)  - using SoftwareSerial
- Gnd is connecetd on both boards

When I send a single string from the mega to Uno multiple times(In void loop)
I receive the string sent infinite number of times on the Uno which is to be expected:

Arduino Mega - Single string sent multiple no. of times

    void setup()
    {
      Serial1.begin(9600);
    }
    void loop()
    {
      Serial1.println("e2e4");
      delay(100);
    }

Now I want to only send the string a single time, so I inserted an exit(0) or an infinite loop after the delay that is always true.

Arduino Mega - Single string sent only one time

    void setup()
    {
      Serial1.begin(9600);
    }
    void loop()
    {
      Serial1.println("e2e4");
      delay(100);
      while(true);
    }

Arduino UNO - code is same for both cases

    #include <SoftwareSerial.h>
    SoftwareSerial s(10, 11);
    void setup()
    {
      delay(200);
      Serial.begin(9600);
      s.begin(9600);
      while (!Serial) ;  // wait for Arduino Serial Monitor
    }
    void loop()
    {
      if(s.available()>0)
      {
         Serial.print("\nrec\n");
         delay(100);
         String b = s.readStringUntil('\n');
         delay(100);
         Serial.print(b);
         delay(40);
      }
   }

Note : Arduino uno is receiving the string using : readStringUntil('\n')

But when I send the string only once I receive nothing on the Arduino Uno, can anyone help me figure out why this is happening

What I want to know is why the uno receives the string only when it's sent an infinite number of times and not when it is sent 1 time.

EDIT (July 8)

Still haven't got a solution that I'm looking for, if anyone needs any extra information to help me out please mention it to me.

EDIT (July 8-9)

Sorry it's my fault for writing Tx1 as 19  and Rx1 as 18 although I did not make the same mistake in the code.
When I pressed the reset button on the mega the string was received on the uno side.How did this happen?  Until now, after I uploaded the code in both the arduino's I opened the serial monitor of the port connected to Uno and I did not receive the string.

Why do I need to reset the mega in order to send the string , shouldn't it work when the serial monitor is opened?

Also I need the mega to send the string automatically without any forced/physical reset is that possible?

I'm asking this because sending a string is part of a larger code where values get updated as time goes by,and a reset will  reset all the values to their original state which I don't want happening.

body:
exit(0) is not the command to use, it is used to completely stop the program, although I'm not sure what happens exactly for an Arduino sketch.

To stop a loop (and continue, normally a break statement is used. This works inside a while or for loop and the sketch continues after the while or for loop where the break statement is executed.

Note, you also can start at the beginning of the while or for loop with the continue statement.


body: `exit` turns off interrupts which will stop the serial output. I suggest something simpler like `while (true);`


body:
try putting a delay in the arduino mega code to make sure the uno is completely setup before it starts sending the data. I can see some delays in the uno code, so its possible that the arduino uno is not yet ready when the data is sent. Add a large delay, say 2000 to make sure uno is ready. Also there are neater ways to do this instead of just putting an infinite loop, unless the only goal of your program is just to send one string. You can use a flag that to disable sending.

    bool isSent = true;

    void loop()
    {
      if(isSent)
       {
         isSent = false;    // set to false so we will never send again.
         Serial1.println("e2e4");
       }
    }


body:
>  Until now, after I uploaded the code in both the arduino's I opened the serial monitor of the port connected to Uno and I did not receive the string.
>
> Why do I need to reset the mega in order to send the string , shouldn't it work when the serial monitor is opened?

Clearly there is a timing issue. When you open the serial monitor it resets the Arduino (in this case, I assume the Uno). So, the Uno resets, however the Mega doesn't reset because you didn't open the serial monitor there. Manually resetting the Mega forces it to send the data again (it would have sent it earlier when powered on).

In normal operation, of course you don't need to reset the Mega just to force a string "to be sent once". You have already proved that you can send a string many times, and sending a string once is clearly a subset of that situation. Sending n times is just (sending once) times n.

Your test setup, which requires powering both Arduinos at the same time, and then opening the serial monitor which resets one, but not the other, is what is confusing you. It is not that you can't send strings whenever you want, in normal operation.


message:
Flashing a specified digit 4x7 segment display and shift register 74HC595N

I have a project that is simply a relay timer. The code is not complete so you will see 'in progress' sections not related to my question in my code.

However, my question is...

I am creating a timer with 4 x 7 segment display using a rotary encoder to set the time. I have 3 'Modes' that allow me to increment the time by 1 second, 10 seconds and minutes. All this is working correctly however when I switch modes I would like to flash the corresponding digit to give a kind of visual feedback showing what mode you are in (the first digit for seconds, the second for 10 seconds etc..). I can manually ground the corresponding common pin to create that effect manually, however, I am having trouble with the code.

I have tried creating for loops that `digitalwrite()` to the specific comPin, however, this is just turning the entire display off and on. The section of code that I am looking at is roughly halfway down.

The Bonus Question: I would like the Dp to illuminate between the second and third digits to show "min:sec". I assume this must be to do with my byte table, however, this is all new to me and I am not sure of what direction to go regarding changes.

    #include <MD_REncoder.h>

    int LightClocksec = 0;
    int LightClockmin = 0;

    int LightClockAdd = 1;
    int Mode = 0;
    boolean LightSW = 5;

    int EncoderSW = 4;
    boolean EncoderSWstate = 0;
    MD_REncoder R1 = MD_REncoder(2, 3);

    int FocusSW = 13;
    boolean FocusSWstate = 0;
    boolean FocusSWstatePRE = 0;
    int FocusSWCounter = 0;

    int MainSW = 14;
    boolean MainSWstate = 0;
    boolean MainSWstatePRE = 0;

    int RelayPIN = 15;
    boolean Relaystate = LOW;

    unsigned long millispre = 0;

    int buttonPushCounter = 0;   // counter for the number of button presses
    int lastButtonState = 0;     // previous state of the button

    int latchPin = 7;          // Pin connected to ST_CP of 74HC595（Pin12）
    int clockPin = 8;          // Pin connected to SH_CP of 74HC595（Pin11）
    int dataPin = 6;           // Pin connected to DS of 74HC595（Pin14）
    int comPin[] = {12, 11, 10, 9};// Common pin (anode) of 4 digit 7-segment
    display

    byte num[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
    0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

    void setup() {
      //  Serial.begin(9600);
      R1.begin();
      pinMode (LightSW, OUTPUT);
      pinMode (RelayPIN, OUTPUT);

      pinMode (EncoderSW, INPUT);
      pinMode (FocusSW, INPUT);

      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);

    for (int i = 0; i < 4; i++) {
      pinMode(comPin[i], OUTPUT);
      }

    }

    void loop() {

      ///set time, encoder..

      EncoderSWstate = digitalRead(EncoderSW);

      uint8_t z = R1.read();
      if (z) {
        if (EncoderSWstate == 0) {
          if ((Mode == 2) )
          {
            z == DIR_CW ? LightClockmin ++  : LightClockmin --;
          }
          else if (Mode == 1) {
            z == DIR_CW ? LightClocksec = LightClocksec + 10  : LightClocksec = LightClocksec - 10 ;
            if (LightClocksec >= 60) {
              LightClocksec = (LightClocksec - 60);
              LightClockmin ++;
            }
            if ((LightClocksec < 0) && (LightClockmin >= 1 )) {
              LightClocksec = (60 - LightClockAdd) ;
              LightClockmin --;
            }
          }
          else if (Mode == 0) {
            z == DIR_CW ? LightClocksec ++  :  LightClocksec --;
            if (LightClocksec >= 60) {
              LightClocksec = (LightClocksec - 60);
              LightClockmin ++;
            }
            if ((LightClocksec < 0) && (LightClockmin >= 1 )) {
          LightClocksec = (60 - LightClockAdd) ;
          LightClockmin --;
        }
      }
      LightClocksec = constrain(LightClocksec, 0, 59);
      LightClockmin = constrain(LightClockmin, 0, 59);
    }

    if (EncoderSWstate == 1) {
      z == DIR_CW ? Mode -- : Mode ++ ;
      Mode = constrain(Mode, 0, 3);
      if (Mode == 0) {
        ////////STACK EXCHANGE?//// FLASH first digit on and off 5 times
      }

      if (Mode == 1) {
        ////////STACK EXCHANGE?//// FLASH second digit on and off 5 times
      }
      if (Mode == 2) {
       ////////STACK EXCHANGE?////  FLASH 3rd Digit On and of 5 times
      }
       }
     }

      ////switching

      FocusSWstate = digitalRead(FocusSW);
      MainSWstate = digitalRead(MainSW);

      if (FocusSWstate != FocusSWstatePRE ) {
        if (FocusSWstate == HIGH) {
          FocusSWCounter++;
        } else {}
      }

      FocusSWstatePRE  = FocusSWstate;
      if (FocusSWCounter % 2 == 0) {
        digitalWrite(RelayPIN, LOW);
      } else {
        digitalWrite(RelayPIN, HIGH);
      }

      if (MainSWstate != MainSWstatePRE ) {
        if (MainSWstate == HIGH) {
          digitalWrite(RelayPIN, HIGH);
          delay(((LightClockmin * 60) + (LightClocksec)) * 1000);
          digitalWrite(RelayPIN, LOW);
        }
        else {}
      }
      MainSWstatePRE  = MainSWstatePRE;

      //display

      byte bit[4];
      bit[0] = LightClocksec % 10;
      bit[1] = LightClocksec / 10 % 10;
      bit[2] = LightClockmin % 10;
      bit[3] = LightClockmin / 10 % 10;

      for (int i = 0; i < 4; i++) {
        chooseCommon(i);
        writeData(num[bit[3 - i]]);
        writeData(0xff);
      }
     }

    void chooseCommon(byte com) {
      // Close all single 7-segment display
      for (int i = 0; i < 4; i++) {
        digitalWrite(comPin[i], LOW);
      }
      // Open the selected single 7-segment display
      digitalWrite(comPin[com], HIGH);
    }

    void writeData(int evalue) {
      // Make latchPin output low level
      digitalWrite(latchPin, LOW);
      // Send serial data to 74HC595
      shiftOut(dataPin, clockPin, LSBFIRST, evalue);
      // Make latchPin output high level, then 74HC595 will update the data to parallel output
      digitalWrite(latchPin, HIGH);
    }

body:
When displaying the digits you need to compare the current digit number (`i`) with the digit number you want to flash. If it's a match then either display the number, or don't display the number. How you make that decision is to examine `millis()`.

Take a look at the `BlinkWithoutDelay` example in the IDE to see how to make something flash without using `delay()`, and apply that knowledge to blinking a digit.


message:
Generating 200 kHz pulse on Arduino Uno in normal mode

I need to obtain 200 kHz from Arduino Uno. I am using `Timer0`. I have configured it to run in normal mode and the Prescaler is set to clk/8 (the clock frequency of Arduino is 16 MHz). `TCNT0` is set to `0xFB` and the code toggles 2 pins of `PORTB` as timer overflow flag is set.

Here is my code (I am using Atmel Studio 7):

    #include <avr/io.h>

    int main(void)
    {
       DDRB = 0x03;
       PORTB |= 0x02;
       while (1)
       {
           TCNT0 = 0xFB;
           TCCR0A = 0X00;
           TCCR0B = 0x02;
           while ( (TIFR0 & 0x01) == 0 );
           PORTB ^= 0x03;
           TCCR1A = 0x00;
           TCCR1B = 0x00;
           TIFR0 = 0X01;
      }
    }

When I check on the oscilloscope, it shows that the pulse is 166 kHz instead of 200 kHz. Although I can use Fast PWM Mode and use interrupts, I am just curious to know why it doesn't work? Did I make any mistake?

body:
That's simple enough - you forgot that **everything takes time**.

Your timeline is:

1. Configure timer
2. Set count
3. Wait for count to overflow (33 ticks)
4. Toggle pin
5. Do something with T1 (why...?)
6. Clear overflow bit
7. Go back to 1.

Here's how that looks as assembly:

    90: 3b ef        ldi r19, 0xFB
    92: 42 e0        ldi r20, 0x02
    94: 23 e0        ldi r18, 0x03
    96: 91 e0        ldi r25, 0x01

    while (1) {
    98: 36 bd        out 0x26, r19 ; TCNT0 = 0xFB;
    9a: 14 bc        out 0x24, r1 ; TCCR0A = 0X00;
    9c: 45 bd        out 0x25, r20 ; TCCR0B = 0x02;

    while ( (TIFR0 & 0x01) == 0 );
    9e: a8 9b        sbis 0x15, 0
    a0: fe cf        rjmp .-4       ; 0x9e <setup+0xe>

    PORTB ^= 0x03;
    a2: 85 b1        in r24, 0x05
    a4: 82 27        eor r24, r18
    a6: 85 b9        out 0x05, r24

    a8: 10 92 80 00  sts 0x0080, r1
    ac: 10 92 81 00  sts 0x0081, r1
    b0: 95 bb        out 0x15, r25

    }
    b2: f2 cf        rjmp .-28

So assuming that the waiting for the timer overflow takes 8*4+
1=33 clock cycles, and referencing the datasheet for how long each instruction takes, we can add up everything in the main while loop:

    while (1) {
    98: 36 bd        out 0x26, r19 ; 1
    9a: 14 bc        out 0x24, r1 ; 1
    9c: 45 bd        out 0x25, r20 ; 1

    while ( (TIFR0 & 0x01) == 0 );
    9e: a8 9b        sbis 0x15, 0 ; 2 (at end)
    a0: fe cf        rjmp .-4     ; 33 (while running)

    PORTB ^= 0x03;
    a2: 85 b1        in r24, 0x05 ; 1
    a4: 82 27        eor r24, r18    ; 1
    a6: 85 b9        out 0x05, r24 ; 1

    a8: 10 92 80 00  sts 0x0080, r1  ; 2
    ac: 10 92 81 00  sts 0x0081, r1  ; 2
    b0: 95 bb        out 0x15, r25 ; 1

    }
    b2: f2 cf        rjmp .-28    ; 2

You can see that takes 48 clock cycles (We don't care about what is in the inner `while` except when it comes to finishing, and that's just the `SBIS` instruction). For 200kHz you want 40 clock cycles. You have 48. 16000000/48 = 333333. Divide by two for your pin toggling, and you get 166666Hz.

If you want to use this kind of method you need to ensure that the timer is completely free running and the overflow flag gets set at a regular interval, not just at 32 ticks after you start it.

You should be operating in CTC mode so it counts up from 0 to your target value and then resets back to 0 whilst setting the overflow flag. Your loop then looks like:

    while (1) {
        if ((TIFR0 & 0x01) == 0x01) {
            PORTB ^= 0x03;
        }
    }

All the timer configuration is done before the loop and it just runs and runs until you say otherwise.


message:
Headers linking - PlatformIO

For those who use the IDE Platform IO, I have an issue for you. I use to program a home application of sensor reading and use the library "JC_Button.h" to manage buttons. There are other third-party libraries, but this in especial is cumbersome. The project tree is shown below.

[![project-tree][1]][1].

The compile log of the build is [here][2]. I have few notion of what is happening. In my opinion, the project does not find the necessary lib.

Thank you in advance.

  [1]: https://i.stack.imgur.com/moXcM.png
  [2]: http://codepad.org/x3uVz30U

body:
It looks like you are not telling PlatformIO that you need the JC_Button library. Try adding this to your `platformio.ini` file:

    lib_deps = https://github.com/JChristensen/JC_Button


message:
Transistor as switch for signal and high current buzzer

I'm a newbie in transistor switching.

I have PIR sensors with C and NC onboard. NC is 12 V signal that I need to switch transistor (bipolar?) to emit 3.3 V (collector connected to 3.3 V).

[![Fire and PIR circuit][1]][1]

VCC equals 3.3 V. PIR is pin on ESP32.

 - Can you tell me if this circuit is okay or does it need additional edits?

**Note**: Q3, Q4 transistor number is random, if you can offer me suitable transistor I would be glad.

Next circuit:

ESP32 pin "ALARM" is connected to transistor (MOSFET N channel) base.

[![Alarm circuit][2]][2]

ALARM as device is connected to 12 V, required 300 mA to run and I need transistor to switch circuit. Relay is awful.

 - Is this circuit correct?
 - Do I need any additional edits?
 - Can you suggest me suitable transistor?
 - I don't know much about MOSFET shortcuts.

Third circuit I need is same as this but instead 12 V I need to switch 5 V.

 - I guess just to change MOSFET transistor?
 - Or use same as for 12 V?

Combined circuit schematic:

[![Fire, PIR and Alarm circuit schematic][3]][3]

  [1]: https://i.stack.imgur.com/0gRPV.png "Fire and PIR circuit"
  [2]: https://i.stack.imgur.com/Fw09E.png "Alarm circuit"
  [3]: https://i.stack.imgur.com/IyeXR.png "Fire, PIR and Alarm circuit schematic"

body:
I'll try to answer your post with "just words" and we will see how it goes. If it is not clear to you, i will post small schematic.

I do not recommend the first schematic that you posted.
You will likely reverse bias the BE (base emitter) junction with 12v. Most bipolar transistors have a maximum reverse BE bias of 5 v.

I do recommend using bipolar so that you dont have to study, understand the range of turn on voltages for a MOS transistor.

The bipolar is always 0.6v
and a Darlington bipolar is twice that.

Also, i dont know why you have the 100nF caps in there. They will guarantee a surge, everytime you turn the circuit on and hence put noise on your supply bus.

When I design a driver for a similar application i frequently use a TIP100 (https://www.digikey.com/product-detail/en/on-semiconductor/TIP100G/TIP100GOS-ND/1485300)

So use the basic design of your second circuit but use the TIP100.

ALWAYS have a resistor (10k ohms or so) to keep the leakage current (Icbo) from turning on the transistor when you dont want it on !

I would put all the loads into the Collector circuit in your second schematic, rather than make the uP drive your LED.

If your load is at all inductive (a coil) then ALWAYS put a reverse-biased diode across the load to catch any inductive kick back.

If this is all Greek to you, then just say so and I will draw a simple universal circuit that will work for 3.3v drive or 12v drive.

All the Best to you.
RP


message:
ESP8266 working as station while in AP mode

I'm programming an ESP8266 via the Arduino IDE with Arduino libraries.  I explicitly set the WiFi mode to `WIFI_AP`, but then, as described below, I'm still able to use it as both AP and station.  That leaves me unclear what's meant by the three modes available (`WIFI_AP`, `WIFI_STA`, and `WIFI_AP_STA`) since it seems that I've set to `WIFI_AP` explicitly but am getting behavior consistent with `WIFI_AP_STA`.

I have read various documents online about these modes. I think I'm clear on the conceptual difference between them.  What concerns / confuses me is that the actual behavior does not appear to match the specified behavior.

More detail:

Near the beginning of my `setup` function, I have this code

    WiFi.mode(WIFI_AP);
    WiFi.softAP(ssid, key);

    server.begin();

where `ssid` and `key` are strings defined with appropriate values, and `server` is a global variable of type `WiFiServer` that has been initialized outside of `setup`.  When run, I see the network with the given name on my phone and can connect to it with the given password.  I can then browse to the IP address assigned by the ESP8266 and set the webpage sent by the server that's been defined in code.  So far so good.

At some point later, inside my `loop`, a condition triggers the ESP8266 to connect to my router.  Specifically, I have this sequence of code that runs once that trigger occurs:

    WiFi.disconnect();
    WiFi.begin(router_ssid, router_key);
    auto status = WiFi.status();
    while ( (status != WL_CONNECTED) && (status != WL_CONNECT_FAILED) ) {
        delay(500);
        status = WiFi.status();
    }

As before, `router_ssid` and `router_key` are variables declared elsewhere with the proper values for my router.  I can verify from subsequent print statements, that the connection succeeds and get the IP address *as assigned by my router*. It is clear that the new IP is assigned by the router because it is on the subnet used by my router, which is different than the subnet the ESP8266 is defining in AP mode.

The ESP8266 is configured to serve a small webpage, as noted above. I can now reach that page using my phone, which is connected directly to the ESP8266 via the IP address assigned initially by the ESP8266 in AP mode, *and* I can also reach the same page from my laptop (connect to my router) using the IP address assigned by my router.  It would seem that I'm effectively in "AP+STA" mode now, despite having explicitly set to "AP" mode at the beginning.

So what's happening here?  Did I automatically switch to "AP+STA" mode when I called `WiFi.begin`?  If yes, what's the point (if any) of calling `WiFi.mode`?  If no, then why am I able to operate as if in "AP+STA" mode given the explicit setting of "AP" mode?

body:
WiFi.begin() is a function of the ESP8266WiFiSTAClass. It changes the WiFi mode for you to STA or AP+STA based on the current mode.

`begin` functions are in [ESP8266WiFiSTA][1]

`enableSTA` function is in class [ESP8266WiFiGeneric][2]

  [1]: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp
  [2]: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp


message:
Parsing example code in Adafruit GPS library with Ultimate Adafruit GPS

I've synced my Uno with the Arduino IDE and I'm using the below code to get the GPS coordinates.

    // Test code for Adafruit GPS modules using MTK3329/MTK3339 driver
    //
    // This code shows how to listen to the GPS module in an interrupt
    // which allows the program to have more 'freedom' - just parse
    // when a new NMEA sentence is available! Then access data when
    // desired.
    //
    // Tested and works great with the Adafruit Ultimate GPS module
    // using MTK33x9 chipset
    //    ------> http://www.adafruit.com/products/746
    // Pick one up today at the Adafruit electronics shop
    // and help support open source hardware & software! -ada

    #include <Adafruit_GPS.h>
    #include <SoftwareSerial.h>

    // If you're using a GPS module:
    // Connect the GPS Power pin to 5V
    // Connect the GPS Ground pin to ground
    // If using software serial (sketch example default):
    //   Connect the GPS TX (transmit) pin to Digital 3
    //   Connect the GPS RX (receive) pin to Digital 2
    // If using hardware serial (e.g. Arduino Mega):
    //   Connect the GPS TX (transmit) pin to Arduino RX1, RX2 or RX3
    //   Connect the GPS RX (receive) pin to matching TX1, TX2 or TX3

    // If you're using the Adafruit GPS shield, change
    // SoftwareSerial mySerial(3, 2); -> SoftwareSerial mySerial(8, 7);
    // and make sure the switch is set to SoftSerial

    // If using software serial, keep this line enabled
    // (you can change the pin numbers to match your wiring):
    SoftwareSerial mySerial(3, 2);

    // If using hardware serial (e.g. Arduino Mega), comment out the
    // above SoftwareSerial line, and enable this line instead
    // (you can change the Serial number to match your wiring):

    //HardwareSerial mySerial = Serial1;

    Adafruit_GPS GPS(&mySerial);

    // Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
    // Set to 'true' if you want to debug and listen to the raw GPS sentences.
    #define GPSECHO  true

    // this keeps track of whether we're using the interrupt
    // off by default!
    boolean usingInterrupt = false;
    void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

    void setup()
    {

      // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
      // also spit it out
      Serial.begin(115200);
      Serial.println("Adafruit GPS library basic test!");

      // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
      GPS.begin(9600);

      // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
      GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
      // uncomment this line to turn on only the "minimum recommended" data
      //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
      // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
      // the parser doesn't care about other sentences at this time

      // Set the update rate
      GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
      // For the parsing code to work nicely and have time to sort thru the data, and
      // print it out we don't suggest using anything higher than 1 Hz

      // Request updates on antenna status, comment out to keep quiet
      GPS.sendCommand(PGCMD_ANTENNA);

      // the nice thing about this code is you can have a timer0 interrupt go off
      // every 1 millisecond, and read data from the GPS for you. that makes the
      // loop code a heck of a lot easier!
      useInterrupt(true);

      delay(1000);
      // Ask for firmware version
      mySerial.println(PMTK_Q_RELEASE);
    }

    // Interrupt is called once a millisecond, looks for any new GPS data, and stores it
    SIGNAL(TIMER0_COMPA_vect) {
      char c = GPS.read();
      // if you want to debug, this is a good time to do it!
    #ifdef UDR0
      if (GPSECHO)
        if (c) UDR0 = c;
        // writing direct to UDR0 is much much faster than Serial.print
        // but only one character can be written at a time.
    #endif
    }

    void useInterrupt(boolean v) {
      if (v) {
        // Timer0 is already used for millis() - we'll just interrupt somewhere
        // in the middle and call the "Compare A" function above
        OCR0A = 0xAF;
        TIMSK0 |= _BV(OCIE0A);
        usingInterrupt = true;
      } else {
        // do not call the interrupt function COMPA anymore
        TIMSK0 &= ~_BV(OCIE0A);
        usingInterrupt = false;
      }
    }

    uint32_t timer = millis();
    void loop()                     // run over and over again
    {
      // in case you are not using the interrupt above, you'll
      // need to 'hand query' the GPS, not suggested :(
      if (! usingInterrupt) {
        // read data from the GPS in the 'main loop'
        char c = GPS.read();
        // if you want to debug, this is a good time to do it!
        if (GPSECHO)
          if (c) Serial.print(c);
      }

      // if a sentence is received, we can check the checksum, parse it...
      if (GPS.newNMEAreceived()) {
        // a tricky thing here is if we print the NMEA sentence, or data
        // we end up not listening and catching other sentences!
        // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
        //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false

        if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
          return;  // we can fail to parse a sentence in which case we should just wait for another
      }

      // if millis() or timer wraps around, we'll just reset it
      if (timer > millis())  timer = millis();

      // approximately every 2 seconds or so, print out the current stats
      if (millis() - timer > 2000) {
        timer = millis(); // reset the timer

        Serial.print("\nTime: ");
        Serial.print(GPS.hour, DEC); Serial.print(':');
        Serial.print(GPS.minute, DEC); Serial.print(':');
        Serial.print(GPS.seconds, DEC); Serial.print('.');
        Serial.println(GPS.milliseconds);
        Serial.print("Date: ");
        Serial.print(GPS.day, DEC); Serial.print('/');
        Serial.print(GPS.month, DEC); Serial.print("/20");
        Serial.println(GPS.year, DEC);
        Serial.print("Fix: "); Serial.print((int)GPS.fix);
        Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
        if (GPS.fix) {
          Serial.print("Location: ");
          Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
          Serial.print(", ");
          Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
          Serial.print("Location (in degrees, works with Google Maps): ");
          Serial.print(GPS.latitudeDegrees, 4);
          Serial.print(", ");
          Serial.println(GPS.longitudeDegrees, 4);

          Serial.print("Speed (knots): "); Serial.println(GPS.speed);
          Serial.print("Angle: "); Serial.println(GPS.angle);
          Serial.print("Altitude: "); Serial.println(GPS.altitude);
          Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
        }
      }
    }

When I compile and upload, it successfully does and the serial output displays something like this:

Time: 23:5:8.0
Date: 6/7/2018
Fix: 1 quality: 1
Location: 3855.8869N, 7721.3422W
Location (in degrees, works with Google Maps): 38.9314, -77.3557
Speed (knots): 0.32
Angle: 211.87
Altitude: 177.90
Satellites: 7
$PGTOP,11,2*6E
$GPGGA,230509.000,3855.8869,N,07721.3423,W,1,7,1.10,177.9,M,-33.4,M,,*64
$GPRMC,230509.000,A,3855.8869,N,07721.3423,W,0.28,211.87,060718,,,A*7F
$PGTOP,11,2*6E
$GPGGA,230510.000,3855.8869,N,07721.3424,W,1,7,1.10,177.9,M,-33.4,M,,*6B
$GPRMC,230510.000,A,3855.8869,N,07721.3424,W,0.28,211.87,060718,,,A*70

Everything seems okay except that the time is also offset by 4 hours?

body: GPS is probably giving you universal time (UTC).  Your profile says that you're in College Park, MD, so that's currently 4 hrs different due to daylight savings time.


message:
Serial.print changes serial output before it is called

I'm making a project with an sd card where the user enters a file name over the serial port, and then the aduino does thing to that file. Right now i'm working on getting the serial input to work, but one Serial.print() is somehow changing a variable/output of another Serial.print(), but before it is even called.
Here is my code:
char input, output;

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      Serial.println("Ready\nEnter input text");
      while (!Serial.available()); // wait till serial available
      delay(2000);
      byte avail = Serial.available() - 1;//extra newline char at end that we don't want
      char inBuf[avail];
      //Serial.println(avail);
      Serial.readBytes(inBuf, avail);
      Serial.read();
      Serial.print("'");
      Serial.print(inBuf);
      Serial.println("'");
      delay(1000);
      Serial.println(avail);//problematic line
    }

    void loop() {
      // put your main code here, to run repeatedly:

    }

When i have the line uncommented, the output is:

    Ready
    Enter input text
    'asd&.'
    4
When all i have typed is 'asd' (no quotes).
With the line commented out, the output is as expected:

    Ready
    Enter input text
    'asd'
I have no clue how it is happening, and should be physically impossible, since it is changing code before it is called.

body: Your string needs to end with a null character `'\0'`.  I think yours does not because of the way that you filled the buffer, so you're getting whatever junk is in memory next to your array printed in addition to the array itself.


message:
DC motor with L289N driver cannot set RPM lower than 130

My setup is using an Uno r3, and the motor driver is an L289N.

I am going to set it to run at a lower RPM, but when adjusting `enA` or `enB` to set to below 130, it won't spin.

    // connect motor controller pins to Arduino digital pins
    // motor one
    int enA = 2;
    int enB = 7;
    int in3 = 5;
    int in4 = 6;
    int in1 = 3;
    int in2 = 4;

    void setup()
    {
      // set all the motor control pins to outputs
      pinMode(enA, OUTPUT);
      pinMode(enB, OUTPUT);
      pinMode(in3, OUTPUT);
      pinMode(in4, OUTPUT);
    }
    void demoOne()
    {
      analogWrite(enB, 130);
      // turn on motor B
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      delay(500);
      digitalWrite(in1, LOW);
      digitalWrite(in2, LOW);
      delay(5000);
      // this function will run the motors in both directions at a fixed speed
      // turn on motor A
      // set speed to 200 out of possible range 0~255
      analogWrite(enA, 130);
      // turn on motor B
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
      // set speed to 200 out of possible range 0~255
      delay(100); //this function to set masa untuk rotation
      // now change motor directions
      // now turn off motor
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
      delay(5000);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      delay(200);
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
      delay(5000);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
      delay(200);
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
      delay(5000);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      delay(100);
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
      delay(5000);

      analogWrite(enB, 130);
      // turn on motor B
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);
      delay(400);
      digitalWrite(in1, LOW);
      digitalWrite(in2, LOW);
      delay(5000);
    }

    void loop()
    {
      demoOne();
      delay(3000);

    }

body:
Looks like you are controlling two motor outputs via the H-bridge, where the logic inputs are `in1,in2` and `in3,in4`.  First of all, you need

    pinMode(in1,OUTPUT);
    pinmode(in2,OUTPUT);

One reason why the motors may not spin for analogWrite value less than 130 is that, coincidentally, the voltage output is too low and motor stalls.  Test this two ways: does (1) changing the motor supply voltage or (2) changing the argument of `analogWrite` actually change the speed?

If no, it may be that `pinMode(enA,OUTPUT);` sets the output as digital and should be removed.  In that case a number less than 128 gets interpreted as a logic 0 and the motor will not spin.

P.S. your code can be neatened up using port syntax and bitwise operators.

    digitalWrite(in1,HIGH);
    digitalWrite(in2,LOW);

can be written on a single line with

    PORTD |= _BV(in1);

Also

    digitalWrite(in1,LOW);
    digitalWrite(in2,LOW);

becomes

    PORTD &= ~(_BV(in1) | _BV(in2));


body:
On an Uno, `D2` and `D7` (`enA` and `enB`) do not have true PWM (analogWrite) capabilities- they will be 100% on at values of 128 or higher, and off at 127 and lower.

You will need to use 3, 5, 6, 9, 10 or 11 for PWM (i.e. your `enA` and `enB`) on the Uno.

See [Arduino Reference - analogWrite()][1] for more info on PWM pin availability on Arduino boards.

  [1]: https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/


message:
Serial communication between 2 arduino's doesn't works when Sending string in a program with a lot of functions

Note :

This question is completely different from the questions that I have asked before although the code snippets might be the same, So please do not waive it as a duplicate right when you see it.

In my setup I have connected two arduino's Serially. An Arduino Mega is the one that is sending the string and a Arduino Uno is the one that's receiving it.

- Arduino Mega : TX1(19),RX1(18) - Serial1
- Arduino Uno : RX(10),TX(11) - using SoftwareSerial
- Gnd is connecetd on both boards

Arduino UNO - code is same for both cases

    #include <SoftwareSerial.h>
    SoftwareSerial s(10, 11);
    void setup()
    {
      delay(200);
      Serial.begin(9600);
      Serial1.begin(9600);
      s.begin(9600);
      while (!Serial) ;  // wait for Arduino Serial Monitor
    }
    void loop()
    {
      if(s.available()>0)
      {
         Serial.print("\nrec\n");
         delay(100);
         String b = s.readStringUntil('\n');
         delay(100);
         Serial.print(b);
         delay(40);
      }
   }

When the code in my arduino mega has only a print statement to send a string an infinite no. of times to the Uno, The Uno is receiving the string properly.

Arduino Mega

    void setup()
    {
      Serial1.begin(9600);
    }
    void loop()
    {
      Serial1.println("e2e4");
      delay(100);
    }

Now when I send the string an infinite no. of times from the Arduino mega but this time the mega has a lot more functions included in the program as well. In this case the Uno does not receive the string sent.

Arduino Mega - code containing a lot of functions and sedning a string to
                  Uno

    int SensorValStore_Prev[8][8] = { {0,0,0,0,0,0,0,0}, \
                                      {0,0,0,0,0,0,0,0}, \
                                      {1,1,1,1,1,1,1,1}, \
                                      {1,1,1,1,1,1,1,1}, \
                                      {1,1,1,1,1,1,1,1}, \
                                      {1,1,1,1,1,1,1,1}, \
                                      {0,0,0,0,0,0,0,0}, \
                                      {0,0,0,0,0,0,0,0} };

    int SensorValStore_Curr[8][8]={ {0,0,0,0,0,0,0,0}, \
                                    {0,0,0,0,0,0,0,0}, \
                                    {1,1,1,1,1,1,1,1}, \
                                    {1,1,1,1,1,1,1,1}, \
                                    {1,1,1,1,1,1,1,1}, \
                                    {1,1,0,1,1,1,1,1}, \
                                    {0,0,0,0,0,0,0,0}, \
                                    {0,1,0,0,0,0,0,0} };
    //int SensorValStore_Curr[8][8];
    int sum1[8],sum2[8],temp[8][8],k,l,i,j,rank,nextRow;
    String file,moveSan,Temp,bestMove;
    char Buffer[20];
    void doAction();
    void ReadSensor();
    void Difference();
    void binToIntCalc();
    void check();
    void getMovePlayed();
    void SendMove();
    void getMove();

    void setup()
    {
      Serial.begin(9600);
      lcd.begin(16,2);
      pinMode(22,INPUT_PULLUP); // Reed switch - Row1
      pinMode(24,INPUT_PULLUP); // Reed switch - Row2
      pinMode(26,INPUT_PULLUP); // Reed switch - Row3
      pinMode(28,INPUT_PULLUP); // Reed switch - Row4
      pinMode(30,INPUT_PULLUP); // Reed switch - Row5
      pinMode(32,INPUT_PULLUP); // Reed switch - Row6
      pinMode(34,INPUT_PULLUP); // Reed switch - Row7
      pinMode(36,INPUT_PULLUP); // Reed switch - Row8
      pinMode(2,INPUT_PULLUP);// Push Button
      pinMode(38,OUTPUT);
      pinMode(40,OUTPUT);
      pinMode(42,OUTPUT);
      pinMode(44,OUTPUT);
      pinMode(46,OUTPUT);
      pinMode(48,OUTPUT);
      pinMode(50,OUTPUT);
      pinMode(52,OUTPUT);
      pinMode(3,OUTPUT);
      digitalWrite(38,HIGH);
      digitalWrite(40,HIGH);
      digitalWrite(42,HIGH);
      digitalWrite(44,HIGH);
      digitalWrite(46,HIGH);
      digitalWrite(48,HIGH);
      digitalWrite(50,HIGH);
      digitalWrite(52,HIGH);
      digitalWrite(3,LOW);
    }

    void loop()
    {

      // doAction();
      delay(40);
      Difference();
      delay(40);
      binToIntCalc();
      delay(40);
      check();
      delay(40);
      getMovePlayed();
      delay(40);
      getMove();
      delay(40);
      //}
    }

    void Print(int matrix[8][8])
    {
      for(i=0;i<8;i++)
      {
        for(j=0;j<8;j++)
        {
          Serial.print(matrix[i][j]);
          Serial.print(" ");
        }
        Serial.println();
      }
    }

    void doAction()
    {
      nextRow = 0;
      for(i=0;i<8;i++)
      {
        digitalWrite(38 + nextRow,LOW);
        delay(40);
        ReadSensor(i);
        digitalWrite(38 + nextRow,HIGH);
        delay(40);
        nextRow +=2;
      }
    }

    void ReadSensor(int iter)
    {
      delay(10);
      for(j=0;j<8;j++)
        SensorValStore_Curr[iter][j] = digitalRead(j+2);
    }

    void Difference()
    {
      for(i=0;i<8;i++)
        for(j=0;j<8;j++)
          temp[i][j] = abs(SensorValStore_Curr[i][j] - SensorValStore_Prev[i[j]);

    }

    void binToIntCalc()
    {
      for(i=0;i<8;i++)
        for(j=0;j<8;j++)
        {
          sum1[i] += pow(2,j)*SensorValStore_Prev[i][j];
          sum2[i] += pow(2,j)*SensorValStore_Curr[i][j];
        }
     }

    void check()
    {
      k=0;
      l=0;
      for(i=0;i<8;i++)
      {
        if(sum2[i]>sum1[i])
          k = i;
        if(sum2[i]<sum1[i])
          l = i;
        delay(40);
      }
    }

    void getMovePlayed()
    {
      for(j=0;j<8;j++)
      {
        if(temp[k][j] == 1)
        {
          rank =k+1;
          file = String(char(97+j));
          delay(40);
          moveSan = file + rank;
          Temp = moveSan;
        }
      }
      for(j=0;j<8;j++)
      {
        if( temp[l][j] == 1)
        {
          rank =l+1;
          file = String(char(97+j));
          delay(40);
          moveSan = file + rank;
          Temp.concat(moveSan);
        }
      }
    }

    void SendMove(String movePlayed)
    {
      Serial.println("start");
      Serial.print(movePlayed);
      Serial.println();
    }

    void getMove() // SENDING STRING TO THE ARDUINO UNO
    {
     while(1){
      Serial1.println("e2e4");
      delay(100);
      }
    }

Note: getMove() is the function that sends the string to the arduino through Serial1

body:
My answer might not be what you'd expect but I'll try anyway.

Did you troobleshoot your serial communications ? Try doing a simple programm for both cards and try sending data from one to another.

Uno code

    #include <SoftwareSerial.h>

    #define rxPin 10
    #define txPin 11

    SoftwareSerial s(rxPin, txPin);

    String buff = "";

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

    void loop()
    {
        if(Serial.available)
        {
            while(Serial.available())
            {
                buff += char(Serial.read());
            }
            s.print(buff);
            buff="";
        }

        if(s.available)
        {
            while(s.available())
            {
                buff += char(s.read());
            }
            Serial.print(buff);
            buff = "";
        }
    }

Mega code

    String buff = "";

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

    void loop()
    {
        if(Serial.available)
        {
            while(Serial.available())
            {
                buff += char(Serial.read());
            }
            Serial1.print(buff);
            buff="";
        }

        if(Serial1.available)
        {
            while(Serial1.available())
            {
                buff += char(Serial1.read());
            }
            Serial.print(buff);
            buff = "";
        }
    }

Did you double check your connections ? Tx (mega) to rx (uno) and rx (mega) to tx(uno)

In your setup() on your arduino mega

    void setup()
    {
      Serial.begin(9600);
      lcd.begin(16,2);
      pinMode(22,INPUT_PULLUP); // Reed switch - Row1
      pinMode(24,INPUT_PULLUP); // Reed switch - Row2
      pinMode(26,INPUT_PULLUP); // Reed switch - Row3
      pinMode(28,INPUT_PULLUP); // Reed switch - Row4
      pinMode(30,INPUT_PULLUP); // Reed switch - Row5
      pinMode(32,INPUT_PULLUP); // Reed switch - Row6
      pinMode(34,INPUT_PULLUP); // Reed switch - Row7
      pinMode(36,INPUT_PULLUP); // Reed switch - Row8
      pinMode(2,INPUT_PULLUP);// Push Button
      pinMode(38,OUTPUT);
      pinMode(40,OUTPUT);
      pinMode(42,OUTPUT);
      pinMode(44,OUTPUT);
      pinMode(46,OUTPUT);
      pinMode(48,OUTPUT);
      pinMode(50,OUTPUT);
      pinMode(52,OUTPUT);
      pinMode(3,OUTPUT);
      digitalWrite(38,HIGH);
      digitalWrite(40,HIGH);
      digitalWrite(42,HIGH);
      digitalWrite(44,HIGH);
      digitalWrite(46,HIGH);
      digitalWrite(48,HIGH);
      digitalWrite(50,HIGH);
      digitalWrite(52,HIGH);
      digitalWrite(3,LOW);
    }

I don't see the `Serial1.begin(9600)` as said by @chrisl but you mentionned it above.

I hope this helps, sorry if I've not solved your problem.