message:
Reading I2C registers as slave device

I need to read the registers of a message gotten from `onReceive()`. I read [here][1] that

> There's nothing "magic" about the register pointer:  it's simply the first data byte in the packet.  So just write your I2C slave code so it examines the first received byte and treats it as an "opcode" for deciding how to interpret the rest of the packet.

So I thought that since hosts set registers by calling `write()` twice, I could just make my `onReceive()` handler function twice, like this
```
byte CURRENT_REGISTER = 0x00;

void onMessage(int numBytes){
  if(CURRENT_REGISTER == 0x00 && numBytes == 1){
    CURRENT_REGISTER = Wire.read();
    return;
  }

  char msg[numBytes];
  for(int i = 0; i < numBytes; i++){
    msg[i] = Wire.read();
  }

  //logic function goes here

  CURRENT_REGISTER = 0x00;
}
```
But then i noticed [here][2] that

> This first byte written here 'r' moves the register pointer to the register with address 'r'. You can think of the pointer as a read/write head.
>Now that the pointer is 'pointing' at the specific register you wanted, this command will **replace the byte stored in that register** with the value 'v'.

which made me think after `endTransmission()`, it only sent one message, which would ruin this idea.
Is this the case, and if so how can I obtain the registers as a slave?

  [1]: https://forum.arduino.cc/index.php?topic=13451.0
  [2]: https://forum.arduino.cc/index.php?topic=211587.0

body:
I just realized, what your actual question might be, so I'm prepending this to my answer:

With I2C and the typical register communication protocol, you have 3 communication patters:

- Master wants to write:
   - Master does transmission with first byte being the address of the register and following bytes being the data, that should be written to the addressed register (and following registers)
- Master wants to read:
   - Master does a 1 byte transmission with the address of the register, that is wants to read
   - Master starts a request for 1 or more bytes and the slave will send the previously requested register (and following registers, until no more bytes are available or requested)
- Some devices have sequential reads. For these devices the register address is not reset, when an operation is done. Thus the master could do more requests and read more data from the registers. Here the current register address is incremented on each read.

This means, that a master write cycle has only 1 transmission (only 1 `endTransmission()` in the master code), since every first byte in a master send transmission is handled as a register address. Your code snippet does not allow that. To solve that, just remove the check of `numBytes` and the return statement.

---

As mentioned in the comments, your question is really unclear. It seems you are asking things, that doesn't really make sense in the context of general I2C communication. So I will go over the basics and then point you in a good direction to solve your problem interfacing the Wiimote as peripheral.

**The I2C protocol:** This is the general communication protocol, that the Wiimote uses for its peripherals. It uses 2 lines and a master-slave structure. That means, that any communication is controlled by the master (the Wiimote in this case) and the slave (the peripheral, like a Motion+, a Nunchuk or your Arduino) cannot do anything by itself. The I2C protocol has markers for the start and end of a message and can address each slave on the bus with its specific address (which is send before the data). The protocol does **NOT** include any rules about the content of each message. So when writing code with the `Wire` library (the Arduinos library for interfacing the I2C hardware), you only get a buffer full of data bytes. It is up to you to interpret these bytes as needed for your application.

**Data structure protocol:** This protocol is imposed onto the data, that is end via I2C, so this is a higher level of abstraction and does not really have much to do with the I2C interface (you could use this data structure protocol with any binary communication interface, that has the concept of separated data packages). The data structure protocol defines the logic of the communication.

Here the registers come in. I2C is often used to interface simple sensor chips. These chips work by reading and writing to their internal memory. So the I2C interface exposes this internal memory to the master, who can now configure the sensor by writing data to the internal memory of the sensor, or read data from it.

An example: Lets imagine a simple distance sensor. It has 2 bytes/registers of internal memory. The first byte/register is for configuration of the sensor; the second byte/register represents the measured distance. The common communication protocol for such a chip can be:

    Master sends the address of the register, that it wants to access
    if Master wants to write to the register
        Master sends bytes to the slave
        Slave saves bytes into previously chosen register (and following registers)
    if masters wants to read form the register
        Master requests X bytes from the slave
        Slave sends X bytes with the content of the previously chosen register (and following registers)

The I2C master now wants to configure the sensor (for example setting the measurement frequency), thus writing a corresponding byte to the first byte/register. It will first send the address of the configuration register to the slave, which is 0 (first byte/register). Then it will send another byte, which is the new value of the configuration register.

Then our I2C master wants to read the distance measurement the sensor. For this it first sends the address of the register, that holds the distance measurement (1 aka second byte/register). Then it will request 1 byte from the slave. The slave will then send the content of the previously chosen register (register 1 aka distance measurement register).

So for the slave, the first byte of a Master send transmission is to be handled as a register address. More complex slave classes might have a 16bit (2byte) register address or even more.

---

Now to your problem mimicking a Wii Motion+. The description on the [site, that you linked to][1] is rather difficult. Unfortunately I cannot help much with that. But you can try to use an already existing library, that mimics a Wiimote peripheral: [Arduino-Wiimote][2]

I cannot guarantee, that is will work, but it is definitely a good start. If you don't want to use a library, but implement this yourself, you can still learn from how the library does it.

With more searching (for term combinations like "github wiimote arduino") you might find more libraries for this. I have only invested a limited amount of time.

  [1]: http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus
  [2]: https://github.com/denizkoekden/arduino-wiimote


sender: user

message:
Blink only one led in a led strip

I wish to blink only one led (number two in the strip) bit it does not do so, any idea why and how can I do it?

Code:

    #include "FastLED.h"

    //Number of LEDs
    #define NUM_LEDS 9

    //Define our clock and data lines
    #define DATA_PIN 11
    #define CLOCK_PIN 13

    //Create the LED array
    CRGB leds[NUM_LEDS];

    void setup() {
          FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS);
          FastLED.setBrightness(5);
    }

    void loop() {
      leds[0] = CRGB::Blue;
      leds[1] = CRGB::Green;

      //Blink this one only
      leds[2] = CRGB::Red;
      leds[2] = CRGB::Black;
      delay(500);
      leds[2] = CRGB::Red;

      leds[3] = CRGB::White;
      leds[4] = CRGB::Purple;
      leds[5] = CRGB::Green;
      leds[6] = CRGB::Blue;
      leds[7] = CRGB::Yellow;
      leds[8] = CRGB::Red;
      FastLED.show();
    }

sender: assistant

body:
Everytime, that you want the LEDs to change, you need to call the `FastLED.show()` function. You are doing that only once after you set the values multiple times. Also you need 2 delays in total (1 for the LED being on, 1 for it being off).

The workflow for blinking an LED would be:

    Set LED to on
    Call show function
    Delay
    Set LED to off
    Call show function
    Delay

You need to translate that to code.


message:
Part of Board exploded when Peltier Plate was wired t(o Board

Photos and Screenshots: https://i.stack.imgur.com/NazA6.jpg

By the way, I used a screenshot that was originally from this post: https://arduino.stackexchange.com/questions/13292/have-i-bricked-my-arduino-uno-problems-with-uploading-to-board

Hey guys,

I was trying to wire two TEC1-12706 Peltier plates to my breadboard, and I saw that using the USB connection for power was not enough for both plates. So, I found a 19v--3.9A DC/AC adapter/computer charger and plugged it in to my Uno via the Power Jack port. The Peltier plates were not wired to the board when I plugged it in and everything looked fine, all the normal LEDs on the UNO lit up, etc. Then, I wired a peltier plate to my breadboard. As soon as I did, a part exploded, and grey smoke come out of the "L" light area. I unplugged it immediately. The next day, I plugged the adapter back into the Power Jack port and a screenshot is attached of some observations I made by touching the board. Photos of my Uno are also attached. As you can see, the "Slightly less hot but still burning part" is pretty much destroyed. The "L" light will not light up and as of right now I can't upload any code to it. Might be an unrelated issue so I will continue troubleshooting that, but it is still another observation. The test LED I wired is lit up, so I guess the board can still kinda function? I'm high school student and obviously a complete beginner. Will continue to do research on this. I really want to know what happened. Please help?  Thanks everyone.

body:
You did a pretty good job of nuking your board. Gratz.

Basically what has happened: you connected 19V to the input of the 5V regulator (rated at 800mA max) and connected a 12V 50W device to the output.

I have no idea what a peltier will do when under powered, but at 12V it's going to want about 4A. That's 20x more than the 5V regulator can provide (also exacerbated by the massive amount of heat needed to be dissipated to drop 14V) - so it went *pop*.

In going pop it short circuited. That meant that 19V (or just short of) ended up going into the rest of your Arduino. The 3.3V regulator didn't like that (the bit that looks toasted), and neither will any of the rest of the components on the board.

In short: probably almost every component on the board has been nuked.

The moral of this story: don't connect high powered 12V devices direct to the Arduino. Things like peltier devices need their own dedicated power supply which can be controlled (as you would a motor or relay) through a power MOSFET.


message:
4 Pelteir Plate Water Bottle wired to Arduino Uno

Note - I plan to use the Arduino Starter kit to make this project.

Hey everyone,

I've had an idea for a project recently and I would like to get some insight on its plausibility. Is it possible to heat and cool a bottle of water using 4 pelteir plates? I'd like to heat up or cool a bottle of water using 2 pelteirs for heating and 2 for cooling. Could the amount of power for the peltiers to function be supplied from a laptop, computer, or battery pack? The role of the Arduino is to program in some safety features or some things to help the circuit function better if necessary. For example, a feature I want to add in is if the cold pelteirs are on, the hot peltiers are off if nessecary. I might add an LCD to display which setting is on/off if I can (example: Cold: ON, Hot: OFF)

Thanks guys.

body:
When it comes for amount of power from laptop, then this is not realy reasonable to expect even USB3, maybe some older laptops PCMCIA, or hardware docks. When it comes to Desk, They would have to be adjusted to get the ATX from PSU (it would have to be upgraded for purpose) We are still talking about a small Can or Yacult botle...

Even then insulate, insulate (and same again)

Then its a question of speed and how hot or cold) Battery pack that charges even when not used, used as buffer might work (for a short time).
Controlling it from Arduino is easy part using function that switches one on other off whenever you want and then calling the function itself to make sure both steps happen, rather then manualy editing or using one output for controlling power on/off and another on two way relay switching between sets (relay would increase consumption here).


body:
In a word, no. Laptop or desktop computer usually have USB ports, which put out like 10 watts of power for a "high current" USB port. That is not enough to do much heating or cooling. You want a high power supply. The pelteir plates I've seen run on 12V DC. Get a 5A 12V supply, or even higher.

You might be able to draw larger amounts of current from a USB-C port or a USB-C power supply, but why? Get a dedicated high current power supply that puts out the maximum voltage your peltier plates can handle.

Note that there is no reason to have 2 plates for heating and 2 plates for cooling. Run the current one way and they heat. Reverse the current and they cool.

Also I'm not sure of the value of using 2 plates to cool. A single plate able to handle more power would likely be more efficient, and easier to insulate. (With 2 plates you'd need 2 heatsinks, which will allow twice as much heat to leak through when the power is off. Doubling the current you feed into a single plate should give double he heating/cooling, without increasing the heat leakage when it's off. Just make sure you don't exceed the maximum rated current of your plate, and that you have a large enough heatsink to handle the heat transfer.)

You could use an H-bridge meant for controlling motors to provide either +12V or -12V under software control. Those generally handle high current.

You could also use a digital thermometer and make a thermostatically controlled system. You'd measure the temp in the bottle, and when it got to your desired temp range, turn off the power. When the temp moved outside the desired range, you'd turn the power back on.


message:
Teensy4.1 with 2x 8MB PSRAM Chips: external_psram_size=0 but EXTMEM char[] works as expected?

So I got 2x PSRAM chips from PJRC with my Teensy4.1 and soldered them on (it's a hideous job as I lost my tips) but it's all tested with a multimeter and the connections are solid.

I ran the [memtest sketch][1] from here compiled in both Teensyduino and PlatformIO:
https://www.pjrc.com/store/psram.html

Aaaaand external_psram_size is reading 0 for both cases. Setting the memory size manually in the program also fails (even with 8MB).

However... EXTMEM vars work as expected. I'm not sure how the mem addressing actually works with the provided memtest program, either - it certainly doesn't seem to use EXTMEM anywhere.

Here's my memory tester (run to crash):

    EXTMEM char bigBuf[10000000];
    //char bigBuf[10000];
    int c = 0;
    void setup() {
      c = 0;
    }

    void loop() {
      bigBuf[c] = 'a';
      Serial.println(bigBuf[c]);
      Serial.println(String(c));
      c = c + 1000;
      delay(1);
    }

Output with EXTMEM char[]: (as expected overflowed until 16MB)

    a
    0
    a
    100
    ...
    a
    16777100
    a
    16777200
Output with internal mem char[]: (as somewhat expected overflowed at 512K - max of RAM1)

    a
    0
    a
    100
    ...
    a
    488081
    a
    489081

Anyway, I'm glad EXTMEM works.. But can someone explain what's going on with the provided memtest? I admit I didn't read it over very well, but I thought that PSRAM could only be accessed via EXTMEM; how is it addressing otherwise?

  [1]: https://raw.githubusercontent.com/PaulStoffregen/teensy41_psram_memtest/master/teensy41_psram_memtest.ino

body:
I'm afraid your test program doesn't work as you intended. I tested it with a T4.1 without RAM soldered on and it gives the same result as in your question.

 1. You didn't declare your array volatile. Thus, the compiler can (and probably will) simply optimize the reading back away.
 2. Even if you declare the variable volatile the processor reads back the value from the cache line, i.e. you always get the correct value back, even without any external RAM.

Here a simple test program showing the effect. It always switches the LED on, even without external RAM soldered on the board.

```c++
EXTMEM volatile int test;

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

    test = 42;
    if(test == 42)
    {
        digitalWriteFast(13, HIGH);
    }
}

void loop(){
}
```

Here the disassembly of the setup function. It clearly shows that the processor tries to store 42 in the (non existing) external RAM and reads it back from there. Obviously the read back value comes from the cache line.
(comments added by me)
```
void setup()
{
      7c: push {r3, lr}                         // pinMode code
    pinMode(13, OUTPUT);                             //
      7e: movs r1, #1                           //
      80: movs r0, #13                          //
      82: bl 160c <pinMode>                       //-------------

    test = 42;
      86: ldr r3, [pc, #20] ; (9c <setup+0x20>)  // load r3 with address of 'test' (0x70000000, stored at 0x9C)
      88: movs r2, #42 ; 0x2a                   // load r2 with #42
      8a: str r2, [r3, #0]                         // store content of r2 at address stored in r3. i.e., store #42 0x7000'0000 (EXTRAM)

    if(test == 42)
      8c: ldr r3, [r3, #0]                         // volatile forces the compiler to read back 'test' (store it in r3)
      8e: cmp r3, r2                               // check if equals r2 (contains #42)
      90: bne.n 9a <setup+0x1e>                  // goto 0x9A if not equal

CORE_PIN13_PORTSET = CORE_PIN13_BITMASK;             // digitalwritefast code (next 3 lines)
      92: ldr r3, [pc, #12] ; (a0 <setup+0x24>)  // ...
      94: movs r2, #8                           // ...
      96: str.w r2, [r3, #132] ; 0x84           // -------

      9a: pop {r3, pc}                             // return from setup()

      9c: .word 0x70000000                       // Address of 'test'; EXTRAM starts at 0x7000'000
      a0: .word 0x42004000                       // Address of GPIO register for LED
```


body:
Paul here.  I'm the author of that memtest program, and also the creator of Teensy.  While luni64 already answered very well about your test program, hopefully I can add some clarity about the official memtest program.

Regarding "I thought that PSRAM could only be accessed via EXTMEM", indeed use of EXTMEM arrays or variables is the normal way.  But it is not the only way.  The memtest program uses pointers with the known address range of those memory chips.  Because the wires physically connect to the "FlexSPI2" peripheral inside the chip, the memory will always start at address 0x70000000.  You can find this detail on page 35 of the chip's reference manual.

https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf

Unfortunately the manual is tough to read and confusing in so many ways.  Even on page 35, it describes the memory as "ciphertext", which might be the case if the Bus Encryption Engine (mentioned on page 184) were used in a certain way.  No encryption is used, and if you read page 184 you'll see that engine only does decryption, so it really only could be used for read-only memory which is pre-loaded with encrypted data.

The point is we know the RAM always starts at 0x70000000 because of the way the hardware is designed.  If you look at the memtest code, you'll see it creates 2 variables called "memory_begin" and "memory_end", which are pointers used to directly access the memory within that known address range.

The idea behind the memory test is the entire memory is filled with a known data pattern.  This sort of testing is meant to catch any (very unlikely) internal problems inside the memory chips, where writing to one place inside the chip might corrupt data somewhere else in the same chip.

The pointer used is declared with "volatile" which prevents the compiler from trying to optimize away actual memory access.

After the memory is completely filled, you'll see a function called arm_dcache_flush_delete() is used.  Even if you use volatile to keep the compiler from optimizing away memory access, the Cortex-M7 hardware has 32K level 1 cache.  This function causes the ARM Cortex-M7 processor to completely write any cached data to the actual memory chip, and then delete the data from its cache.  Normally these special cache functions are only used by low-level driver code using Direct Memory Access (DMA), where you need to be sure data you've written is actually in memory before instructing a peripheral to use DMA to directly grab it from the memory (generally DMA-based peripherals can't access the cache), or before you read data a peripheral put into memory using DMA.  Normally you don't need to mess with the cache, but this sort of hardware testing and special benchmarking are the other sort of application where special attention to the processor's cache is important.

Then the entire memory is read back, using the volatile pointer so the compiler doesn't try to do anything too smart.  As the data is read, every 32 bit word is compared to the original pattern written.  Again, the idea is to check for the pretty unlikely case where the memory appears to work, but could theoretically have an internal problem where writing to one place causes corruption somewhere else inside the chip.

The entire test is repeated many times.  A variety of fixed 32 bit patterns are used.  Many of the tests fill the entire memory with a pseudo-random sequence, of course doing the same verification where any change to even just 1 bit within the entire memory range will be detected and reported as a failure.  Maybe that's overkill, but I tried to design the memtest program according to best practices described for testing PC memory, and those are the ways experts recommend to test memory (actually they recommend even more sophisticated & complex patterns... maybe someday I'll add those).

Hopefully this helps answer "can someone explain what's going on with the provided memtest?"

Regarding the soldering, a problem other people have seen involves the solder adhering only to the memory chip pin.  Even though it looks ok when viewed from above, it's possible for the solder to be a blob resting just slightly above the pad surface on the circuit board.  I would recommend re-heating the solder.  Allow time for it to fully heat and flow onto the pad.  While extra time heating isn't wonderful for the PSRAM chip, those chips are pretty hearty heat-size and if the memory isn't working you really don't have much to lose.  Counting to 10 while reheating the solder usually works.  If you have any liquid flux chemical, applying that before reheating might also help.

Focus your repair effort first on the chip mounted to the smaller set of pads next to the edge of the PCB.  The startup code looks for the first 8MB chip in that location.  If won't even look for the other chip if no memory is detected in the first location.


message:
analogRead() doesn't read more than 500Hz

I connected a wave generator to the analog pins to read the frequencies of the waves generated. I used different frequencies of sine waves with a minimum of 0V and maximum of 5V.

Whenever the voltage is greater than 2.5V, I made one of the digital pins HIGH, and LOW when less than 2.5V. Now by measuring the square wave from the digital pin, it always has the same frequency as the sine waves until 500Hz.

After 500Hz, the square wave's frequency doesn't agree with the sine wave, which made me think that the problem is in the `analogRead()`. Is there a way to have higher frequency?

Code:

```c++
const int sensorPin1 = A0;
const int sensorPin2 = A1;
const float maximumPower = 2.5;
int calibration = 1;

void setup() {
  Serial.begin(57600);
  pinMode(6, OUTPUT);
  digitalWrite(6, LOW);
}

void loop() {
  int voltage2 = 3;
  int voltage1 = 3;
  int sensorVal = abs(analogRead(sensorPin1) - analogRead(sensorPin2));
  float ratio = abs(analogRead(sensorPin2) / analogRead(sensorPin1));
  float voltageDifference = (sensorVal / 1024.0) * 5.0;
  float power = calibration * voltageDifference;
  if (power >= maximumPower || voltage1 <= 1 || voltage2 <= 1) {
    digitalWrite(6, LOW);
  }
  else {
    digitalWrite(6, HIGH);
  }
}
```

body:
You have 4 calls to `analogRead()` in your loop. At about 112 µs per
call, that's already taking 448 µs. Add to that the time taken by the
floating point calculations, and you are likely to end up with something
in the order of 500 µs per loop iteration. This should give you a
sampling rate close to 2 kHz, which should allow you to detect the highs
and lows of an input signal up to 1 kHz, provided the duty cycle is
close to 50%.

There are a couple of easy optimizations that could be done here. Two of
the calls to `analogRead()` serve no purpose, as the results are never
used. And the floating point calculations are also pointless. The whole
loop can be simplified to this:

```c++
void loop() {
    if (abs(analogRead(A0) - analogRead(A1)) >= 512) {
        digitalWrite(6, LOW);
    } else {
        digitalWrite(6, HIGH);
    }
}
```

This should take about 224 µs per iteration. If you need to go faster,
you will have to increase the working frequency of the ADC. This can
cost some accuracy, but if accuracy is not critical to your application,
it can be a good trade-off. See [Nick Gammon's page on the Arduino
ADC][adc] for details. If that's not enough, you will have to use
external components, e.g. an analog subtractor made from an op-amp, and
a couple of comparators.

[adc]: http://gammon.com.au/adc


message:
Can I run 3 motion sensors with a voltage regulator?

I want to power 3 hc-sr501 PIR motion sensors with a voltage regulator that can output 5v-1A.
If I make such a system, will there be a noise?

body:
Many internet sources [like this one][1] claim the HC-SR501 requires less than 50uA (or 0.00005 Amps).  Likely this is only in a quiet or quiescent state and current demand may increase initially when power is applied and when motion is detected.  Regardless, this is an insignificant fraction of a 2 Amp power supply.

Likely the Atmel 328p will require several times the total current of the 3 PIR sensors added together.  Still, the over all current of the described project (1 processor and 3 PIRs) is expected to be far less than half the capacity of a 2 Amp power supply.

It is suggested to keep the PIR to Arduino wires as short as possible to avoid noise.  It would be preferable they only be several inches (10s of centimeters).  And certainly not as long as several feet (a meter).

  [1]: https://www.espruino.com/Pyroelectric


message:
Storing data in Arduino Portenta H7's SDRAM

I am working on storing data from Portenta H7's ADC through a high sample rate (>100kSa/sec) per channel. I am using 2 ADC channel for my work.  Through the forum, I learned that the serial. print command reduces the sampling rate. Therefore one of the suggestions was to use the onboard available Portenta H7's 8MB SDRAM to store the sample values and then retrieving them after the sampling period. My sampling time is between 3-5 seconds so it is well within the storage limit of this SDRAM.

 However, since I have no previous experience with microcontrollers, I am struggling to find a starting point for accessing this SDRAM for saving my data?  Any suggestions from your side are most welcomed.

Please do recommend If you have any other ideas about managing the data for faster sampling.

You can find the Portenta H7 information here. https://store.arduino.cc/usa/portenta-h7. Portenta has STM32H747 dual-core processor.

Thank you all.

body:
    #include <SDRAM.h>

    SDRAMClass ram;
    uint8_t *b;
    void setup() {
      ram.begin();
      b = (uint8_t *)ram.malloc(320 * 240 * sizeof(uint8_t));
    }

The way to do it is to use the SDRAM library for the portenta. Above you see an example for a uint8 array.


message:
How to change ArduinoOTA upload timeout?

I'm using `ESP8266WiFiMulti`, `ESP8266WebServer` and `ArduinoOTA` to communicate with my device and perform over-the-air-updates. Everything was working perfectly until I moved the ESP8266 further from the WiFi router. The OTA upload slowed down, which caused upload timeouts after 5 seconds. It fails at a different point each time, usually between 30% and 60%.

How do I increase the OTA timeout to 30 seconds?

Here is the setup code, let me know if you need more:

```c++
void startWiFi() {
    ESP8266WiFiMulti wifiMulti;
    wifiMulti.addAP(ssid, password);
    wifiMulti.run();
}

void startOTA() {
    ArduinoOTA.setHostname(_hostname);
    ArduinoOTA.setPassword(_password);

    ArduinoOTA.onStart([]() {
        Serial.println("Start OTA");
    });
    ArduinoOTA.onEnd([]() {
        Serial.println("\nEnd OTA");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
        Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
        Serial.printf("Error[%u]: ", error);
        if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
        else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
        else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
        else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
        else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });
    ArduinoOTA.begin();
}
```

body:
The only timeout I can find is in the `espota.py` script itself. That is riddled with such lines as:

```
sock.settimeout(10)
```

You would need to scour that program and change them all.

<s>**However**

ArduinoOTA uses UDP for communication. Because of that it is *unreliable* (yes, that's a technical term). It doesn't have any form of retransmit / retry, so if a packet is lost it's lost for good. No amount of increasing of timeouts will make that packet reappear.

So increasing your timeouts most likely will just make it wait longer before failing.

You should consider switching to a more reliable update system which uses TCP instead of UDP - such as downloading an update from a website using `ESP8266httpUpdate`. </s>

**Update:**

ArduinoOTA uses a combination of both UDP (to initialise and authenticate the connection) and TCP (to make a "back channel" connection back to your computer) to download the actual binary.

The same still applies: you will need to alter the `espota.py` program to change its timeouts (`sock2` is the back-channel object), but there is also one line in `ArduinoOTA.cpp` that will need to be altered to increase timeouts.  [Line 294](https://github.com/esp8266/Arduino/blob/master/libraries/ArduinoOTA/ArduinoOTA.cpp#L294):

```
int waited = 1000;
```

This is not strictly the number of milliseconds to wait for incoming data, but it's not far off - it's a 1 millisecond delay in a loop while looking for incoming data.  Increasing that will allow more time for the ESP8266 to wait for data to arrive.

But of course, with an unstable WiFi connection YMMV...


message:
Whats wrong with my POST request?

Ive been trying to get POST working on my ESP8266. I followed this tutorial https://techtutorialsx.com/2016/07/21/esp8266-post-requests/ which works, but once i change the request URL to anything else i get -1 response from http.POST() which the library returns when "no info".

I have no clue what the "no info" means and what im doing wrong. Does anyone have any suggestions? Below is the code im using.

```
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status

    HTTPClient http;    //Declare object of class HTTPClient

    //http.begin("http://192.168.1.88:8085/hello"); //Works fine
    //http.begin("https://httpbin.org:8080/post"); //Causes -1 as httpCode
    //http.begin("https://httpbin.org/post"); //Causes -1 as httpCode
    http.begin("https://XXXXX.execute-api.eu-west-2.amazonaws.com/XXXXX/XXXXX");
    http.addHeader("Content-Type", "application/json");  //Specify content-type header

    int httpCode = http.POST("{\"key\":\"1\",\"id\": \"ESPXXX2\",\"action\": \"rbg\",\"value\": \"255255000\"}");   //Send the request
    String payload = http.getString(); //Get the response payload

    Serial.println(httpCode);   //Print HTTP return code
    Serial.println(payload);    //Print request response payload

    http.end();  //Close connection

  } else {

    Serial.println("Error in WiFi connection");

  }

  delay(10000);  //Send a request every 10 seconds
```
Only serial output im getting is "-1" for httpCode and empty line for payload.

body:
I ended up ditching HTTPS since it doesnt seem to be implemented all that well (Requires hardcoding of fingerprint).
Changed the architecture of my system so that HTTPS is handled by Python which doesnt require jumping through hoops.


message:
Recommend an Arduino Uno shield to monitor the state of 5 DPDT electrical switches

I have a project where I need to monitor the state of 5 DPDT electrical switches with Arduino Uno. Also, the Arduino board will be measuring the output from 3 thermocouples on 3 of the analogue pins as input and sending signals to open and close 3 relays for heaters on the 3 of the digital pins as output. The data with the state of the microswitches and the measurements from the thermocouples will be send over a serial connection to a PC.

I think I need a shield with at least 20 inputs for monitoring the 5 DPDT electrical switches (5 x 2 x 2). The common of the switches will be connected to a common rail. Can I use an I2C extension shield for this purpose? Is this going to create an issue with the serial connection? Any specific shield recommendations?

body:
If you're really set on measuring the state of every single connection of every single switch (though I still don't see the need) then yes, you'll need 20 IO connections.

You could create those with IO expanders (MCP23017 for example), or you could use multiplexing.

Instead of 4x5 (20) IO pins you'd instead need 2+10 (12) IO pins.

Treat all the "Common" connections as the rows of a keypad and all the NC and NO connections as the columns of a keypad. Add a smattering of diodes to isolate everything, and you can then scan through the switches one at a time checking each of the two switch states.

You can read more about keypad matrices [here](https://www.gammon.com.au/forum/?id=14175).


message:
How to use this confing function

For INA3221 current sensor, I found this [library](https://github.com/switchdoclabs/SDL_Arduino_INA3221), however, I don't understand how to use the `INA3221SetConfig()` function as defined in the .cpp file [link](https://github.com/switchdoclabs/SDL_Arduino_INA3221/blob/master/SDL_Arduino_INA3221.cpp).

    void SDL_Arduino_INA3221::INA3221SetConfig(void)
    {

          // Set Config register to take into account the settings above
          uint16_t config =
              INA3221_CONFIG_ENABLE_CHAN1 |
              // INA3221_CONFIG_ENABLE_CHAN2 |
              // INA3221_CONFIG_ENABLE_CHAN3 |
              INA3221_CONFIG_RESET |
              INA3221_CONFIG_AVG1 |
              INA3221_CONFIG_VBUS_CT2 |
              INA3221_CONFIG_VSH_CT2 |
              INA3221_CONFIG_MODE_2 |
              INA3221_CONFIG_MODE_1 |
              INA3221_CONFIG_MODE_0;
          wireWriteRegister(INA3221_REG_CONFIG, config);
        }

It seems like the function is called automatically when the `.begin()` function is called and whatever is defined in the config function is written to the register. The use of | operator confuses me. I tried to comment out the some settings to see if it works but it makes no difference. There isn't any documentation so I am in a fix. Could you please tell how can I change the configuration settings e.g. instead of all the three channels or change the config_mode?

body:
Without looking at the library, you can check yourself if this method (`INA3221SetConfig`) is called from the `begin` method (of the same class). Just trace back the methods manually until you find a call to this method.

About the `|` or 'bit-wise-or' operator (see https://en.wikipedia.org/wiki/Bitwise_operations_in_C), these are used to set bits in a byte/word/long.

Most registers have 8, 16 or 32 bits and with the `|` operator you can easily set multiple bits at the same time. Each value (e.g. `INA3221_CONFIG_ENABLE_CHAN`) has a value that is a power of 2 (mostly defined in the form `1 << ..something..` you can add them (with +) or `|` them together, but | is more clear what the purpose is and repeatedly calling `|` the same bit twice is not a problem (it still gives the same result).


message:
ESP8266: #include <Keyboard.h> causes fatal error: HID.h: No such file or directory

OS: Mac
Arduino: 1.8.13
Keyboard Library: 1.0.2

[![ESP8266][1]][1]

I have a generic ESP8266 board, and I have the following code

    void setup() {
      // put your setup code here, to run once:
      pinMode(LED_BUILTIN, OUTPUT);
      Keyboard.begin();
    }

    void loop() {}

However I get the following ouput:

> In file included from /Users/quba/Sandbox/sketch_feb07a/sketch_feb07a.ino:1:0:

/Applications/Arduino.app/Contents/Java/libraries/Keyboard/src/Keyboard.h:25:17: fatal error: HID.h: No such file or directory

 #include "HID.h"

                           ^

compilation terminated.

exit status 1

Error compiling for board Generic ESP8266 Module.

Could not find boards.txt in /Users/quba/Library/Arduino15/packages/arduino/hardware/megaavr/1.8.7. Is it pre-1.5?

  [1]: https://i.stack.imgur.com/aMsjO.jpg

body: The Keyboard library is for Arduino ATMega32U4 based Arduinos (and other similar ones with USB) only. The ESP8266 does not have USB, so how can it possibly use the Keyboard library?


message:
RFM95 digital io to control mute on PAM8403 to get rid of hiss while receiving

I am building a solution with an ESP32, a PAM8403 amp, a parallel TFT display, and a RFM95 LoRa module. All works great but I want to get rid of the noise that is generated when Lora is in receive mode.

I can do this by pulling pin 12 low on the PAM8403, which mutes all sound. However I have ran out of output pins on my ESP32, and it's too late to use a IO expander as the PCB has been built.

My initial idea was to use the RX/TX pins on the ESP32 when the unit was out of diagnostics mode. However if I can avoid this then that would be great. In my code when I issue `Lora.sleep() / Lora.idle()` the hissing goes away.

So I started to wonder if I could just trigger the mute function through another logic state that goes low when LoRa is idle and high when sleeping (allowing the mute to deactivate).

I am using the `LoRa` library by Sandeep Mistry, and I was wondering if I could use `DIO1, DIO2`, etc. as an IO PIN to control mute. If not, is it possible to use any of the already connected pins to behave in the desired way?

Thanks all in advance!

body:
No, there is no way you can use the DIO pins to indicate sleep mode. They can only be set to indicate certain events, and sleep/idle is not one of them.

However the nRESET pin is optional, and you can use the `setPins()` function in the LoRa library to change which pin it's connected to - and one option is to set it to `-1` in which case the library ignores it (this must be run *before* `.begin()` is called) as it's only used during `begin()` to initially reset the LoRa module.

You could either tie nRESET HIGH (to 3.3V) to never reset it, or couple it with the reset signal of another peripheral so it gets reset at the same time - just be careful with your initialisation order in this case so you don't reset the module after configuring it...


message:
can't connect paj7620 (gesture detector module) to nodemcu

I'm trying to connect paj7620 to nodemcu micro-controller. I have implemented the following code and it worked perfect on arduino uno. The problem is that I was made to migrate to nodemcu.

Here is my code:

```
/*
 * Copyright (c) 2015 seeed technology inc.
 * Website    : www.seeed.cc
 * Author     : Wuruibin
 * Modified Time: June 2015
 * Description: This demo can recognize 15 gestures and output the result.
 *     You can adjust the reaction time according to the actual circumstance
 *    by modifying "#define GES_REACTION_TIME  500".
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <ESP8266WiFi.h>
#include <Wire.h>
#include "paj7620.h"

/*
Notice: When you want to recognize the Forward/Backward gesture or other continuous gestures, your gestures' reaction time must less than GES_REACTION_TIME(0.8s).
        You also can adjust the reaction time according to the actual circumstance.
*/
#define GES_REACTION_TIME  800
#define GES_QUIT_TIME   1000

void setup()
{
 uint8_t error = 0;

 Serial.begin(9600);
 Serial.println("\nPAJ7620U2 TEST DEMO: Recognize 15 gestures.");

 error = paj7620Init();   // initialize Paj7620 registers
 if (error)
 {
  Serial.print("INIT ERROR,CODE:");
  Serial.println(error);
 }
 else
 {
  Serial.println("INIT OK");
 }
 Serial.println("Please input your gestures:");
    Serial.begin(115200);
  Serial.println();

  // Serial.print("Setting soft-AP configuration ... ");
  // Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");

  Serial.print("Setting soft-AP ... ");
  Serial.println(WiFi.softAP("NODEMCU") ? "Ready" : "Failed!");

  Serial.print("Soft-AP IP address = ");
  Serial.println(WiFi.softAPIP());
}

void loop()
{
 uint8_t data = 0, data1 = 0, error;

 error = paj7620ReadReg(0x43, 1, &data);    // Read Bank_0_Reg_0x43/0x44 for gesture result.
 if (!error)
 {
  switch (data)          // When different gestures be detected, the variable 'data' will be set to different values by paj7620ReadReg(0x43, 1, &data).
  {
   case GES_RIGHT_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_LEFT_FLAG)
    {
     Serial.println("Right-Left");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Right");
    }
    break;
   case GES_LEFT_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_RIGHT_FLAG)
    {
     Serial.println("Left-Right");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Left");
    }
    break;
    break;
   case GES_UP_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_DOWN_FLAG)
    {
     Serial.println("Up-Down");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Up");
    }
    break;
   case GES_DOWN_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_UP_FLAG)
    {
     Serial.println("Down-Up");
    }
    else if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    else if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Down");
    }
    break;
   case GES_FORWARD_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_BACKWARD_FLAG)
    {
     Serial.println("Forward-Backward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Forward");
     delay(GES_QUIT_TIME);
    }
    break;
   case GES_BACKWARD_FLAG:
    delay(GES_REACTION_TIME);
    paj7620ReadReg(0x43, 1, &data);
    if(data == GES_FORWARD_FLAG)
    {
     Serial.println("Backward-Forward");
     delay(GES_QUIT_TIME);
    }
    else
    {
     Serial.println("Backward");
     delay(GES_QUIT_TIME);
    }
    break;
   case GES_CLOCKWISE_FLAG:
    Serial.println("Clockwise");
    break;
   case GES_COUNT_CLOCKWISE_FLAG:
    Serial.println("anti-clockwise");
    break;
   default:
    paj7620ReadReg(0x44, 1, &data1);
    if (data1 == GES_WAVE_FLAG)
    {
     Serial.println("wave");
    }
    break;
  }
 }
 delay(100);
}
```

```
------------------------
|paj7620    | nodemcu  |
------------------------
| VCC       | 3.3v     |
------------------------
| GND       | GND      |
------------------------
| SCL       | D1       |
------------------------
| SDA       | D2       |
------------------------
```

After connecting the ports like the above table, I get the following error when I am trying to upload the code on nodemcu.

Would someone help me how to resolve this error?

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

**Wiring**
[![enter image description here][2]][2]

**PS** I have also tried [I2C Scanner](https://playground.arduino.cc/Main/I2cScanner/) as @timemage mentioned in comments.

[![enter image description here][3]][3]

**PS 2** It works properly when I connect the paj7620 to arduino compiling the above code.

[![enter image description here][4]][4]

**output:**
[![enter image description here][5]][5]

  [1]: https://i.stack.imgur.com/yek2q.png
  [2]: https://i.stack.imgur.com/JO9OG.jpg
  [3]: https://i.stack.imgur.com/VmCbG.png
  [4]: https://i.stack.imgur.com/H5Ll3.jpg
  [5]: https://i.stack.imgur.com/vRN7m.png

body:
You've gotten rather quiet over there since I suggested zooming in on your sensor board.  Just so this question doesn't circulate around in the system for years, here's *an* answer:

[![Zooming in on poorly soldered header.][1]][1]

Your soldering should closer to this.  Hopefully better, as these are ones I did:

[![Soldering][2]][2]

The solder short of sort web-up the sides of the pins. The use the term "fillet" for that.  Where your pads around the through-hole looks broader than the ones that are on the board above, it should probably look a bit better.  **There shouldn't be unfilled parts of the through-hole**, in any case.  At least not on the side you're soldering.

I expect it will at least show in the I2C scanner when you fix that.  It *may* show a different address from what is default in the library, in which case you may need to tell it to use the address that shows in the scanner.

  [1]: https://i.stack.imgur.com/xyETc.jpg
  [2]: https://i.stack.imgur.com/Ot9qN.jpg


body:
Special thanks to @timemage for his support. After struggling with the board for more than 6 hours it works properly. I will describe and give more details about how the problem was solved later on.

Arduino Uno has 5 Analog inputs, while there isn't any of them on nodemcu. To connect paj7620 to nodemcu, it is noticable that as @timemage said:
> "The A4 and A5 on the UNO are where the ATMega328P's I2C bus signals happen to be. Earlier versions of the Arduino UNO and related boards didn't have dedicated SDA and SCL headers as they do now. On those UNO that have SDA and SCL pins on the upper digital header, they are the same exact signal as those found on A4 and A5."

So the first schema was correct.

As it is implied from the fifth page of [this link](https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF) there isn't any difference among 3.3v inputs on nodemcu. But I have changed wiring like the following image and it works!

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

```
#COLOR MAPPING
RED: VCC - 3.3v
BLACK: GND
ORANGE: SCL - D1
GREEN: SDA - D2
```

I hope it helps, cause there isn't any way to trace the problem. :)

  [1]: https://i.stack.imgur.com/aJSUU.jpg


message:
LF: flexible scheduler/timer library

I'm working on a few arduino projects where I've needed a flexible scheduler and/or timer library and was wondering if anyone has a library they recommend?

**Case 1:**
I have a sensor that needs to collect observations every hour, but it has a specific  measurement sequence:
- Power up/boot (takes about 15 seconds)
- Warm-up for 60 seconds.
- Observe (2 min), collect raw data, generate stats
- Cool-down for 5 min.
- Power off

In this case have a single micro-controller acting as a data-logger that is controlling multiple sensors and writing to an SD card.

**Case 2:**
I have an oven that needs to be controlled to a user-specified temperature profile (up say to 6 points of change), i.e.:
- Turn on heater
- Set temperature, 100C and hold for 2 min
- Set temperature, 160C and hold for 15 min
- Set temperature, 250C and hold for 1 hr
- ....
- Set temperature, 100C and hold for 1 hr
- Turn off heater

I'm familiar with non-blocking timers and (in the past) have cobbled together a few simple timers with millis() and some ulong variables. Alas, the complexity and debugging time rapidly grows with the number of dependent timers. Before I sit down and sketch out a class definition, I figured I'd ask what others are using.

body:
Some libraries I find good (opinion-based):

* TaskManagerIO: https://github.com/davetcc/TaskManagerIO
   * does a good job at managing events / scheduling things for a certain (system) time, or even repetitively.
   * with that you could e.g. use a `scheduleFixedRate()` API to call a function every 60 minutes. Then starts the power up (I assume asynchronously, by setting a pin or something), and just primes the scheduler with the `scheduleOnce()` API to call another function in 15 seconds. That target function then starts the warmup and schedules the next function / step for 60 seconds into the future, et cetera. It would express the flow very naturally.
* If accurate timekeeping is needed so that it's really every hour, you might want to  use an external RTC module. Also depends on the microcontroller you're using, many have a builtin one that you can feed with a 32.768 kHz crystal and thus you don't need an external chip
  * library for the DS3231 / DS3232 RTC lets you set an alarm in the RTC: https://github.com/JChristensen/DS3232RTC/blob/master/alarm-primer.md
   * with that you can e.g. set an alarm for every 60 minutes and then execute your task.


message:
Help with NodeMCU based smart switch

The project I'm planning is to use a NodeMCU at each electrical board in house to control lights and fans via relays. Each MCU will communicate via MQTT over WiFi to a Raspberry Pi 4 from where I can control all lights and fans in the house. My doubt is:

Can the 3.3V NodeMCU drive a 5V relay like this [1 Channel 5V Relay Module with Optocoupler][1] since I can't find any 3.3 V relays in India. Or must I use a logic level shifter? Or just use an ESP32 board (double price).

  [1]: https://www.electronicscomp.com/1-channel-5v-relay-module

body: The relay I linked to couldn't be operated with 3v3 from the NodeMCU board. I was powering the NodeMCU via a breadboard power supply that had both 3v3 and 5v output (https://www.electronicscomp.com/mb102-breadboard-power-supply-module). I connected the Vcc and GND of relay to 5V supply on that module. the IO pin relay was connected to NoddeMCU. It worked fine and NodeMCU could switch it on and off.


message:
Any explanation for this behavior?

For the below code snippet
```
const char* fr_fbdb(char tag[30]) // fn for retrieving data
{
  char full_path[120];
  const char *_dt ;
  strcpy(full_path , base_path);
  strcat(full_path , tag);
  Serial.print( "retrieving from " );
  Serial.println(full_path) ;
  Firebase.get(firebaseData, full_path);
  _dt = firebaseData.cstrData();
//  Serial.print("while ext: ");
//  Serial.println(_dt);
  return _dt ;
}

void retreive_sch()
{
  int no_tag = strlen(*tag) ;
  //Serial.print("no. of tags in the DB: ");
  //Serial.println(no_tag);
  const char *_data[no_tag];

  Firebase.get(firebaseData, "/SCHEDULE DETAILS/SELECTED");
  sch_no = firebaseData.cstrData();

  Serial.print("extracting schedule");
  Serial.println(sch_no);

  strcat(base_path , sch_no); // base path w/ sch no.

  for (int i = 0 ; i < 6 ; i++)
  {
    _data[i] = fr_fbdb(tag[i]);
    Serial.print("while ext: ");
    Serial.println(_data[i]);

  }

  for(int i=0 ; i<6 ; i++)
  {
    Serial.print("after extraction:");
    Serial.println(_data[i]) ;
  }
}
```

This is the output:
```
retrieving  schedule changes -- setup
extracting schedule3
retrieving from /SCHEDULE DETAILS/SCHEDULE3/DATE
while ext: [1609612200000,\"inf\"]
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ FR
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ TO
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/WEIGHT
while ext: 29
retrieving from /SCHEDULE DETAILS/SCHEDULE3/TIME
while ext: \"6:30\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/frequency
while ext: \"-1\"
after extraction:"root":[]
after extraction:\"-1\"
after extraction:keep-alive
after extraction:\"-1\"
after extraction:"root":[]
after extraction:\"-1\"
```
As you can see, the output of the same variable ```_data[]``` inside that particular function changes.
Any idea why?

body:
The problem is these lines of code in your function `fr_fddb()`:
```
  Firebase.get(firebaseData, full_path);
  _dt = firebaseData.cstrData();
```

You didn't share enough code to make this clear, but `firebaseData` appears to be a global which you reuse. When you call its `.cstrData()` method you're getting a pointer to the same buffer each time, and that buffer is overwritten each time you call `Firebase.get()`.

You can verify this by printing the pointer value each time through, like so in your `retrieve_sch()` function:
```
  for (int i = 0 ; i < 6 ; i++)
  {
    _data[i] = fr_fbdb(tag[i]);
    Serial.print("while ext: ");
    Serial.println(_data[i]);
    Serial.printf("_data[i] pointer %p\n", _data[i]);
  }
```

You'll likely see that the 6 pointers are identical. The value is changing because you keep reusing the same string.

The easy fix is:
```
  Firebase.get(firebaseData, full_path);
  _dt = strdup(firebaseData.cstrData());
```

This allocates memory and stores in it a duplicate of the string that was fetched from Firebase. Your function will now return that and `firebaseData` can safely be reused.

This solution will require you to free that memory at some point when you're doing using it by calling `free(_dt);` or whatever you're holding the pointer in when you're done. I leave that as an exercise for you.


message:
[SOLVED]Normalization not working on input buffer. How to solve this?

I wrote a piece of code that takes input from a sensor which is called the World Famous Pulse Sensor from Analogue Pin 1 and stores it in an Array with 127 elements then finds the largest in it, divides the rest by the largest, multiplies by 64 which is the maximum y length on my OLED and prints it onto the OLED.
It still gives me pre-normalized and scaled values on Serial Plotter.

What am I doing wrong?
Here is my code.

    #include <U8glib.h>
    U8GLIB_SSD1306_128X64 u8g(12, 11, 8, 9, 10);
    int x, y;int Buffer2[128];
    void pageBP();
    const int pageCount = 1;
    int p;
    void (*pages[pageCount])() = {pageBP};
    int duration [pageCount] = {1000};
    void setup() {

      u8g.setFont(u8g_font_unifont);
      u8g.setColorIndex(1);
      p = 0;
      Serial.begin(9600);

    }

    void loop() {

    u8g.firstPage();
      do {
        (*pages[p])();
      } while( u8g.nextPage() );
      delay(duration[p]);
      p = p+1;
      if (p == pageCount)
        p=0;
    }

    void pageBP() {
      for(x = 0;x < 128;x++) {
    Buffer2[x] =(analogRead(A1)>>2);//IP for PPG
    Serial.println(Buffer2[x]);
    delay(5);
    }
    for(int i = 1;i < 128; i++)
        {
           if(Buffer2[0] < Buffer2[i])
               Buffer2[0] = Buffer2[i];
        }
        for(int i = 1;i < 128; i++)
        {
           64*(Buffer2[i]/Buffer2[0]);
        }
      for(x = 0;x < 127;x++) {

    u8g.drawLine(x, Buffer2[x], x, Buffer2[x+1]); //OP to OLED for ECG

    u8g.drawLine(64, 0, 64, 63);
    u8g.drawLine(0, 32, 128, 32);}
    for(x=0;x<128;x+=8)
    u8g.drawLine(x, 31, x, 33);
    for(x=0;x<64;x+=8)
    u8g.drawLine(63, x, 65, x);
    u8g.drawFrame(0, 0, 128, 64);
    }
Here is Garbage Graph.
[![enter image description here][1]][1]

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

body:
I will point out some problems with your code:

- Look at this line:

        64*(Buffer2[i]/Buffer2[0]);

    It doesn't do anything. You calculate a scaled value, but you are not saving it anywhere. You need to assign that value to a variable (like an element in a new array).

- With this code

        for(int i = 1;i < 128; i++)
        {
            if(Buffer2[0] < Buffer2[i])
                Buffer2[0] = Buffer2[i];
        }

    You are overwriting the first value in your buffer to find the highest value. That might not be a problem for you, but to be clean here, you should just use a new variable, that holds the highest value outside of the buffer.

- I'm not sure what you are trying to do with this line:

        u8g.drawLine(x, Buffer2[x], x, Buffer2[x+1]);

    Normally, you would want to draw a line from one point in the graph to the next. So the second x parameter would need to be the x value for the next point. Currently you are just drawing a vertical line. I would instead write

        u8g.drawLine(x, Buffer2[x], x+1, Buffer2[x+1]);

     since you already are only counting to 127 instead of 128.

- Even if you get the above right, the Serial Monitor would still show the unscaled values, since you are printing to Serial directly after measuring. So to display the scaled values in the Serial Monitor, you need to move the line

        Serial.println(Buffer2[x]);

    down to after the scaling, for example in the same for loop as the OLED display code.

- And finally you should really fix your indentation. That will make your code way more readable and thus better understandable. The Arduino IDE even has an autoformat feature, that you could use for that.


message:
Arduino IDE - scope of the pre-processor "#define"

I'm creating an Arduino library and have 3 files - a "test.ino" program, and two library/class files: "testLibrary.h" and a "testLibrary.cpp".

The library makes use of some hardware-specific resources such as registers and ISRs that depend upon which I/O pin is used, and this should be done at compile time.

I would like to *#define* a pin number in the main program which, at compile time, is used in the library to determine which code sections are activated. Since this will be a standard Arduino library for use by others, it should compile and run without users having to change their compiler or *#include* path to make it work.

But it seems that the scope of *#define* in the main program/sketch does not extend to the library.

test.ino
```
#define PIN_NUMBER 3
#include "testLibrary.h"
void setup() {}
void loop() {}
```

testLibrary.h
```
#ifndef _TESTLIBRARY_h
#define _TESTLIBRARY_h
#ifndef PIN_NUMBER
#error PIN is not defined
#endif
class test {
public:
  test();
  ~test();
};
#endif
```

testLibrary.cpp
```
#include "testLibrary.h"
test::test(){}*
test::~test(){}
```

Compiling the above branches to "#error" using the Arduino IDE 1.8.13 and also using Visual Studio with Visual Micro.

Is there a way for me to have an Arduino library use a "#define" from the main sketch?

body:
The scope of a `#DEFINE` macro is the translation unit. That is the current `.c` or `.cpp` file that is currently being compiled.

In you code `PIN_NUMBER` is defined in `test.ino`. The `#include` macro literaly copies the content of `testLibrary.h` into `test.ino`. So for the compiler this is working perfectly fine as `PIN_NUMBER` is defined.

Your `testLibrary.cpp` however is not happy with that. Including `testLibrary.h` for compilation lacks the definition of `PIN_NUMBER`.

The Arduino IDE is very limited and does not offer you a way to define `PIN_NUMBER` globally. This is usually done with the compiler argument `-DPIN_NUMBER=3`. All translation units will get this argument and thus the compilation would succeed. No need to define `PIN_NUMBER` in code.


message:
confirming this will blink LED at given frequency

I want to blink an LED at an specific frequency, ie: 7Hz

here what Im doing

    int ledPin = 4;
    float freq = 7;

    void setup() {
      pinMode(ledPin, OUTPUT);
    }

    float periodo() {
      float peri = 1/freq;
      float halfer = peri/2;
      float millisec = halfer*1000;
      return millisec;
      //return ((1/freq)/2)*1000;
    }

    void loop() {
      digitalWrite(ledPin, HIGH);
      delay(periodo());
      digitalWrite(ledPin, LOW);
      delay(periodo());
    }

Is this correct? is that the best way to do it?

thanks in advance!

body:
You can check if it is correct by timing it for one minute and check if it is (approximately) ok.

However, I see a few improvements:

- First is that you always return 1/7/2*1000 = 71.429, which is rounded down to 71. 71 * 14 = 994 ms so you get a bit faster speed than 7 Hz. if this is a problem you have to compensate for this.
- Another small problem is that you `delay`, but the `digitalWrite` commands also take some time which is not included for the delays. So you need also to take this into account when using a precise delay.
- When using floats I always use float constant numbers, like 1.0 and 7.0 instead of 1 and 7. This can especially be useful when you divide two integers (e.g. 1/7), which results in 0.14 this is rounded down to 0 as it is an int.

The best you can do is using the `millis` command. You keep a timer and compare it to the current `millis` value. If it is too high, do a state change. This will take into account every other method you do meanwhile the `digitalWrite`s.

Something like: (code fixed due to EdgarBonet's remarks)

    const float FREQ = 7.0; // Hz
    const int PIN_NR = 4;

    unsigned long _startTime;
    unsigned long _counter;

    int _currentState = LOW;

    void setup()
    {
      _startTime = millis();
      _counter = 0;
      _currentState = LOW;
      digitalWrite(PIN_NR, _currentState);
    }

    void loop()
    {
      if (_startTime + _counter * 1000.0 / FREQ / 2.0 >= millis())
      {
        _counter++;
        _currentState = ~_currentState;
        digitalWrite(PIN_NR, _currentState);
      }
    }

Some small notes:

- _currentState is the current state of the LED, with ~ you can flip it (it's called the `not` operator).
- _startTime is the (close to zero) value of the `millis` value at startup.
- Take in mind there is a limit how long this app can run or precise. `millis` works with ms, meaning you cannot get beyond 500 Hz, and you get 'approximations' with frequencies below in some cases. E.g. when Freq = 80 Hz, you get 1000 * 1 / 80 / 2 = 1000 / 160 = 6.25 => 6, which is actually 1000/6/2=83.3 Hz.
- Also the counter is added once per state change, and because of 1000 * _counter ... an overflow exists when _counter >= 256 * 256 * 256 * 256 / 1000 = about 4 million. With 1000 state changes per second, this happens after 4000 seconds, which is 66 minutes. For 7 Hz it will not occur fast.


message:
How to wire and control a 16mm button with 2 legs using arduino?

I can't find any tutorials online explaining how to wire and control a 16mm push button like the one in the picture:

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

  [1]: https://i.stack.imgur.com/2H6vG.jpg

Do  you have any suggestions as to how use it with an arduino or a raspberry pi?

body:
A pushbutton is a pushbutton. It is a momentary switch. Since it has flexible wires, and needs a place to mount, you should probably wire it using a breadboard.

That pushbutton looks like a panel mount pushbutton. You might want to mount it in a pice of plastic or sheet metal. (Unscrew that nut up by the red part that you press. Measure the outside diameter of the threaded part. Drill a hole ≈1/64" (≈0.4MM) bigger than the switch diameter into the plastic/metal. Insert the pushbutton from underneath the panel. screw the nut back on to secure it. Tighten moderately tight with needle-nose pliers, being careful not to round off the corners of the nut.

To wire it:

Get a breadboard. Run wires from your Arduino to the breadboard.

Wire the pushbutton into the breadboard as well.

There are various libraries that offer switch debouncing, or you can write your own fairly easily.

I suggest using INPUT_PULLUP mode, and wiring your switch between an Arduino digital input and ground. When the switch is open, the input will read HIGH. When you press the the switch, the input will drop to LOW.

If you want to debounce the switch input yourself: When the switch changes state, note the value of `millis()`, and ignore any new changes for a brief period (try 20-100 mS).


message:
What is touch_pad_get_status() supposed to return?

What I want to do:
I have 7 touch buttons on my board (ESP32 TTGO T-Display) and I want to attach interrupts to everyone, calling the same function.
In this function I would like to use touch_pad_get_status() or other to get which button was touched. Then a switch case would do the rest.

What I'm facing:
This code

      Serial.print("Button ");
      uint32_t touch = touch_pad_get_status();
      Serial.println(String(touch));

always returns 0, no matter what.

What I've tried:
Including this part of code to the setup

      touch_pad_init();
      touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); //tried the SW MODE too
      touch_pad_io_init(TOUCH_PAD_GPIO15_CHANNEL);

But nothing seem to work. I don't want to make 7 different functions...

Thanks in advance.

body:
As pointed out from people in the comments, things need to be different.
If you use the function `touchAttachInterrupt`, things are a bit simpler.
The example that comes with the ESP32 library is enough to make you understand.

If you want to do what I did, this is how:

      touch_pad_init();
      touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
      touch_pad_config(TOUCH_PAD_GPIO2_CHANNEL, 500);
      touch_pad_config(TOUCH_PAD_GPIO15_CHANNEL, 500);
      touch_pad_config(TOUCH_PAD_GPIO13_CHANNEL, 500);
      touch_pad_isr_register(TouchButton, NULL);
      touch_pad_intr_enable();

Put this code in the `setup()`. Of course needs the `init()`, but also needs to be set to timer mode, or otherwise you're going to need to `start()` probably.
The `config()` is to configure the pin as an interrupt. I've set 500 in the threshold because the readings of `touch_pad_read()` told me it went from 800 untouched to 50 touched, so the midterm I chose 500.
`isr_register` is the function that tells to call `TouchButton()`, with `NULL` as argument to it.

    void TouchButton(void *arg)
    {
      uint32_t touch = touch_pad_get_status();
      touch_pad_clear_status();
      Serial.print("Button ");
      Serial.println(String(touch));
    }

This is the declaration of the callback function I've done. It should be noted that `clear_status()` should be called as soon as possible after the `get_status()`, preventing the system from panicking (that's the name). You'll also see in the serial monitor that each button represents a power of 2. That's because the `get_status()` returns the pin mask in binary. So just do something similar to this

    for (int i = 0; i < TOUCH_PAD_MAX; i++) {
        if ((pad_intr >> i) & 0x01) {
            s_pad_activated[i] = true;
        }
    }

and you'll get a vector of which one was pressed.


message:
String comparison problem

I have this callback function in my Firmata sketch. It receives a string as a character array and does something with it. The problem is, that the string is being sent to the Arduino in `T\0h\0i\0s\0` form - after each character there is a `\0` terminator. As you can see, my function is switching the d13 LED on if the string incoming is `COMMAND`. I had tried to use several comparison methods:
- `strcmp(myString, "COMMAND") == 1`;
- `myString == "COMMAND"`;
- `strcmp(myString, "COMMAND\0") == 1`;
- `myString == "COMMAND\0"`;
- `strcmp(myString, "C\0O\0M\0 M\0A\0N\0D\0") == 1`;
- `myString == "C\0O\0M\0 M\0A\0N\0D\0"`;
- `==` with saving the `COMMAND` to a char array variable;
- `strcmp` with saving the `COMMAND` to a char array variable;
- last two things with converting both the incoming and the needed to a String instance;
- comparing a String instance with a directly stated `"COMMAND"`...

Nothing works. How can I compare the strings workably?

Full Arduino sketch:
```c++
#include <Firmata.h>

void stringCallback(char *myString)
{
  if (strcmp(myString, "COMMAND") == 1) {
    digitalWrite(13, HIGH);
  }
  Firmata.sendString(myString);
}

void sysexCallback(byte command, byte argc, byte *argv)
{
  Firmata.sendSysex(command, argc, argv);
}

void setup()
{
  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(STRING_DATA, stringCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.begin(57600);
  pinMode(13, INPUT);
}

void loop()
{
  while (Firmata.available()) {
    Firmata.processInput();
  }
}
```

Full code of the desktop program:
```python
import pyfirmata, time

class CustomArduino(pyfirmata.Arduino):
    def __init__(self, port: str):
        pyfirmata.Arduino.__init__(self, port)
        self.iterator = pyfirmata.util.Iterator(self)
        self.iterator.start()

        self.add_cmd_handler(0x71, self.receiveString)

    def receiveString(self, *args, **kwargs):
        print(f'Raw: {args}\n'
              f'Received: {pyfirmata.util.two_byte_iter_to_str(args)}')

    def sendString(self, data):
        self.send_sysex(0x71, pyfirmata.util.str_to_two_byte_iter(data))

    def send_sysex(self, sysex_cmd, data=[]):
        """
        Sends a SysEx msg.
        :arg sysex_cmd: A sysex command byte
        : arg data: a bytearray of 7-bit bytes of arbitrary data
        """
        msg = bytearray([pyfirmata.pyfirmata.START_SYSEX, sysex_cmd])
        msg.extend(data)
        msg.append(pyfirmata.pyfirmata.END_SYSEX)
        self.sp.write(msg)

print('STRING TESTER\nPlease input your COM port: ', end = '')
myCom = str(input())
device = CustomArduino(myCom)

while True:
    device.sendString(input('Send: '))
    time.sleep(1)
```

Strange detail: my Arduino is on the `COM6` COM-port. If I connect it via my program and send `com6` to the arduino, the D13 LED turns on!

body:
As @timemage stated, `strcmp` returns `0` for equal. Sincerely in the provided code, while you send a message, which contents are **not** `COMMAND`, the LED will be turned on.

To get what we need, we must compare `strcmp` return value with `0`! If it equals, then the strings match, and your suggested code is being executed:

```c++
void stringCallback(char *myString)
{
  if (strcmp(myString, "COMMAND") == 0) {
    digitalWrite(13, HIGH);
  }
  Firmata.sendString(myString);
}
```


message:
Difference between char array and unsigned char array

I have written a small test code for Arduino Uno which is as follows:

    unsigned char tes[4];
    char testing[4];

    void setup() {
        Serial.begin(9600);
        for (int i = 0; i < 4; i++) {
            testing[i] = i;
            tes[i] = i;
        }
        for (int i = 0; i < 4; i++) {
            Serial.print("unsigned char is: ");
            Serial.println(tes[i]);
            Serial.print("char is: ");
            Serial.println(testing[i]);
        }
    }

    void loop() {
    }

and the output which I get is as follows

    unsigned char is: 0
    char is:
    unsigned char is: 1
    char is:
    unsigned char is: 2
    char is:
    unsigned char is: 3
    char is:

Can someone help me out why is the difference in output.

body:
An unsigned char is treated as a number, and a signed char as a character.
See the https://simple.wikipedia.org/wiki/ASCII table for the result.


body:
***tl;dr : Since unsigned char is represented as a byte value, the output to the serial is the byte representation, not the char***

I re-wrote the code you had for reference:

    #define CHARS 255
    #define BAUD 115200

    unsigned char unsChar[CHARS];
    char sinChar[CHARS];

    void setup() {
      Serial.begin(BAUD);
      Serial.println("~~Setup~~");
      for(int i = 0; i < CHARS; i++) {
        unsChar[i] = (unsigned char)i;
        sinChar[i] = (char)i;
      }
    }

    void loop() {
      Serial.println("~~Loop~~");
      for(int i = 0; i < CHARS; i++) {
        Serial.print("INDEX        : ");
        Serial.println(i);
        Serial.print("unsigned char: ");
        Serial.println(unsChar[i]);
        Serial.print("         char: ");
        Serial.println(sinChar[i]);
        Serial.println("---------------------");
      }
      delay(10000);
    }

When you run this you'll see the [`unsigned char`][1] is simply printed to the serial like any other `byte` value but the [`char`][2] value is printed as a character according to the [ASCII chart][3].

If you compare the documentation for [`unsigned char`][1]

> **An unsigned data type that occupies 1 byte of memory**. Same as the byte datatype.

The unsigned char datatype encodes numbers from 0 to 255.

For consistency of Arduino programming style, the byte data type is to be preferred.

versus a normal (signed) [`char`][2]:

> A data type used to store a character value. Character literals are written in single quotes, like this: 'A' (for multiple characters - strings - use double quotes: "ABC").

Characters are stored as numbers however. You can see the specific encoding in the [ASCII chart][3]. This means that it is possible to do arithmetic on characters, in which the ASCII value of the character is used (e.g. 'A' + 1 has the value 66, since the ASCII value of the capital letter A is 65). See [`Serial.println`][4] reference for more on how characters are translated to numbers.

**The size of the char datatype is at least 8 bits.** It’s recommended to only use char for storing characters. For an unsigned, one-byte (8 bit) data type, use the byte data type.

So size wise an array of chars and unsigned chars are going to be the same. It's more about the representation of the underlying number (byte) and what works best for your use case.

  [1]: https://www.arduino.cc/reference/en/language/variables/data-types/unsignedchar/
  [2]: https://www.arduino.cc/reference/en/language/variables/data-types/char/
  [3]: https://www.arduino.cc/en/Reference/ASCIIchart
  [4]: https://www.arduino.cc/reference/en/language/functions/communication/serial/println


message:
IR receiver receives only 0

I am trying to decode IR codes of my Samsung tv remote

But the receiver always receiving "0"

Schematics:

[![Schematics][1]][1]

Code:
```
#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

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

void loop()
{
  if (irrecv.decode(&results))
    {
    int value = results.value;
    Serial.println(" ");
    Serial.print("Code: ");
    Serial.println(results.value);
    Serial.println(" ");
    irrecv.resume();
    Serial.println("*****************");
    }
}
```

Please help me to decode my IR codes

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

body:
Next update with [3.1 of the library][1], you need to call `irrecv.decodedIRData.decodedRawData` to get the data. This code worked for me:

    #include <IRremote.h>

    int IRpin = 11;
    IRrecv irrecv(IRpin);

    void setup()
    {
      Serial.begin(9600);
      irrecv.enableIRIn(); // Start the receiver
    }

    void loop()
    {
      if (irrecv.decode())
        {
          Serial.println(irrecv.decodedIRData.decodedRawData); // Print the Serial
          irrecv.resume();   // Receive the next value
        }
    }

  [1]: https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-3x-version


message:
SSD1306 unable to display Text and waveform cohesively.Why?

Here is my code I am collecting data using an ECG sensor and trying to enhance the incoming data by stretching it across the x axis. Which results in this.
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/jqY7T.jpg
After this the screen eventually just goes black. What am I doing wrong?
 This is my code.

    #include <U8glib.h>
    U8GLIB_SSD1306_128X64 u8g(12, 11, 8, 9, 10);
    int Buffer[128];int Buffer2[128];int max=0;
    //int largest;
    void pageECG();     // Page-1

    const int pageCount = 2;
    int p;
    void (*pages[pageCount])() = {pageECG};
    int duration [pageCount] = {10000};
    void setup() {

      u8g.setFont(u8g_font_unifont);
      u8g.setColorIndex(1);
      p = 0;
      Serial.begin(9600);

    }

    void loop()
    {
    u8g.firstPage();
      do {
        (*pages[p])();
      } while( u8g.nextPage() );
      delay(duration[p]);
      p = p+1;
      if (p == pageCount)
        p=0;
    }
    void pageECG() {
    for(int x = 0;x < 128;x++)
    {
    Buffer[x] =(analogRead(A0)*0.075);//This loop takes data input
    delay(5);
    if(Buffer[x]<32&&Buffer[x]!=2)
    x-=2;
    if(Buffer[x]>32&&Buffer[x]!=62)
    x+=2;
    Serial.println(Buffer[x]);
    }

    for(int x = 0;x < 127;x++)
    {
    u8g.setFont(u8g_font_unifont);
    u8g.drawStr( 0, 60, "ECG");
    u8g.drawLine(x, Buffer[x], x,Buffer[x+1]); //OP to OLED for BP

    }}

body:
Well, one problem is this: You have made an array of pointer to function, but only initialized the first of the two, to `pageECG`.

```c++
const int pageCount = 2;
int p;
void (*pages[pageCount])() = {pageECG};
```

The last line there roughly equivalent to:

```c++
void (*pages[pageCount])() = {pageECG, nullptr};
```

Later in `loop()` you have:

```c++
  u8g.firstPage();
  do {
    (*pages[p])();
  } while( u8g.nextPage() );
  delay(duration[p]);
  p = p+1;
  if (p == pageCount)
    p=0;
```

After the first execution of `loop()`, `p` is 1.  Since it was not 2, it was not reset by your `if (p == pageCount) p=0;`  So on the next pass through `loop()`, `(*pages[p])();` is     `(*pages[1])();`  where `pages[1]` is `nullptr`.

In practice, what you're doing is generating and executing an AVR `icall` (indirect call) instruction to address 0x0000 (`nullptr` representation) to the reset vector.  So, your sketch starts over almost like a reset, except the hardware has not been reset.  Importantly, the interrupts are still configured as they were and the global interrupt flag is on, which means all manner of potential weirdness if one of them manages to execute before you get back ground `setup().`  So, it's difficult to say exactly why you're seeing what you're seeing.  But, it doesn't surprise me as a potential outcome.  And it may not be the *only* problem; just *a* problem.


message:
Configure input pullup through registers

I can set pin mode to input or output through the DDRx registers. How can I enable the internal pullup resister through a register?

body:
Credits to GoForSmoke.
Also see Gerben's comment below.

See: https://forum.arduino.cc/index.php?topic=286145.0

    byte ddrcMask =       ~
    (
            (1 << DDC0) |  // pinMode( 14, INPUT ); // Set to input
            (1 << DDC1) |  // pinMode( 15, INPUT ); // Set to input
            (1 << DDC2) |  // pinMode( 16, INPUT ); // Set to input
            (1 << DDC3)    // pinMode( 17, INPUT ); // Set to input
    );

    byte portcMask =
    (
            (1 << PORTC0) |  // digitalWrite( 14, HIGH ); // Enable the pullup
            (1 << PORTC1) |  // digitalWrite( 15, HIGH ); // Enable the pullup
            (1 << PORTC2) |  // digitalWrite( 16, HIGH ); // Enable the pullup
            (1 << PORTC3)    // digitalWrite( 17, HIGH ); // Enable the pullup
    );

    byte pincMask = ( (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) );

    void setup( void )
    {
      // Configure the pins for input
      DDRC = DDRC & ddrcMask;

      // Enable the pullups
      PORTC = PORTC | portcMask;

      // Read all four inputs
      uint8_t Pdat = PINC & pincMask;
    }

    void loop( void )
    {
    }


message:
Ethernet shield issues (defective shield?!)

I'm a newbie in using the **Arduino Ethernet Shield v2** (Arduino product code [A000024][1]) and I'm experiencing some strange behaviours on a critical work with strict deadline.

The project involve some Arduino (both UNOs and MEGA2560s) sending sensor data via OSC to a couple of destination PCs for later processing.

To do that I'm using what it seemed to me to be a quite simple to use Arduino OSC library, the [CNMAT one][2].

I've noticed this fact, which I think is related to some hardware malfunction.

I've found my code getting stuck even with a correct setup of the LAN. The code stops working, stops sending OSC messages, Ethernet shield is no more reachable with the *ping*. This persists also after loading again the code, or manually resetting the Arduino board. Initially I thought it was my fault but I've found that, substituting the shield with another one, the problem magically disappeared. On one of the problematic shield I've also experienced many continuous shutdowns and startups of the Arduino every 5 seconds (firmware restart from the setup)!

Are these ethernet shields known to be defective or having some issues?
The strange thing is that I've experienced this problem on 3 out of 8 of them: this is super critical!
Have you experienced something similar? Do you know of similar problems occurred before?

---

For debug purposes, here's a code test I've written and tried on a single Arduino UNO, always the same, using the same LAN setup (ethernet cable, IP addresses, Ethernet switch) switching two different Ethernet shields:

```c++
/* NET stuff ********************************************/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
EthernetUDP Udp;

IPAddress ip(10, 3, 3, 210); // the Arduino's IP
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x83, 0xCE };

#define DELAY 1000

// SETUP //////////////////////////////////////////////////////////////////
void setup() {

  Serial.begin( 115200 );
  Serial.println("setup");

  // Ethernet and OSC utilities **************************
  Ethernet.begin(mac, ip);

  // Hardware status check
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.");
  }
  else if (Ethernet.hardwareStatus() == EthernetW5100) {
    Serial.println("W5100 Ethernet controller detected.");
  }
  else if (Ethernet.hardwareStatus() == EthernetW5200) {
    Serial.println("W5200 Ethernet controller detected.");
  }
  else if (Ethernet.hardwareStatus() == EthernetW5500) {
    Serial.println("W5500 Ethernet controller detected.");
  }

  //Tells you whether the link is active.
  // LinkOFF could indicate the Ethernet cable is unplugged or defective.
  if (Ethernet.linkStatus() == Unknown) {
    Serial.println("Link status unknown. Link status detection is only available with W5200 and W5500.");
  }
  else if (Ethernet.linkStatus() == LinkON) {
    Serial.println("Link status: On");
  }
  else if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Link status: Off");
  }

  while( Ethernet.linkStatus() == LinkOFF ) {
    delay( DELAY );
  }
}

// LOOP ///////////////////////////////////////////////////////////////////
void loop()
{

  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.print("Ethernet link broken!\t");
    Serial.println("please connect the Ethernet cable");
    delay( DELAY );
    return;
  }

  Serial.println("LOOP working as expected!");
  delay( DELAY );
}
```

When I try this code using the "defective" Arduino Ethernet shield the Serial monitor print something like this (note that I'm not doing anything, I'm leaving everything untouched):

    [...]
    14:25:17.906 -> setup
    14:25:18.471 -> W5500 Ethernet controller detected.
    14:25:18.471 -> Link status: On
    [...]
    14:26:41.545 -> LOOP working as expected!
    14:26:42.542 -> LOOP working as expected!
    14:26:43.538 -> LOOP working as expected!
    14:26:44.535 -> Ethernet link broken! please connect the Ethernet cable
    14:26:45.531 -> LOOP working as expected!
    14:26:46.561 -> LOOP working as expected!
    14:26:47.558 -> LOOP working as expected!
    14:26:48.555 -> LOOP working as expected!
    14:26:49.552 -> Ethernet link broken! please connect the Ethernet cable
    14:26:50.549 -> LOOP working as expected!
    14:26:51.546 -> LOOP working as expected!
    14:26:52.543 -> LOOP working as expected!
    14:26:53.540 -> LOOP working as expected!
    14:26:54.570 -> LOOP working as expected!
    14:26:55.567 -> Ethernet link broken! please connect the Ethernet cable
    14:26:56.564 -> LOOP working as expected!
    14:26:57.561 -> LOOP working as expected!
    14:26:58.557 -> LOOP working as expected!
    14:26:59.553 -> Ethernet link broken! please connect the Ethernet cable
    14:27:00.550 -> Ethernet link broken! please connect the Ethernet cable
    14:27:01.546 -> LOOP working as expected!
    14:27:02.576 -> Ethernet link broken! please connect the Ethernet cable
    14:27:03.572 -> LOOP working as expected!
    14:27:04.569 -> LOOP working as expected!
    14:27:05.566 -> LOOP working as expected!
    14:27:06.563 -> LOOP working as expected!
    14:27:07.560 -> LOOP working as expected!
    14:27:08.557 -> LOOP working as expected!
    14:27:09.587 -> LOOP working as expected!
    14:27:10.583 -> Ethernet link broken! please connect the Ethernet cable
    14:27:11.580 -> LOOP working as expected!
    14:27:12.577 -> LOOP working as expected!
    [...]

In the meantime, the ping stops working and will not work again until I reboot the Arduino:

    [...]
    64 bytes from 10.3.3.210: icmp_seq=301 ttl=128 time=0.185 ms
    64 bytes from 10.3.3.210: icmp_seq=302 ttl=128 time=0.171 ms
    64 bytes from 10.3.3.210: icmp_seq=303 ttl=128 time=0.184 ms
    64 bytes from 10.3.3.210: icmp_seq=304 ttl=128 time=0.229 ms
    64 bytes from 10.3.3.210: icmp_seq=305 ttl=128 time=0.206 ms
    64 bytes from 10.3.3.210: icmp_seq=306 ttl=128 time=0.278 ms
    64 bytes from 10.3.3.210: icmp_seq=307 ttl=128 time=0.143 ms
    64 bytes from 10.3.3.210: icmp_seq=308 ttl=128 time=0.229 ms
    64 bytes from 10.3.3.210: icmp_seq=309 ttl=128 time=0.198 ms
    From 10.3.3.165 icmp_seq=335 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=336 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=339 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=342 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=343 Destination Host Unreachable
    From 10.3.3.165 icmp_seq=344 Destination Host Unreachable
    [...]

As you see the "Link" seems to be on and than off repeatedly. I don't know why from the moment. I'm not modifying anything on my network setup (the LAN cable or anything like that).

I don't know why the ping stops working and will not work again even if the Serial monitor is telling the LINK is ON.

Let me know as soon as you can and thank you so much for your help and support.

bests

na

PS: I've posted a similar question on the Arduino forum but I had no way of understanding what kind of problem is this --> [link][3]

  [1]: https://store.arduino.cc/usa/arduino-ethernet-shield-2
  [2]: https://github.com/CNMAT/OSC
  [3]: https://forum.arduino.cc/index.php?topic=725989.msg4882309#msg4882309

**edit 11/02/2021**

I've written a new code sketch to always print the status of the link. Here it is.

```c++
    /* NET stuff ********************************************/
    #include <SPI.h>
    #include <Ethernet.h>
    #include <EthernetUdp.h>
    EthernetUDP Udp;

    IPAddress ip(10, 3, 3, 210); // the Arduino's IP
    byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x83, 0xD5 };

    #define DELAY 1000

    // SETUP //////////////////////////////////////////////////////////////////
    void setup() {

      Serial.begin( 115200 );
      Serial.println("setup");

      // Ethernet and OSC utilities **************************
      Ethernet.begin(mac, ip);

      // Hardware status check
      if (Ethernet.hardwareStatus() == EthernetNoHardware) {
        Serial.println("Ethernet shield was not found.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5100) {
        Serial.println("W5100 Ethernet controller detected.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5200) {
        Serial.println("W5200 Ethernet controller detected.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5500) {
        Serial.println("W5500 Ethernet controller detected.");
      }

      //Tells you whether the link is active.
      // LinkOFF could indicate the Ethernet cable is unplugged or defective.
      if (Ethernet.linkStatus() == Unknown) {
        Serial.println("Link status unknown. Link status detection is only available with W5200 and W5500.");
      }
      else if (Ethernet.linkStatus() == LinkON) {
        Serial.println("Link status: On");
      }
      else if (Ethernet.linkStatus() == LinkOFF) {
        Serial.println("Link status: Off");
      }

      while( Ethernet.linkStatus() == LinkOFF ) {
        Serial.println("\tplease connect the Ethernet cable");
        delay( DELAY );
      }
    }

    // LOOP ///////////////////////////////////////////////////////////////////
    void loop()
    {

      int LINK_STATUS = Ethernet.linkStatus();

      if ( LINK_STATUS == LinkOFF) {
        Serial.print("Ethernet link broken!\t");
        Serial.println("please connect the Ethernet cable");
        delay( DELAY );
        return;
      } else if( LINK_STATUS == Unknown ) {
        Serial.println("LINK_STATUS: Unknown");
        delay( DELAY );
        return;
      } else if( LINK_STATUS == LinkON ) {
        Serial.println("LOOP working as expected! (LINK_STATUS: ON)");
      }

      delay( DELAY );
    }
```

After a while, it gave me this output on the serial monitor (at the same time ping said "Destination Host Unreachable"):

    [...]
    10:57:21.207 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:22.203 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:23.200 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:24.197 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:25.195 -> Ethernet link broken! please connect the Ethernet cable
    10:57:26.192 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:27.188 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:28.186 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:29.216 -> Ethernet link broken! please connect the Ethernet cable
    10:57:30.213 -> Ethernet link broken! please connect the Ethernet cable
    10:57:31.210 -> Ethernet link broken! please connect the Ethernet cable
    10:57:32.207 -> Ethernet link broken! please connect the Ethernet cable
    10:57:33.204 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:34.202 -> Ethernet link broken! please connect the Ethernet cable
    10:57:35.198 -> Ethernet link broken! please connect the Ethernet cable
    10:57:36.194 -> Ethernet link broken! please connect the Ethernet cable
    10:57:37.224 -> Ethernet link broken! please connect the Ethernet cable
    10:57:38.221 -> Ethernet link broken! please connect the Ethernet cable
    10:57:39.219 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:40.216 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:41.213 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:42.210 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:43.207 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:44.236 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:45.232 -> Ethernet link broken! please connect the Ethernet cable
    10:57:46.228 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:47.225 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:48.222 -> LOOP working as expected! (LINK_STATUS: ON)
    10:57:49.218 -> Ethernet link broken! please connect the Ethernet cable
    10:57:50.216 -> Ethernet link broken! please connect the Ethernet cable
    10:57:51.212 -> Ethernet link broken! please connect the Ethernet cable
    10:57:52.242 -> Ethernet link broken! please connect the Ethernet cable
    10:57:53.239 -> Ethernet link broken! please connect the Ethernet cable
    10:57:54.235 -> Ethernet link broken! please connect the Ethernet cable
    10:57:55.231 -> Ethernet link broken! please connect the Ethernet cable
    10:57:56.227 -> Ethernet link broken! please connect the Ethernet cable
    [...]

Adding some new elements here.
I've also noticed that, sometimes, even if the LINK status is ON, the ping is not working. It is almost clear to me that the two things are completely uncorrelated.

I've made some experiments in changing also the MAC address (setting a MAC address which is different from the one I see on the label on the shield). The "*wrong*" MAC address seems not to be cause of problems.
Can it be that a MAC address misconfiguration on the Arduino firmware can make the things work the wrong way?

I've also made many attempts in disconnetting and re-connecting the ethernet cable to the shield without powering the Arduino off and I've experinced a series of different behaviours.

**1A)** disconnecting the ethernet cable:
* Serial monitor prints: "Ethernet link broken! please connect the Ethernet cable"
* ping stops;

**1B)** re-connecting the ethernet cable:
* on the Serial monitor LinkOn and LinkOff alternate between themselves, then, "LOOP working as expected! (LINK_STATUS: ON)" becomes stable;
* ping still prints "Destination Host Unreachable";

**2)** reset of the Arduino Board (not the reset on the shield)
* Serial monitor: "LOOP working as expected! (LINK_STATUS: ON)"
* ping works again;

**3A)** Trying to repeat the same procedure as before (1A). Disconnecting the Ethernet cable:
* Serial monitor prints "Ethernet link broken! please connect the Ethernet cable";
* ping stops;

**3B)** re-connecting the ethernet cable:
* on the Serial monitor LinkOn and LinkOff alternate between themselves, then, "LOOP working as expected! (LINK_STATUS: ON)" becomes stable;
* ping works again (which is a different behaviour from before!!!);

This problem is really difficult for me to debug. It seems we have a lot of variables to take into consideration here, which are not under my control: if I repeat the same procedure again and again, behaviour changes.

I'm not sure if it depends on the board, on the *W5500* chip, maybe on other things happening on the net. Is it possible?

I don't know how to write a code to be capable of detecting these malfunctions.

Thank you so much for your help.
na

body:
I've had similar issues with the Ethernet V2 shield, which were probably caused by the (unused) SD Card interface on the Ethernet V2 shield interfering with Ethernet functionality (both use the SPI bus).

From what I could see in the [Ethernet Shield2 schematics](https://www.arduino.cc/en/uploads/Main/arduino-Ethernet-Shield2-V2-sch.pdf), there is no pull-up on the signal controlling the SD card Chip Select (D4/SD_CS), which means an unitialized I/O pin on the Arduino side could potentially cause random noise on the SD CS input.

My solution was to explicitly disable the SD Card interface CS, by setting pin 4 to high at the start of my `setup()` code.

I used the following code:

    #define SDSelect  4

    ... Other initialization code

    setup() {
        pinMode (SDSelect, OUTPUT);
        digitalWrite (SDSelect, HIGH);

        ... Code continues ...

This solved my issues with random crashing. I realize that I can't remember if there was an SD card present in the slot at the time.