message:
why is my arduino stuck on uploading?

my arduino for the playground adafruit express gets stuck uploading, and is saying that it is not recognizing the ports. <Arduino: 1.8.16 (Windows Store 1.8.51.0) (Windows 10), Board: "Adafruit Circuit Playground"

    Sketch uses 6360 bytes (22%) of program storage space. Maximum is 28672 bytes.

    Global variables use 351 bytes of dynamic memory.

    Forcing reset using 1200bps open/close on port COM13

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    PORTS {COM13, } / {COM13, } => {}

    Uploading using selected port: COM13

    C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.51.0_x86__mdqgnx93n4wtt\hardware\tools\avr/bin/avrdude -CC:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.51.0_x86__mdqgnx93n4wtt\hardware\tools\avr/etc/avrdude.conf -v -patmega32u4 -cavr109 -PCOM13 -b57600 -D -Uflash:w:C:\Users\Owner\AppData\Local\Temp\arduino_build_570140/sorting_numbers_test.ino.hex:i

    avrdude: Version 6.3-20190619

             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

             Copyright (c) 2007-2014 Joerg Wunsch

             System wide configuration file is "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.51.0_x86__mdqgnx93n4wtt\hardware\tools\avr/etc/avrdude.conf"

             Using Port                    : COM13

             Using Programmer              : avr109

             Overriding Baud Rate          : 57600

             AVR Part                      : ATmega32U4

             Chip Erase delay              : 9000 us

             PAGEL                         : PD7

             BS2                           : PA0

             RESET disposition             : dedicated

             RETRY pulse                   : SCK

             serial program mode           : yes

             parallel program mode         : yes

             Timeout                       : 200

             StabDelay                     : 100

             CmdexeDelay                   : 25

             SyncLoops                     : 32

             ByteDelay                     : 0

             PollIndex                     : 3

             PollValue                     : 0x53

             Memory Detail                 :

                                      Block Poll               Page                       Polled

               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack

               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------

               eeprom        65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00

               flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00

               lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00

               hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00

               efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00

               lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00

               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

             Programmer Type : butterfly

             Description     : Atmel AppNote AVR109 Boot Loader

    Connecting to programmer: .avrdude: butterfly_recv(): programmer is not responding

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: butterfly_recv(): programmer is not responding

    Found programmer: Id = "F"; type = @

        Software Version = �.v; Hardware Version = �.

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: error: buffered memory access not supported. Maybe it isn't

    a butterfly/AVR109 but a AVR910 device?

    avrdude: initialization failed, rc=-1

             Double check connections and try again, or use -F to override

             this check.

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: error: programmer did not respond to command: leave prog mode

    avrdude: butterfly_recv(): programmer is not responding

    avrdude: error: programmer did not respond to command: exit bootloader

    avrdude done.  Thank you.

    the selected serial port

     does not exist or your board is not connected

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.>

body:
* > ...for the playground adafruit express gets stuck...

* `avrdude: initialization failed, rc=-1`

You appear to have selected the "Classic" rather than "Express" version of the board, [which are different things][1].

* The classic you have selected uses an AVR ATMega32u4 like you'd find in the Arduino Micro/Leonardo.

* The "Express" uses an ATSAMD21 chip like an Arduino Zero.

They don't use the same family of microcontroller, bootloader, bootloader protocol, or upload tool. The boards manager package that [supports the Class board][2] is completely different from the [one that supports the Express board][3]; they are divided support along the lines of the AVR (8-bit) vs SAMD (32-bit arm) chips.

In short, choose the "Express" version of the board after you've gone through [setup process for the Express][4].  If you have problems uploading to an Express with the Express board selected, you're likely to see errors [that mention `bossac`][5], but you're not going to see anything about `avrdude`.

  [1]: https://learn.adafruit.com/adafruit-circuit-playground-express/classic-vs-express
  [2]: https://github.com/adafruit/Adafruit_Arduino_Boards/
  [3]: https://github.com/adafruit/ArduinoCore-samd
  [4]: https://learn.adafruit.com/adafruit-circuit-playground-express/set-up-arduino-ide
  [5]: https://github.com/adafruit/ArduinoCore-samd/blob/1.7.5/boards.txt#L201


sender: user

message:
Arduino Uno freezes for unknown reason during code execution

I am struggeling with a behaviour of my Arduino I do not fully understand.

**Long story short:**

When starting the communication over I2C the Arduino freezes. In my opinion during the "Wire.write()" command.

**Long story and background:**

I want to connect my Arduino Uno to an Arduino MKR Wifi 1010 via I2C. I implemented the code for the communication step by step, so I started with the code below.

**Code for the Master Arduino Uno:**

```
#include <Wire.h>
#include <Arduino.h>

#define SLAVE_ADRESS                            2

void Send_Data(int receiver, int data)
{
    Wire.beginTransmission(receiver);
    Wire.write(data);
    Wire.endTransmission();
    Serial.println(F("Data sent"));
}

void setup() {
  Serial.begin(38400);
  while (!Serial) {;} /* Wait for serial interface to be connected and ready for use. */
  Serial.setTimeout(2000);
  Serial.println(F("Serial Connection ready"));
  Wire.begin(); // join i2c bus (address optional for master)
}

void loop() {
  static int LedStatus = 0;
  if (LedStatus == 0)
  {
      LedStatus = 1;
  }
  else
  {
      LedStatus = 0;
  }
  Serial.print(F("Master LED status: "));
  Serial.println(LedStatus);
  Send_Data(SLAVE_ADRESS,LedStatus);
  delay(500);
}n
```

**Code for the Slave Arduino MKR Wifi 1010:**
```

#include <Wire.h>
#include <Arduino.h>

#define NODE_ADDRESS 2

int led = 0;

void setup()
{
  Serial.begin(38400);
  while (!Serial)
  {
        ; /* Wait for serial interface to be connected and ready for use. */
  }
  Serial.setTimeout(1000);

  Wire.begin(NODE_ADDRESS);
  Wire.onReceive(receiveEvent);
}

void receiveEvent(int bytes)
{
  led = Wire.read();
  Serial.println("Data reveived!");
  Serial.print("Slave Value led: ");
  Serial.println(led);

}

void loop()
{

}
```

This piece of code works fine as expected.
So I implemented the very same functionality for the master into my projekt.
```
/****************************************************************************/
/*-------------------------------Description--------------------------------*/
/****************************************************************************/

/*
Used board: Arduino Uno

>>> Pin usage overview <<<
0:
1:
2: waterlevel tank sensor low (black sensor wires)
3: waterlevel tank sensor high (red sensor wires)
4: waterlevel reservoir sensor low (not used yet)
5: waterlevel reservoir sensor high (not used yet)
6: pump level tank
7: pump level reservoir
8: water temperature sensor
9: water temperature sensor
10:
11:
12:
13:
A0: EC sensor
A1: pH sensor
A2:
A3:
A4:
A5:
/*

/****************************************************************************/
/*---------------------------------Includes---------------------------------*/
/****************************************************************************/

#include <Arduino.h>
#include <RTClib.h>
#include <TimerOne.h>
#include <Wire.h>
#include "WaterCondition.h"
#include "WaterFlow.h"
#include "Serial.h"

/****************************************************************************/
/*----------------------------------Macros----------------------------------*/
/****************************************************************************/

#define TIMER_INTERVAL                          2000000 // 5sec (timer in microsec)

#define RTC_INIT_TIME_SECOND                    0
#define RTC_INIT_TIME_MINUTE                    0
#define RTC_INIT_TIME_HOUR                      0
#define RTC_INIT_TIME_DAY                       0
#define RTC_INIT_TIME_MONTH                     0
#define RTC_INIT_TIME_YEAR                      0

#define OPERATING_MODE_AUTO                     0
#define OPERATING_MODE_TEST_TEMP_SENSOR         1
#define OPERATING_MODE_TEST_EC_SENSOR           2
#define OPERATING_MODE_TEST_PH_SENSOR           3
#define OPERATING_MODE_TEST_RTC                 4
#define OPERATING_MODE_TEST_WATERLEVEL          5
#define OPERATING_MODE_TEST_COMMUNICATION       6

#define SLAVE_ADRESS                            2 // adress of the slave for communication

/****************************************************************************/
/*-----------------------------Global Variables-----------------------------*/
/****************************************************************************/

/*
OPERATING_MODE 0: Automatic
OPERATING_MODE 1: Testing / Calibration
*/
uint8_t OperatingMode = 0;

/* Used for Serial.h to read the input from serial connection */
extern char StringBuffer[STRING_BUFFER_SIZE];
extern float WaterConPhVolt, WaterConEcVolt, WaterConPhVal, WaterConEcVal, WaterConTempVal;

/****************************************************************************/
/*------------------------------Initialization------------------------------*/
/****************************************************************************/

RTC_DS3231 rtc;
DateTime now;

int freeRam()
{
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

/* standard operations */
void ISR_Task(void)
{
    if (OperatingMode == OPERATING_MODE_AUTO) // Automatic
    {
        Serial.println(F("Running in automatic mode"));

        uint8_t min;
        min = now.second(),DEC;
        if ((min == PUMP_TANK_ON_INTERVALL_1) || (min == PUMP_TANK_ON_INTERVALL_2))
        {
            //Serial.println(F("Test: RTC min = 0 or 30");
            //Activate pump
            //Function tbd
        }
        else if ((min == PUMP_TANK_OFF_INTERVALL_1) || (min == PUMP_TANK_OFF_INTERVALL_2))
        {
            //Serial.println(F("Test: RTC min = 20 or 50");
            //Deactivate pump
            //Function tbd
        }
        WaterConTempVal = WaterCon_Sensor_TEMP(0);
        WaterConEcVal = WaterCon_Sensor_EC();
        WaterConPhVal = WaterCon_Sensor_PH();
        if (Waterflow_Tank() == 99)
        {
            // tbd
        }

    }
    else // Testing
    {
        /* >>> Test the temperature sensor <<< */
        if (OperatingMode == OPERATING_MODE_TEST_TEMP_SENSOR)
        {
            Serial.print(F("Water temperature filtered: "));
            Serial.println(WaterCon_Sensor_TEMP(0));
        }

        /* >>> Test the PH sensor <<< */
        else if (OperatingMode == OPERATING_MODE_TEST_PH_SENSOR)
        {
            float test_ph = 0;
            test_ph = WaterCon_Analog_Read(PH_PIN, VOLTAGE_PIN, RESOLUTION_SENSOR_PH);
            Serial.print(F("PH-Sensor-Value raw from 0 - 5000mV: "));
            Serial.println(test_ph);
            Serial.print(F("PH-Value from 0 - 14: "));
            Serial.println(WaterCon_Sensor_PH());
        }

        /* >>> Test the PH sensor <<< */
        else if (OperatingMode == OPERATING_MODE_TEST_EC_SENSOR)
        {
            float test_ec = 0;
            test_ec = WaterCon_Analog_Read(EC_PIN, VOLTAGE_PIN, RESOLUTION_SENSOR_EC);
            Serial.print(F("EC-Sensor-Value raw from 0 - 5000mV: "));
            Serial.println(test_ec);
            Serial.print(F("EC-Value from 0 - 2000uS: "));
            Serial.println(WaterCon_Sensor_EC());
        }

        /* >>> Test the RTC clock <<< */
        else if (OperatingMode == OPERATING_MODE_TEST_RTC)
        {
            Serial.print(F("\nRTC-Time: "));
            Serial.println(now.second(),DEC);
        }

        /* >>> Test the waterlevel sensors <<< */
        else if (OperatingMode == OPERATING_MODE_TEST_WATERLEVEL)
        {
            int WaterLvlSensorLow = 0;
            int WaterLvlSensorHigh = 0;
            WaterLvlSensorLow = digitalRead(TANK_LVL_LOW_PIN);
            WaterLvlSensorHigh = digitalRead(TANK_LVL_HIGH_PIN);

            Serial.print(F("Waterlevel Sensor Low: "));
            Serial.println(WaterLvlSensorLow);
            Serial.print(F("Waterlevel Sensor High: "));
            Serial.println(WaterLvlSensorHigh);
        }

        /* >>> Test the communication over I2C <<< */
        else if (OperatingMode == OPERATING_MODE_TEST_COMMUNICATION)
        {
            static int LedStatus = 0;
            if (LedStatus == 0)
            {
                LedStatus = 1;
            }
            else
            {
                LedStatus = 0;
            }
            Serial.print(F("Master LED status: "));
            Serial.println(LedStatus);
            Send_Data(SLAVE_ADRESS,LedStatus);
        }
    }
}

void Send_Data(int receiver, int data)
{
    Wire.beginTransmission(receiver);
    Wire.write(data);
    Wire.endTransmission();
    Serial.println(F("Data sent"));
}

/****************************************************************************/
/*-------------------------Function Implementations-------------------------*/
/****************************************************************************/

void setup() {
    Serial.begin(38400);
    while (!Serial) {;} /* Wait for serial interface to be connected and ready for use. */
    Serial.setTimeout(2000);
    Serial.println(F("Serial Connection ready"));

    /* Initialize sensors */
    Serial.println(F("Setup Sensors"));
    WaterCon_Sensor_Init();
    Waterflow_Sensor_Init();

    /* Initialize RTC */
    Serial.println(F("Setup RTC"));
    rtc.begin();
    Serial.println(F("Test"));

    /* Initialize timers */
    Serial.println(F("Setup Timers"));
    Timer1.initialize(TIMER_INTERVAL);
    Timer1.attachInterrupt(ISR_Task);
    Serial.println(F("Setting the time for the RTC..."));
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

    /* Initialize I2C Master-Slave */
    Wire.begin();
}

void loop()
{
    now = rtc.now();

    delay(200);
    Serial_Read(1);
    /* Change operating mode to automatic */
    if (strcmp("opauto",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to automatic"));
        OperatingMode = 0;
    }
    /* Change operating mode to testing */
    else if (strcmp("optest1",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to Testing: temperature sensor"));
        OperatingMode = 1;
    }
    else if (strcmp("optest2",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to Testing: EC sensor"));
        OperatingMode = 2;
    }
    else if (strcmp("optest3",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to Testing: pH sensor"));
        OperatingMode = 3;
    }
    else if (strcmp("optest4",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to Testing: RTC clock"));
        OperatingMode = 4;
    }
    else if (strcmp("optest5",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to Testing: Waterlevel Sensors"));
        OperatingMode = 5;
    }
    else if (strcmp("optest6",StringBuffer) == 0)
    {
        Serial.println(F("Operating Mode changed to Testing: Communication via I2C Master-Slave"));
        OperatingMode = 6;
    }
}
```
Some explanation for you to understand what I am trying to do:
Above you can see the code from the Main.ino file for a hydroponic project. I wanted to realize different operating modes for automatic and testing. So if I encounter a fault, I want to be able to plug the laptop on the USB port and start to read out some information over the serial port. Later this should be accomplished over the air but for the beginning this should be fine.
To achieve this, I put string compare into the loop to notice if the user did some input and respond to it.
I tested that functionality a lot and it worked fine. I am able to jump from any operating mode to another.

There is an external real time clock running for using interrupts and run code at specific times.
During this interrupt I check what operating mode is active and run the respective code. With the string compare I mentioned above I can jumo into the respective code with the next interrupt.

**ISSUE:**
Now I can describe the actual issue. Everytime I enter the "operating mode 6" to test the I2C connection, the Arduino freezes. As you can see I used the very same code inside the "else if" as tested before.
This is the relevant part of the code:
```
        /* >>> Test the communication over I2C <<< */
        else if (OperatingMode == OPERATING_MODE_TEST_COMMUNICATION)
        {
            static int LedStatus = 0;
            if (LedStatus == 0)
            {
                LedStatus = 1;
            }
            else
            {
                LedStatus = 0;
            }
            Serial.print(F("Master LED status: "));
            Serial.println(LedStatus);
            Send_Data(SLAVE_ADRESS,LedStatus);
        }
    }
}

void Send_Data(int receiver, int data)
{
    Wire.beginTransmission(receiver);
    Wire.write(data);
    Wire.endTransmission();
    Serial.println(F("Data sent"));
}
```
In the following picture it looks like the Board freezes during the serial communication when it prints out "Master LED status: ". I testet this by commenting out the serial.print commands and insert a print command between Wire.begin and Wire.write in the code.
[![enter image description here][1]][1]

I think the main problem is caused by the Wire.write function, but I am not able to debug it other than using serial.print commands. But the printed commands do not correlate with the line of code when the board actually freezes. I think I would need real debugger that stops the processor and gives me the possibility to go through the code step by step.
At first I thought this issue was caused because the SRAM got filled. So I put the Serial.print commands in the flash memory and inserted some lines of code for checking the usage of the SRAM and the Stack. You can see the "freeRam()" function in the code, but I removed them for better readability.

Did anyone have a similar issue or do you know what could cause this issue?

Thanks a lot in advance!

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

sender: assistant

body:
The program most likely hangs at `Wire.endTransmission();`, because that's where the actual I2C communication happens. `Wire.write()` does nothing but placing the data into the internal buffer of the `Wire` library.

**You experience problems because you are calling interrupt-dependent code inside an ISR, where interrupts are deactivated by default.**

The `Wire` library uses the I2C hardware of the Uno. This hardware generated interrupts for the different stages in the communication (for example generating an interrupt so that the library can place the next data byte in the hardware buffer). That means that the `Wire` library will not work if interrupts are turned of for some reason. It will wait forever for an interrupt that will never come.

When entering an ISR (in this case of the Timer1 interrupt) other interrupts are deactivated by default. At the end of the ISR the compiler will again turn on interrupts. Any interrupts which happen during the execution of the current ISR will be executed after it has exited.

With `Wire.endTransmission()` you currently have a function call in your Timer1 ISR, which will wait for its corresponding I2C ISRs to run, which cannot happen inside the Timer1 ISR.

**What to do now:** You need to restructure your code. You shouldn't do that much stuff in an ISR either way. It needs to be as short as possible to not disturb other interrupt based functions. In the ISR just set a simple 1-byte flag variable. Then in `loop()` check this flag variable. If it is set, you can do the stuff, which currently is in your ISR. And then you reset the flag to be ready for the next ISR setting it again. For this to work correctly you need to ditch the `delay()` call in `loop()`. If you want to do timed things, you can use `millis()` like in the `BlinkWithoutDelay` example, that comes with the Arduino IDE. Make sure that nothing can block the `loop()` function for a long period of time (meaning longer than the interval between 2 interrupts or longer than the minimal time resolution, that you want in your system).

---

Note: You thought of the wrong line while debugging, because of your Serial output. But Serial output is only helping to a certain extent with debugging, since it too needs interrupts to work correctly. All the data that gets printed in your ISR will only be send once the ISR exits. `Serial.print()` and its siblings only fill the buffer of the library, while the actual sending is done in the background via ISRs. So the sending stopped when it got stuck at the ISR, but that doesn't mean that this actually was what you printed directly before that line. Even when not having interrupts involved this might not be the case. Just keep that in mind when using Serial prints for debugging.


message:
multiple mpu9250 using tca9548a with esp32

I'm using ESP32 and 1 sensor mpu9250(only for test) with tca9548a, connections are:

TCA <-> ESP

VIN - VCC

GND - GND

SDA - GPIO21

SCL - GPIO22

TCA <-> MPU

SD2 - SDA

SC2 - SCL

VIN - VIN

GND - GND

And my code here:

    #include <SparkFunMPU9250-DMP.h>
    #include <Wire.h>

    #define TCAADDR 0x70
    void tcaselect(uint8_t i) {
      if (i > 7) return;

      Wire.beginTransmission(TCAADDR);
      Wire.write(1 << i);
      Wire.endTransmission();
    }

    MPU9250_DMP imu;

    void setup()
    {
      Serial.begin(115200);
      Wire.begin();
      tcaselect(2);
      if (imu.begin() != INV_SUCCESS)
      {
        while (1)
        {
          Serial.println("Unable to communicate with MPU-9250");
          Serial.println("Check connections, and try again.");
          Serial.println();
          delay(5000);
        }
      }

      imu.dmpBegin(DMP_FEATURE_6X_LP_QUAT | // Enable 6-axis quat
                   DMP_FEATURE_GYRO_CAL, // Use gyro calibration
                  10); // Set DMP FIFO rate to 10 Hz
                  delay(10000);
    }

    void loop()
    {
      tcaselect(2);
        imu.dmpUpdateFifo();
      float q0 = imu.calcQuat(imu.qw);
      float q1 = imu.calcQuat(imu.qx);
      float q2 = imu.calcQuat(imu.qy);
      float q3 = imu.calcQuat(imu.qz);
      Serial.println("Q: " + String(q0, 4) + ", " +
                        String(q1, 4) + ", " + String(q2, 4) +
                        ", " + String(q3, 4));delay(10);
    }

I need to get quaternions from the MPU sensor but I'm only getting zeros on the output.

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

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

Library that I used: https://github.com/rupin/SparkFun_MPU-9250-DMP_Arduino_Library

What could be wrong, my connection or library?

body:
The solution is that I just removed the tca9548a from the circuit. Then I connected each AD0 pin to the corresponding GPIO ESP32 pins to turn on the sensor, I send a low signal to it, and a high signal to all the others. Thus, the library only works with a sensor whose address is 0x68.

There is example function from my sketch:

    #include <SparkFunMPU9250-DMP.h>

    /*INIT SENSORS*/
    MPU9250_DMP imu;
    MPU9250_DMP imu1;
    const int sensor1 = 18;
    const int sensor2 = 19;

    String IMU_1Update(){
      String res;
        digitalWrite(sensor1, LOW); // 1st sensor enable - 0x68
        digitalWrite(sensor2, HIGH); // 2nd sensor disable - 0x69
      if ( imu1.fifoAvailable() ){
        if ( imu1.dmpUpdateFifo() == INV_SUCCESS){
          float q0 = imu1.calcQuat(imu1.qw);
          float q1 = imu1.calcQuat(imu1.qx);
          float q2 = imu1.calcQuat(imu1.qy);
          float q3 = imu1.calcQuat(imu1.qz);
          Serial.print("G1|");
          Serial.print(q0);
          Serial.print("|");
          Serial.print(q1);
          Serial.print("|");
          Serial.print(q2);
          Serial.print("|");
          Serial.print(q3);
          Serial.println("|");
        }
      }
      return res;
    }


message:
Why does the send pin influence the receive pin with Arduino Capacitive Sensing Library

I'm trying to figure out how the Arduino Capacitive Sensing Library https://playground.arduino.cc/Main/CapacitiveSensor/ works. It says:

> When the send pin changes state, it will eventually change the state of the receive pin.

However, when I look at the following schematic, I don't understand why this is the case. It seems like the send pin is set to OUTPUT and HIGH and the receive pin to INPUT with deactivated pull-up. I think it's okay to ignore the capacitance at first, yes? Doesn't all the voltage drop over the resistor R and the receive pin will just be floating and showing LOW or HIGH randomly?

[![schematic][1]][1]

Source: https://playground.arduino.cc/Main/CapacitiveSensor/

  [1]: https://i.stack.imgur.com/92KIv.gif

body:
If we ignore the capacitance of the input pin, then it would instantly follow the voltage of the send pin. A voltage drop over the resistor only happens if a current is flowing though it, which cannot happen without any capacitance the receive side. Without current a resistor is just a wire.

A floating pin doesn't directly have its state randomly changes between LOW and HIGH. That can only be the result as the voltage on that pin is changes by the noise. We need the noise to not be directly in the logic voltage range, so that the state of the digital input pin is not totally dictated by noise. That often the case. Also the additional capacitance added by the sensing foil helps with filtering the noise.

The actual measurement works as follows: We set the send pin to a known state and wait a bit (to fully load or unload the capacitance on the pin). Then we change the send pin to the other state and count the time until we see that change on the receive pin. That is when the capacitance of the pin is loaded. Then we are doing that procedure many times, averaging the measured time. What the receive pin does outside of the measurements is not important. During the meausrement its state is mainly dictated by us setting the send pin. Though the library might use some optimization to get a better reading. You could read the libraries code to learn more about that.


message:
Capacitive touch on Adafruit Trinket M0 goes unstable when USB cable from laptop is disconnected

Note that to get to this point, I used much of the helpful information from the Post
*How to use capactive touch on Adafruit board in Arduino mode?*

I am using a Trinket M0 with the Arduino IDE with the Adafruit_FreeTouch.h library.
Also used the example code found here

https://github.com/adafruit/Adafruit_FreeTouch/blob/master/examples/freetouch/freetouch.ino

I modified the code to use the A0 input as a touch sensor with a wire and aluminum foil.
Using a FET on the digital output A2 to turn a fan on or off when the foil is touched.
I am using a small 12VDC wall transformer (1.25A) and then a DC-DC converter to output 5vdc for the Trinket on the BAT in.  The 12Vdc also supplies power to the small computer fan ( uses about 200ma)

The circuit and code work great when the USB cable from my laptop is connected to the Trinket.
**BUT, when I disconnect the USB cable from the Trinket** and touch the sensor, everything goes unstable.  Fan and built-in led cycle on/off randomly at 0.5sec to 2sec intervals.

I've tried all different parameters for the library including the series resistor, sampling rate and frequency modes. I've checked grounds multiple times and this one is really stumping me.
I suspected fan noise early on so the most interesting experiment I've tried so far IMHO is to remove the 12vdc to the fan but keep it supplying the DC-DC converter for the 5v to the trinket-But, the onboard led has the same instability as when fan is connected.
Lastly, I used an Arduino Uno to develop the code and the circuit earlier and it worked fine without USB cable connected.
I feel so close.
Any suggestions or insights much appreciated.

**Here is my code**

    / touch - Capacitive touch demo using FreeTouch. Trinket M0 version.
    // Note: the pin silkscreened 1 is Analog Pin 0.

    #include "Adafruit_FreeTouch.h"

    Adafruit_FreeTouch qt_1 = Adafruit_FreeTouch(A0, OVERSAMPLE_4, RESISTOR_0, FREQ_MODE_NONE);
    int led = 13; // blink 'digital' pin 1 - AKA the built in red LED
    int FAN = 2;  //

    void setup() {
    // initialize the digital pin as an output.
      pinMode(led, OUTPUT);
      pinMode(FAN, OUTPUT);
      digitalWrite(led, LOW);
      digitalWrite(FAN, LOW);
      delay(50);
      // Initialize A0 as a touch sensor
      if (! qt_1.begin())
        //Serial.println("Failed to begin qt on pin A0");
        digitalWrite(led, HIGH);    // Turn on the led
    }
    void loop()
    {
      int counter;
      int result = 0;
      counter = millis();
      result = qt_1.measure();
      if (result > 950) {
        digitalWrite(FAN, HIGH);    // Turn on the FAN
        digitalWrite(led, HIGH);    // Turn on the led
      }
      else {
          digitalWrite(FAN, LOW);    // Turn off the FAN
          digitalWrite(led, LOW);    // Turn off the led
      }
      delay(50);
    }

Here is schematic

[![schematic][1]][1]

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

---

Not sure if I'm doing this right by posting an answer?

I didn’t expect this to be as complex!  Unfortunately adding the suggestion to add the capacitors did not change anything.
But the answer makes sense to me because when I think of why it worked so well on my Arduino Uno development circuit, it could have been because I was using the Capacitive Sense library which utilized two pins that to my understanding measured a RC type of decay to achieve the touch sensing.

Too bad that the Trinket doesn’t operate the same way.  And my programming skills are not strong enough to come up with a similar design solution as the Arduino Uno RC sensing.
So, I will try the idea in the answer where I implement the “side by side with a gap” touch sensor just for learnings sake.  I’ve seen these touch sensors often as traces on a pcb.

But I should share what my ultimate design goal is.
That is to make a touch sensitive art lamp that has a steel body. The lamps are diodes and diodes strips which will be brightness controlled with a PWM input.  So, there is no need for an AC connection other than for the wall transformer which supplies DC.  The design needs to sense a touch whenever someone touches anywhere on the lamp body so that the SW can simulate a three-way switch.  So, a “side by side” gap doesn’t work in this application.  I was hopeful that the Trinket would work since I had everything working in my Arduino proto.  And I’m really looking for a “small” trinket type board solution to fit in the lamp.  In the past I have been successful achieving this functionality with AC power lamps by using those replacement touch circuit modules for 3-way AC switched bulbs.  But for this I wanted to use LED energy saving light sources with a microcontroller.

I think I will try to research “dedicated or discrete” touch sensing circuits that can give me digital input to the Trinket when a touch is sensed on the lamp body.
Any other suggestions/comments are greatly appreciated.
Cheers

body:
The problem is most likely your power supply coupled with the poor design of the capacitive sensing system.

The capacitive sensing is done by measuring the capacitance between your foil plate and "ground". That "ground" is usually a connection through the USB cable and your computer's power supply through the earth wire of your power cable to the physical ground, so you are then between the two "plates" of the capacitor.  That ground connection is "clean". For a laptop the "ground" is usually just the case of the laptop or metal parts of the internals. This has no, or little, power supply noise.

However when you use a USB power supply you no longer have that "clean" connection. Instead your "ground" is going through the negative lead of the USB into the negative rail of the USB power supply which is then capacitively coupled to the neutral of the mains through a "class Y" capacitor across the transformer (there to remove inductive switching noise). That capacitor handles some quite high voltages and lots of noise, so you get that noise also reflected into your USB "ground", meaning the ground that you are using in your capsense "capacitor" is really quite noisy. Noisy enough to make your readings meaningless. On some laptops you may even notice a change when you plug the charger in compared to running on batteries for this same reason. (It's also why some early aluminium Apple laptops could give you an electric shock if you used them while plugged in...)

If you look at proper capacitive sensing arrangements you will see that the aren't just a bit of metal foil. They are properly arranged traces on a PCB which not only include the "sense" side but also the "ground" side of the capacitor. Your finger then affects the capacitance between these two points, not between a bit of foil and the floor of your room.

You should get a piece of cardboard and glue two pieces of foil side by side on it with a small gap between them. Then connect one of them to the Arduino's ground and the other to your input pin. Then recalibrate your readings to work with the new arrangement. You should find it far more stable and reliable.


message:
String Split Issue

I am getting multiple messages from a GPS device at different frequencies. After getting strings I have to save this data on the SD card. It works well when we have the same frequencies messages but if the frequencies are not same the saved data gets some blank spaces.
I am using the split strings method.

```c++
    CR1A = String1.indexOf(13);  //finds location of first
    String1A = String1.substring(0, CR1A + 2 );   //captures first data String
    CR1B = String1.indexOf(13, CR1A + 2 ); //finds location of second ,
    String1B = String1.substring(CR1A , CR1B + 2 ); //captures second data String
    CR1C = String1.indexOf(13, CR1B + 2 );
    String1C = String1.substring(CR1B , CR1C + 2 );
    CR1D = String1.indexOf(13, CR1C + 2 );
    String1D = String1.substring(CR1C , CR1D + 2 );
    CR1E = String1.indexOf(13, CR1D + 2 );
    String1E = String1.substring(CR1D , CR1E + 2 );
    CR1F = String1.indexOf(13, CR1E + 2 );
    String1F = String1.substring(CR1E , CR1F + 2 );

    strID = (String1A.substring(0, 2));
    if (strID == "$G") {
      File dataFile = SD.open("GPS1.txt", FILE_WRITE);
      // if the file is available, write to it:

      strID = (String1A.substring(0, 5));
      if (strID == "$GPGG") {
        dataFile.print(dt);
        dataFile.print(" ");
        dataFile.print(tm);
        dataFile.print(msec);
        dataFile.print(",");
        dataFile.print(String1A);
        String1A = "";
      }

      strID = (String1D.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1B);
        String1B = "";
      }
      strID = (String1C.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1C);
        String1C = "";
      }
      strID = (String1D.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1D);
        String1D = "";
      }
      strID = (String1E.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1E);
        String1E = "";
      }
      strID = (String1F.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1F);
        String1F = "";
      }
      dataFile.close();
    }
```

---
EDIT:

This is the code now I am using. I have turned off all the commands which extract strings from my available data received at the serial port. I am just using an interrupt timer for it.. and it is working perfectly. But I didn't like this simple method and I don't know it's a good way to get strings like this or not as I am not a good programmer.

```
#include <TimerOne.h>
#define RxTimeOut 5

/*
  ** MEGA MINI **
  ** MOSI - pin 51
  ** MISO - pin 50
  ** CLK - pin 52
  ** CS - pin 53 (for MKRZero SD: SDCARD_SS_PIN)
  ** SDA - pin 20
  ** SCL - pin 21
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include "math.h"
#include <SPI.h>
#include <SD.h>
#include "RTClib.h"
#define DS1307_CTRL_ID 0x68
unsigned long int ticks = 0;
RTC_DS1307 rtc;
bool flag = false;
String GPSmessage = "";
const int chipSelect = 53;
String dataString = "";
//String dataString1 = "";
//String dataString2 = "";
//String dataString3 = "";
bool stringComplete = false;
bool string1Complete = false;
bool string2Complete = false;
bool string3Complete = false;
String strID = "";

unsigned long msec;
const long interval = 500;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

unsigned long CurrentBaudRate = 9600;

unsigned long x = 0;

int Up = 3;
int Dn = 4;
int Mnu = 5;

String String1;
String inputString1 = "";         // a String to hold incoming data
boolean NewDataFlag1 = 0;
unsigned int Serial1TimeOut = 0;

String String2;
String inputString2 = "";         // a String to hold incoming data
boolean NewDataFlag2 = 0;
unsigned int Serial2TimeOut = 0;

String String3;
String inputString3 = "";         // a String to hold incoming data
boolean NewDataFlag3 = 0;
unsigned int Serial3TimeOut = 0;

void timerIsr()
{
  serial1Event();
  serial2Event();
  serial3Event();

  if (Serial1TimeOut > 0)Serial1TimeOut--;
  if (Serial1TimeOut == 0 && NewDataFlag1 == 1)
  {
    String1 = inputString1;
    inputString1 = "";
    NewDataFlag1 = 0;
  }

  if (Serial2TimeOut > 0)Serial2TimeOut--;
  if (Serial2TimeOut == 0 && NewDataFlag2 == 1)
  {
    String2 = inputString2;
    inputString2 = "";
    NewDataFlag2 = 0;
  }

  if (Serial3TimeOut > 0)Serial3TimeOut--;
  if (Serial3TimeOut == 0 && NewDataFlag3 == 1)
  {
    String3 = inputString3;
    inputString3 = "";
    NewDataFlag3 = 0;
  }

}

void setup() {

  Timer1.initialize(5000); // Timer event time
  Timer1.attachInterrupt( timerIsr );

  Serial.println("Sonay di nathli");

  //========================================= SD Card =======================================================//
  //  Serial.println("Initializing SD card...");

  // see if the card is not present:
  if (!SD.begin(chipSelect)) {
    //    Serial.println("Card failed, or not present");
    //     don't do anything more:
    return;
  }
  //  Serial.println("SD card Ready");

  //====================================================== RTC =============================================//
  if (!rtc.begin())
  {
    //    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  if (!rtc.isrunning()) {
    //    Serial.println("RTC is NOT running, let's set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  //================================================ OLED Baudrate selection ====================================================//
  pinMode(Up, INPUT_PULLUP);
  pinMode(Dn, INPUT_PULLUP);
  pinMode(Mnu, INPUT_PULLUP);

  unsigned char bdindx = EEPROM.read(0);
  if (bdindx > 3) bdindx = 0;
  if (bdindx == 0) CurrentBaudRate = 4800;
  if (bdindx == 1) CurrentBaudRate = 9600;
  if (bdindx == 2) CurrentBaudRate = 19200;
  if (bdindx == 3) CurrentBaudRate = 115200;
  delay (500);

  while (!Serial) { }// wait for serial port to connect
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(CurrentBaudRate);
  Serial1.begin(CurrentBaudRate);
  Serial2.begin(CurrentBaudRate);
  Serial3.begin(CurrentBaudRate);
  Serial.println(CurrentBaudRate);
  delay (1000);

  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  display.clearDisplay();
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.display();

}

String String1A, String1B, String1C, String1D, String1E, String1F;
String String2A, String2B, String2C, String2D, String2E, String2F;
String String3A, String3B, String3C, String3D, String3E, String3F;
int CR1A, CR1B, CR1C, CR1D, CR1E, CR1F;
int CR2A, CR2B, CR2C, CR2D, CR2E, CR2F;
int CR3A, CR3B, CR3C, CR3D, CR3E, CR3F;

// ============================================ Showing baud rate on screen (position) ===========================================//

void DrawBaudRate(unsigned long BdRt)
{
  unsigned char Xoffset = 0;
  if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;
  if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;
  if (BdRt >= 100000 ) Xoffset = 25;
  //  display.drawRect(0,0,128,64,SSD1306_WHITE);
  //  display.setTextSize(2);
  //  display.setCursor(15,10);
  //  display.println("Baudrate");
  //  display.setTextSize(2);
  //  display.setCursor(15,10);
  //  display.println(tm);
  //  display.setCursor(Xoffset,37);// 6 digit
  //  display.println(BdRt);
  //  display.display();
  //  delay(10);
}

// ================================================== Selection of Baud Rate ========================================================//
unsigned long SelectBaudRate(unsigned long BdRt)
{
  unsigned char BdRtIndx = 0;
  unsigned int FlashCnt = 0;

  if (BdRt == 4800) BdRtIndx = 0;
  if (BdRt == 9600) BdRtIndx = 1;
  if (BdRt == 19200) BdRtIndx = 2;
  if (BdRt == 115200) BdRtIndx = 3;

  unsigned char Xoffset = 0;
  if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;
  if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;
  if (BdRt >= 100000 ) Xoffset = 25;
  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(15, 10); display.println("Select Baudrate");
  display.setCursor(15, 20); display.println("by Up/Dn Buttons");
  display.setTextSize(2);
  display.setCursor(Xoffset, 37); // 6 digit
  display.println(BdRt);
  display.display();
  delay(10);

  while (digitalRead(Mnu) == 0) delay(10);
  delay(100);

  while (digitalRead(Mnu) == 1)
  {
    delay(10);
    FlashCnt++;

    if (digitalRead(Up) == 0)
    {
      if (BdRtIndx < 3) BdRtIndx++;
    }

    if (digitalRead(Dn) == 0)
    {
      if (BdRtIndx > 0) BdRtIndx--;
    }

    if (BdRtIndx == 0) BdRt = 4800;
    if (BdRtIndx == 1) BdRt = 9600;
    if (BdRtIndx == 2) BdRt = 19200;
    if (BdRtIndx == 3) BdRt = 115200;

    if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;
    if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;
    if (BdRt >= 100000 ) Xoffset = 25;
    display.clearDisplay();
    display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
    display.setTextSize(1);
    display.setCursor(15, 10); display.println("Select Baudrate");
    display.setCursor(15, 20); display.println("by Up/Dn Buttons");
    display.setTextSize(2);
    display.setCursor(Xoffset, 37); // 6 digit
    if (FlashCnt > 1) display.println(BdRt);
    if (FlashCnt > 2) FlashCnt = 0;
    display.display();
    delay(250);

    //while(digitalRead(Up)==0 || digitalRead(Dn)==0) delay(10);
  }
  while (digitalRead(Mnu) == 0) delay(10);

  display.clearDisplay();
  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  display.setTextSize(2);
  display.setCursor(20, 10); display.println("Saving");
  display.setCursor(20, 35); display.println("Changes");
  display.display();
  delay(2000);

  EEPROM.write(0, BdRtIndx);

  return (BdRt);

}

//=================================================== OLED showing time ===============================================//
char Time[]     = "  :  :  ";
byte i, second, minute, hour;

void DS3231_display() {
  // Convert BCD to decimal
  second = (second >> 4) * 10 + (second & 0x0F);
  minute = (minute >> 4) * 10 + (minute & 0x0F);
  hour   = (hour >> 4)   * 10 + (hour & 0x0F);
  // End conversion

  Time[7]     = second % 10 + 48;
  Time[6]     = second / 10 + 48;
  Time[4]     = minute % 10 + 48;
  Time[3]     = minute / 10 + 48;
  Time[1]     = hour   % 10 + 48;
  Time[0]     = hour   / 10 + 48;
  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  draw_text(16, 25, Time, 2);                         // Display the time
}

void blink_parameter() {
  byte j = 1;
  while (j < 10 && digitalRead(Up) && digitalRead(Dn)) {
    j++;
    delay(25);
  }
}

byte edit(byte x_pos, byte y_pos, byte parameter) {
  char text[3];
  sprintf(text, "u", parameter);
  while (!digitalRead(Up));                     // Wait until button B1 released
  while (true) {
    while (!digitalRead(Dn)) {                  // If button B2 is pressed
      display.clearDisplay();
      parameter++;
      if (i == 0 && parameter > 23)                  // If hours > 23 ==> hours = 0
        parameter = 0;
      if (i == 1 && parameter > 59)                  // If minutes > 59 ==> minutes = 0
        parameter = 0;
      sprintf(text, "u", parameter);
      draw_text(x_pos, y_pos, text, 2);
      delay(200);                                    // Wait 200ms
    }
    display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
    draw_text(x_pos, y_pos, "  ", 2);
    blink_parameter();
    draw_text(x_pos, y_pos, text, 2);
    blink_parameter();
    if (!digitalRead(Up)) {                     // If button B1 is pressed
      i++;                                           // Increament 'i' for the next parameter
      //      display.clearDisplay();

      return parameter;                              // Return parameter value and exit
    }
  }
}

void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  display.display();
}

//---------------------------------------------
void loop() {

  // ========================================= Editing time and displaying on OLED ============================================//
  if (!digitalRead(Up)) {                       // If button B1 is pressed
    i = 0;
    while (!digitalRead(Up));                   // Wait for button B1 release

    hour   = edit(16, 25, hour);                     // Edit hours
    minute = edit(52, 25, minute);                   // Edit minutes

    // Convert decimal to BCD
    minute = ((minute / 10) << 4) + (minute % 10);
    hour = ((hour / 10) << 4) + (hour % 10);
    // End conversion

    // Write data to DS3231 RTC
    Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address
    Wire.write(0);                              // Send register address
    Wire.write(0);                              // Reset sesonds and start oscillator
    Wire.write(minute);                         // Write minute
    Wire.write(hour);                           // Write hour
    Wire.endTransmission();                     // Stop transmission and release the I2C bus
    delay(200);                                 // Wait 200ms
  }

  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0);                                // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 7);                    // Request 7 bytes from DS3231 and release I2C bus at end of reading
  second = Wire.read();                         // Read seconds from register 0
  minute = Wire.read();                         // Read minutes from register 1
  hour   = Wire.read();                         // Read hour from register 2
  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0x11);                             // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 2);                    // Request 2 bytes from DS3231 and release I2C bus at end of reading
  DS3231_display();                             // Diaplay time & calendar

  delay(50);                                    // Wait 50ms

  { display.clearDisplay();
    if (digitalRead(Mnu) == 0) CurrentBaudRate = SelectBaudRate(CurrentBaudRate);
    //  DrawBaudRate(CurrentBaudRate);
    delay(10);

    x++;
    if (x > 123456) x = 0;
  }

  // ======================================= Reading Date and Time from RTC =============================================//
  DateTime now = rtc.now();
  char dt[16];
  char tm[16];
  char buffer [16];
  uint8_t thisSec, thisMin, thisHour;
  thisSec = now.second();
  thisMin = now.minute();
  thisHour = now.hour();
  sprintf(dt, "d-d-d", now.year(), now.month(), now.day());
  sprintf(tm, "ddd", now.hour(), now.minute(), now.second());
  sprintf (buffer, "d:d:d", thisHour, thisMin, thisSec);
  msec = millis() % 1000; //TO USE LAST 3 DIGITS OF MILLIS OF ARDUINO

  //SERIAL_PORT_1

//  if (string1Complete)
  { Serial.print (String1);
//    CR1A = String1.indexOf(13);  //finds location of first
//    String1A = String1.substring(0, CR1A + 2 );   //captures first data String
//    CR1B = String1.indexOf(13, CR1A + 2 ); //finds location of second ,
//    String1B = String1.substring(CR1A , CR1B + 2 ); //captures second data String
//    CR1C = String1.indexOf(13, CR1B + 2 );
//    String1C = String1.substring(CR1B , CR1C + 2 );
//    CR1D = String1.indexOf(13, CR1C + 2 );
//    String1D = String1.substring(CR1C , CR1D + 2 );
//    CR1E = String1.indexOf(13, CR1D + 2 );
//    String1E = String1.substring(CR1D , CR1E + 2 );
//    CR1F = String1.indexOf(13, CR1E + 2 );
//    String1F = String1.substring(CR1E , CR1F + 2 );
//
//    strID = (String1A.substring(0, 5));
//    if (strID == "$GPGG") {
//      Serial.println(String1);
//    }
//    strID = (String1B.substring(0, 5));
//    if (strID == "$GPVT") {
//      Serial.println(String1B);
//    }
//    strID = (String1C.substring(0, 5));
//    if (strID == "$GPZD") {
//      Serial.println(String1C);
//    }
//    strID = (String1D.substring(0, 5));
//    if (strID == "$GPGL") {
//      Serial.println(String1D);
//    }
//    strID = (String1E.substring(0, 5));
//    if (strID == "$GPGN") {
//      Serial.println(String1E);
//    }
//    strID = (String1F.substring(0, 5));
//    if (strID == "$GPGR") {
//      Serial.println(String1F);
//    }
//    strID = (String1.substring(0, 2));
//    if (strID == "$") {
      File dataFile = SD.open("GPS1.txt", FILE_WRITE);
      // if the file is available, write to it:

      strID = (String1A.substring(0, 5));
      if (strID == "$GPGG") {
        dataFile.print(dt);
        dataFile.print(" ");
        dataFile.print(tm);
        dataFile.print(msec);
        dataFile.print(",");
        dataFile.print(String1);
        Serial.print (String1);
        String1 = "";
        Serial.print (String1);
        dataFile.close();
      }
//    }
//      strID = (String1D.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1B);
//        String1B = "";
//      }
//      strID = (String1C.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1C);
//        String1C = "";
//      }
//      strID = (String1D.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1D);
//        String1D = "";
//      }
//      strID = (String1E.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1E);
//        String1E = "";
//      }
//      strID = (String1F.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1F);
//        String1F = "";
//      }

//    }
    else {
      File dataFile = SD.open("ES2.txt", FILE_WRITE);

      if (dataFile) {
        dataFile.print(dt);
        dataFile.print(" ");
        dataFile.print(tm);
        dataFile.print(msec);
        dataFile.print(",");
        dataFile.println(String1);
        Serial.print (String1);
//        dataFile.println(String1B);
        String1A = "";
        String1B = "";
        dataFile.close();
      }
    }
//  }
  string1Complete = false;
  }

}

//-----------------------------------------------------------------------------------------------------------------

void serial1Event() {
  while (Serial1.available()) {
    char inChar1 = (char)Serial1.read();
    inputString1 += inChar1;
    Serial1TimeOut = RxTimeOut;
    NewDataFlag1 = 1;

    if (NewDataFlag1 == 1) {
      string1Complete = true;
    }

  }
}
```

body:
I do not know what the “frequencies” have to do with your problem, but I
would bet that you would get more reliable results if you handle one
NMEA sentence at a time, instead of trying to handle six of them at
once, and hoping to get the right ones.

Below is a function that processes one complete sentence at a time. It
records the sentence to the SD file if its type belongs to a list of
“interesting” types you want to monitor:

```c++
// Sentence types that are to be recorded.
const char monitoredTypes[6][4] = {
    "GGA", "VTG", "ZDA", "GLL", "GNS", "GRS"
};

// Process a complete, CRLF-terminated NMEA sentence.
void processSentence(String &sentence) {

    // Sanity check.
    if (sentence.substring(0, 3) != "$GP") {
        Serial.print("WARNING: invalid sentence: ");
        Serial.print(sentence);
        return;
    }

    // Record the sentence if it has an interesting type.
    String type = sentence.substring(3, 6);
    for (int i = 0; i < 6; i++) {
        if (type == monitoredTypes[i]) {
            File dataFile = SD.open("GPS1.txt", FILE_WRITE);
            if (type == "GGA") {  // this type seems to be special
                dataFile.print(dt);
                dataFile.print(" ");
                dataFile.print(tm);
                dataFile.print(msec);
                dataFile.print(",");
            }
            dataFile.print(sentence);
            dataFile.close();
        }
    }
}
```

The way to use it is to buffer the incoming characters until you get a
complete sentence (identified by the final LF), then submit that buffer
to this function:

```c++
String buffer;

void loop() {
    while (Serial.available() > 0) {
        char c = Serial.read();
        buffer += c;

        // On end of sentence, process and clear the buffer.
        if (c == '\n') {
            processSentence(buffer);
            buffer = "";
        }
    }
}
```

Note that it wouldn't take too much work to get rid of the `String`
class and use plain C strings instead. Plain strings are way more memory
friendly.


message:
Arduino Zero not recognised as MIDI device via native USB port

I'm currently trying to get an Arduino Zero to show up as a native USB MIDI device in my DAW (ableton). No matter what I try, I cannot get it to show up as a device in Ableton. I have previously used an arduino DUE for a similar project, but cannot get this to work the same. Is there something I'm missing to get the Zero to show up as a native USB Device?

Below is the code have written. I had assumed that the MIDIUSB library takes care of the arduino being recognised as a USB device.

    #include <MIDIUSB.h>

    const byte CHANNEL = 1;
    const byte OFFSET = 48;

    void setup(){}

    void loop()
    {
        delay(100);
        sendNoteOn(CHANNEL, 50 + OFFSET, 127);
        delay(100);
        sendNoteOff(CHANNEL, 50 + OFFSET, 0);
    }

    void sendNoteOn(byte channel, byte pitch, byte velocity)
    {
      midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOn);
    }

    void sendNoteOff(byte channel, byte pitch, byte velocity)
    {
      midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOff);
    }

body:
After extended trouble shooting and device manager fiddling, It turned out that Windows was auto installing the wrong (or partially wrong) drivers that made the native port not be recognised as a USB device. The device was detected as two different ports in the USB drivers, one of which had an error warning. I could still upload to it via either of the USB ports, just couldn't get it to be recognised as a MIDI device.

The solution was to:

 1.  completely uninstall the drivers from the device manager
 2.  uninstall the SAMD boards from the Arduino IDE
 3.  manually download [the drivers from github][1]
 4.  plug the arduino back in and install everything again as normal using those drivers

It now works like a charm.

  [1]: https://github.com/arduino/ArduinoCore-samd/tree/master/drivers


message:
Which C++ standard does the Arduino language support?

The "Arduino language" (as [they call it](https://www.arduino.cc/reference/en/)) of the Arduino IDE 1 is obviously C++. Which C++ exactly?

I tried to figure it out myself (Arduino IDE 1.8.13 for Arduino Uno), but I can't conclude what C++ standard it supports.

From these tests, it seems to support C++14
* C++ 14 variable templates are supported (`template<typename T> constexpr T pi = T(3.1415926535);`)
* C++ 14 lambda captures are supported (`auto lambda = [value = 1] {return value;};`)

* C++ 14 deprecated is supported (`[[deprecated]]int fdep(){return 5;}`)

But not fully:

* C++ 14 digit separators are not supported (`int j = 2'000;`)

From these tests, it even seems to support some C++17:

* Nested namespace definitions are supported (`namespace X::Y {int func(){ return 1; } }`)

But also not fully:

* UTF-8 characters are not supported (`char x = u8'a';`)

If it partially supports everything, is there an overview like a list or table where I can look it up?

body:
The Arduino "language" is nothing more than a set of C++ functions and classes. It does not mandate any particular C++ standard.

The standard is dictated purely by the compiler that the core you are using happens to support (and is configured to use through command line flags).

Different cores use different compilers. Different versions of the same core use different compilers. Different compilers provide different C++ standard levels.

Most cores use GCC or some variant thereof. That could be anything from GCC 3.x.x through to the most recent release (whatever that is this week).

Currently the AVR core uses GCC 7.3.0 and is configured to use the gnu++11 standard by default (though avr-gcc and the associated libraries lack a full STL implementation). You can of course change that in the configuration files if you want.


message:
What's is the best way to convert std::string to String?

Pardon me, I am a novice programmer. I was trying to use the toInt() function for a std::string but I noticed that toInt() only works for the String class. So, I have an std::string sliderValue and wanted to convert it to the String class so I could use the toInt() function. [Here][1], I found a way that seemed to pacify Intellisense, vMicro, and building. I did:
```
String convertValue = strcpy(new char[sliderValue.length() + 1], sliderValue.c_str());
```
so I could do:
```
ledcWrite(ledChannel, convertValue.toInt()  * (10.24));
```
Is there a better way to do this or am I on point? Also, I'd love to get insight in what I'm doing, if possible. Thanks folks!

P.S. I looked up [this][2] here at arduino stackexchange, and it didn't seem to provide a solution specific to my question.

  [1]: https://www.techiedelight.com/convert-std-string-char-cpp/
  [2]: https://arduino.stackexchange.com/questions/56365/arduino-convert-stdstring-to-string

body:
There is absolutely no need to use `String` (for anything, generally...). Instead you can either (if you have it) use `std::stoi()` or use `strtol()` on the `c_str` of the string.

```c++
ledcWrite(ledChannel, std::stoi(sliderValue)  * (10.24));
```

Or

```c++
ledcWrite(ledChannel, strtol(sliderValue.c_str(), NULL, 10)  * (10.24));
```

The former just converts into the latter anyway.


message:
Driving higher loads with PWM

My [Arduino Pro Micro][1] can source 500mA from 3.3V VCC, when it is USB powered.

The chip itself, is rated for 200mA, though, and its output pins for 20mA recommended, 40mA max.

I am looking to have 3 PWM outputs, though, each doing 120mA. The combined 360mA would be in-spec for VCC, but not for the chip.

Is there a buffer IC that I can use that will switch these loads at that current, and can keep up with a few hundred Hz PWM?

From what I've read, you can switch loads with discrete transistors, but these require extra components like resistors? Are there CMOS chips that will take the PWM signal and output it at 120mA?

I am looking to source the current, not sink it.

The load [in my application][2] are LEDs driven with constant-current drivers that are daisy chained. I just want to PWM the Vled supply so I can dim per channel, of the entire daisy chain.

**UPDATE:** I went with @Majenko's solution of pre-biased [DTB114EK][3]. Although it somewhat works, it seems to struggle to deliver 30mA out, even though it is rated at 500mA?

**UPDATE:** The [DTB113ZC][4] works better. Due to a lower bias resistor, I can get more current through it.

  [1]: https://wiki.keyestudio.com/Ks0249_keyestudio_PRO_MICRO_Development_Board
  [2]: https://electronics.stackexchange.com/questions/589973/tuning-a-constant-current-led-driver-per-channel
  [3]: https://www.mouser.ca/datasheet/2/348/dtb114ekt146-e-1872468.pdf
  [4]: https://fscdn.rohm.com/en/products/databook/datasheet/discrete/transistor/digital/dtb113zct116-e.pdf

body:
Here is a part that will do the job for you, just 4 wires to connect.  Use your favorite search engine or go to your favorite china supplier and use this term: "Low Control High Voltage 12V 24V 36V switch Mosfet Module For Arduino Connect IO MCU PWM Control Motor Speed 3V 5V". You will get many choices several in the dollar range. It is opto isolated so that eliminates the ground connections etc. I have used them several times and they work nicely. [![enter image description here][1]][1]

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


message:
Hardware implementation of trigonometric functions?

Is anybody aware as to whether there are any modern microcontrollers that have hardware implementations of trigonometric functions? According to my understanding, modern CPUs have basic maths functions such as square roots and the trigonometric functions implemented in hardware to increase the speed and/or throughput of these maths functions. Do any widely used microcontrollers you know of have similar hardware implementations?

The reason I am asking this is because I want to know if it is feasible to implement more efficient trigonometric functions for specific use cases. On modern CPUs with the right compiler settings, it is almost always faster to use or derive from the built in trigonometric functions, rather than rolling your own software implementation specific to your problem.

body:
I do not know the answer to your main question, but I will try to answer
the underlying question:

> I want to know if it is feasible to implement more efficient
> trigonometric functions for specific use cases.

There are microcontrollers that do _not_ have hardware implementations
of trig functions, and that is the main point. The AVRs powering many
Arduinos are among them: they don't even have hardware floating point.
The libc provides implementations of the trig functions that are both
quite accurate (about 24 bits of accuracy) and very slow (about
100 µs for a `cos()` on an Uno).

There are also situations where you do not need that level of accuracy.
So yes, custom trig functions that hit the right balance between speed
and accuracy can be helpful on Arduinos. Note that the right balance is
project specific, so there is no one-size-fits-all, and rolling your own
can make sense.

For reference, I once wrote a fixed-point `cos()` accurate to
9.53 × 10<sup>−5</sup> that ran in 6.77 µs on average on
an Uno. I can provide a link if someone is interested. If you can do
better (faster at same accuracy, or more accurate at same speed) I
definitely would love to see that.


message:
NFC hang after RF_ON command

We have developed our board with PN5180 NFC but I cannot make it work properly. After I send RF_ON command I am stuck on STATE_CHANGE_IRQ_STAT while waiting for TX_RFON_IRQ_STAT but the state never changes. In this moment I can see sinus vawes on the oscilloscope. If I ignore it I will be stuck waiting for the RX_STATUS register to reflect the TRANSCEIVE_STATE. If I ignore both, the TX_RFON_IRQ_STAT appears after few SEND_DATA sequences but card cannot be read. Has anyone experience this?

    def init(self):

    # 1. Loads the ISO 15693 protocol into the RF registers
    self._send([LOAD_RF_CONFIG, 0x00, 0x80])

    # 2. Switches the RF field ON.
    self._send([RF_ON, 0x00])

    answer = self.read_irq_status_register()
    while ((TX_RFON_IRQ_STAT & answer) == 0):
      answer = self.read_irq_status_register()
      self.show_status(answer)

    return 1

body: The solution is that PN5180 simply cannot work without BUSY pin connected.


message:
ESP32 BLE service not visible to Node-RED

I've been trying to host a BLE-server on my ESP32 with a custom service. I'm trying to read the service data in NodeRED, but the service IDs and custom characteristics don't show up in NodeRED whenever I import the scan results of my BLE input node in NodeRED.
The device and service both show up fine on Android using NRFtool:

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

However, in NodeRED, the device shows up and connects just fine, but none of the characterestics are displayed at NodeRED's end:

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

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

I'm using NodeRED version 1.2.9 with the [Generic BLE node][4]. And the ESP32 sample i'm using can be found [here][5].

I've also tried the BLE server examples included with the BLEDevice library with similar issues.
In addition to this: I'm not sure if this is just a typo in the node's error message, or if it's a typo in the node itself, but all mentions of the type "topic" are displayed as "tpoic" in NodeRED's debug log. Though i doubt this affects the functionality of the node in any way. Nowhere in my flow is there a mention of the keyword "tpoic".

[![enter image description here][6]][6]

Any suggestions as to how i could make my services show up in NodeRED would be appreciated.
Thank you.

  [1]: https://i.stack.imgur.com/IRkhL.jpg
  [2]: https://i.stack.imgur.com/LFEyV.jpg
  [3]: https://i.stack.imgur.com/nykiY.jpg
  [4]: https://flows.nodered.org/node/node-red-contrib-generic-ble
  [5]: https://github.com/LiveSparks/ESP32_BLE_Examples/blob/master/BLE_potentiometer/BLE_potentiometer.ino
  [6]: https://i.stack.imgur.com/sU76V.jpg

body: Turns out BlueZ on linux no longer supports ESP32 BLE devices. I tried the same code on a bluefruit M0 and it worked just fine.


message:
Serial comm UART1 works on Arduino but makes ESP32 continuously reboot

This comm sketch simply read incoming bytes from the UART 1 where a device is attached.
It works normally on a real Arduino device.
But on ESP32, it makes it continuously reboot with the following messages:

([UPDATE] Note that there is no reboot on ESP32 is I use Serial2 instead of Serial1)

```
9:13:19.676 -> ets Jun  8 2016 00:22:57
19:13:19.676 ->
19:13:19.676 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
19:13:19.676 -> configsip: 0, SPIWP:0xee
19:13:19.676 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
19:13:19.676 -> mode:DIO, clock div:1
19:13:19.676 -> load:0x3fff0018,len:4
19:13:19.676 -> load:0x3fff001c,len:1216
19:13:19.714 -> ho 0 tail 12 room 4
19:13:19.714 -> load:0x40078000,len:10944
19:13:19.714 -> load:0x40080400,len:6388
19:13:19.714 -> entry 0x400806b4
19:13:19.786 -> Yo! from serial UART 18/19
19:13:19.786 -> SbmDi⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮@D@⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
@%cGuru Meditation Error: Core  1 panic'ed (IllegalInstruction). Exception was unhandled.
19:13:19.823 -> Memory dump at 0x400e90f4: ffffffff ffffffff ffffffff
19:13:19.823 -> Core 1 register dump:
19:13:19.823 -> PC      : 0x400e90f8  PS      : 0x00060530  A0      : 0x800d1529  A1      : 0x3ffb1f80
19:13:19.823 -> A2      : 0x3ffbfe88  A3      : 0x3ffbfe6c  A4      : 0x0001c200  A5      : 0x0800001c
19:13:19.823 -> A6      : 0x00004e20  A7      : 0x00000000  A8      : 0x800d0c4f  A9      : 0x3ffb1f60
19:13:19.857 -> A10     : 0x3ffbfe6c  A11     : 0x3f40013b  A12     : 0x0800001c  A13     : 0x00000009
19:13:19.857 -> A14     : 0x00000009  A15     : 0x00000000  SAR     : 0x00000016  EXCCAUSE: 0x00000000
19:13:19.857 -> EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffbd
19:13:19.857 ->
19:13:19.857 -> ELF file SHA256: 0000000000000000
19:13:19.857 ->
19:13:19.857 -> Backtrace: 0x400e90f8:0x3ffb1f80 0x400d1526:0x3ffb1fb0 0x400860ed:0x3ffb1fd0
19:13:19.891 ->
19:13:19.891 -> Rebooting...

```

Here's my code:

```cpp
#include <Arduino.h>

#define SbmDisplaySerial Serial1

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);
  Serial.println("Yo v0.0.1! from serial UART 18/19");

  SbmDisplaySerial.begin(9600, SERIAL_8N1);//, 16, 17);

  Serial.print("SbmDisplaySerial is ");
  Serial.println(SbmDisplaySerial);
}

int _loop = 1;

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("Loop #"); Serial.println(_loop++);
  delay(1000);

  if (!SbmDisplaySerial.available()) {
    delay(2000);
    Serial.println("No byte avail from the UART, looping…");
    return;
  }

   int b = 0;

   Serial.print("Synching with message limit (waiting for 0xA5 (165) header byte): ");
   int i=0;
   do {
     delay(10);
     b = SbmDisplaySerial.read();
     Serial.print(b);
     Serial.print(" ");
     if (i8==0) Serial.println();
      i++;
   }
   while(b!=0xa5);

  Serial.println("Ok, packet started!");
  Serial.print("Received bytes: ");
  Serial.print(b);
  Serial.print(" ");

  int soc = 0;
  int voltage = 0;
  int current = 0;
  int capacity = 0;

  for(int i=1; i<16; i++) {
    b = SbmDisplaySerial.read()&0xff;

    Serial.print(b);
    Serial.print(" ");

    switch(i) {
      case  0: Serial.print("Header byte 0xA5");
        voltage = 0;
        current = 0;
        capacity = 0;
      break;
      case  1: soc = b; Serial.print("(SoC: ");  Serial.print(soc); Serial.print("%) "); break;

      case  2: voltage = b<<8; break;
      case  3: voltage |= b;  Serial.print("(");  Serial.print(float(voltage)*0.01); Serial.print("V) "); break;

      case  4: capacity = b<<24; break;
      case  5: capacity = b<<16; break;
      case  6: capacity = b<<8; break;
      case  7: capacity |= b;  Serial.print("(");  Serial.print(float(capacity)*0.001); Serial.print("A.h) "); break;

      case  8: current = b<<24; break;
      case  9: current = b<<16; break;
      case 10: current = b<<8; break;
      case 11: current |= b;  Serial.print("(");  Serial.print(float(current)*0.001); Serial.print("A) "); break;

      //case 12: current = b<<8; break;
      //case 13: current = b<<8; break;
      //case 10: current |= b;  Serial.print("(TOA: ");  Serial.print(float(current)*0.001); Serial.print("Seconds) "); break;
    }

    if (!SbmDisplaySerial.available()){
      delay(2000);
      Serial.print(" No more byte prior reaching 16 bytes, looping…");

      break;
    }
  }

  Serial.println("Waiting for next packet");
  delay(10000);

}
```
*[UPDATE]*
When ran on Arduino, I get typical logs as follows:

```
11:20:18.217 -> Yo v0.0.1! from serial UART 18/19
11:20:18.217 -> SbmDisplaySerial is 1
11:20:18.217 -> Loop #1
11:20:19.204 -> Synching with message limit (waiting for 0xA5 (165) header byte): 0
11:20:19.204 -> 0 0 0 0 165 Ok, packet started!
11:20:19.275 -> Received bytes: 165 28 (SoC: 28%) 4 251 (12.75V) 0 0 54 248 (14.07A.h) 255 255 0 0 (0.00A) 0 0 0 0 Waiting for next packet
11:20:29.263 -> Loop #2
11:20:30.266 -> Synching with message limit (waiting for 0xA5 (165) header byte): 0
11:20:30.266 -> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 165 Ok, packet started!
11:20:30.508 -> Received bytes: 165 28 (SoC: 28%) 4 251 (12.75V) 0 0 182 0 (46.59A.h) 0 0 0 0 (0.00A) 0 0 0 0 Waiting for next packet

```

body: Here is what I've ended up with: I dropped Serial1 as I did not find anyway to make it run and I switched to Serial2, where everything works as expected.


body:
```c++
#define SER1_RX 35
#define SER1_TX 32

void setup()
{
    Serial.begin(115200);      //
 Serial.setDebugOutput(1);

    // For Serial1, be sure to set the communication port.
 Serial1.begin(115200, SER1_RX, SER1_TX); // set the communication port
}
```


message:
ESP8266 with HC05 : expecting to receive more bytes then the 63 received

I'm trying to read a Ant BMS 32H with a ESP8266 and a HC05 module.
BMS is sending 146 bytes when asking for these by sending DB DB 0 0 0 0 (HEX)
I did test with my android phone and the app 'Serial Bluetooth Terminal' and I receive/see the 146 bytes.
When doing this with the ESP8266/HC05 I only receive 63 bytes.
I saw already that I shouldn't use delays before reading the serial buffer, as this could cause buffer overflows.

I have no clue on what the reason could be ... hope someone has some more knowledge then I do ...
Please see my code I use ( I didn't post the Process_Data() routine as this one is called afterwards )
Initial I tried without the cosmetic visualization ( extra lines of code taking cpu cycle to execute) and it give the same result

The result I receive :

    ---------------------------------------------------
    Sending request (6 bytes) : DB DB 0 0 0 0  Answer :
    00:AA 01:55 02:AA 03:FF 04:02 05:7B 06:08 07:43 08:08 09:43
    10:08 11:47 12:08 13:41 14:08 15:3B 16:08 17:45 18:08 19:41
    20:08 21:46 22:08 23:43 24:08 25:41 26:08 27:43 28:08 29:46
    30:08 31:44 32:08 33:41 34:08 35:49 36:08 37:41 38:08 39:43
    40:08 41:42 42:08 43:3F 44:08 45:3F 46:08 47:46 48:08 49:44
    50:08 51:4F 52:08 53:38 54:08 55:3E 56:08 57:47 58:08 59:47
    60:08 61:45 62:08
    Bytes received : 63

My .ino :

    #include <SoftwareSerial.h>;
    SoftwareSerial EEBlue(12, 13); // RX | TX // AT command mode
    // byte message[] = {0x5A, 0x5A, 0x5A, 0x00, 0x00, 0x5A, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
    byte message[] = {0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 };
    byte bms[147]; // 82 + 65 = 147 bytes
    int i;
    int x;
    int highbyte, lowbyte;
    uint16_t a16bitvar;
    unsigned int BattSOCG;
    float BattPowerG;

    void setup()
    {
      Serial.begin(115200);
      delay(500);
      EEBlue.begin(38400);  //38400 Baud for AT commands , set by command : AT+UART=38400,1,0 or AT+UART=9600,1,0
      delay(500);
      Serial.println();
      Serial.println("Serial and Bluetooth started.");
      Serial.println(); Serial.println("");
    }

    void loop()
    {
      AskBMSData();
      GetBMSData();
      Process_Data();
      delay(3000);
    }

    // ---------------------------------------------------------
    void AskBMSData()
    {
      Serial.print("Sending request ("); Serial.print(sizeof(message)); Serial.print(" bytes) : ");
      for (i=0; i<sizeof(message); i++)
      {
        Serial.print(message[i], HEX);
        Serial.print(" ");
      }

      EEBlue.write(message, sizeof(message));
    }

    void GetBMSData()
    {
      Serial.println(" Answer :");
      // Feed any received bluetooth data to Terminal.
      i=0;
      while (EEBlue.available()) {
        bms[i]= EEBlue.read();
        if(i<10) Serial.print("0");
        Serial.print(i); Serial.print(":");
        if(bms[i]<16) Serial.print("0");
        Serial.print(bms[i], HEX);
        Serial.print(" ");
        x = (i+5)/10; x = 10*x-1; if(i==x) Serial.println();
        i++;
      }
      Serial.println(); Serial.print("Bytes received : ");Serial.println(i);Serial.println();
    }

    // --------------------------------------------------------

**Code changed based on Chrisl's response to :**

    void GetBMSData()
    {
      Serial.println(" Answer :");
      // Feed any received bluetooth data to Terminal.
      i=0;
      if (EEBlue.available()) {
          while (i<146) {
            bms[i]= EEBlue.read();
            i++;
            }
      }

      for (z=0; z<i; z++) {
        if(z<10) Serial.print("0");
        Serial.print(z); Serial.print(":");
        if(bms[z]<16) Serial.print("0");
        Serial.print(bms[z], HEX);
        Serial.print(" ");
        x = (z+5)/10; x = 10*x-1; if(z==x) Serial.println();
      }
      Serial.println(); Serial.print("Bytes received : ");Serial.println(i);Serial.println();
    }

with result :

    ---------------------------------------------------
    Sending request (6 bytes) : DB DB 0 0 0 0  Answer :
    00:AA 01:55 02:AA 03:FF 04:02 05:71 06:08 07:23 08:08 09:23
    10:08 11:26 12:08 13:21 14:08 15:1B 16:08 17:25 18:08 19:1E
    20:08 21:27 22:08 23:24 24:08 25:1E 26:08 27:23 28:08 29:27
    30:08 31:25 32:08 33:1F 34:08 35:28 36:08 37:21 38:08 39:22
    40:08 41:22 42:08 43:1C 44:08 45:23 46:08 47:28 48:08 49:26
    50:08 51:31 52:08 53:17 54:08 55:1E 56:08 57:28 58:08 59:29
    60:08 61:25 62:08 63:FF 64:FF 65:FF 66:FF 67:FF 68:FF 69:FF
    70:FF 71:FF 72:FF 73:FF 74:FF 75:FF 76:FF 77:FF 78:FF 79:FF
    80:FF 81:FF 82:FF 83:FF 84:FF 85:FF 86:FF 87:FF 88:FF 89:FF
    90:FF 91:FF 92:FF 93:FF 94:FF 95:FF 96:FF 97:FF 98:FF 99:FF
    100:FF 101:FF 102:FF 103:FF 104:FF 105:FF 106:FF 107:FF 108:FF 109:FF
    110:FF 111:FF 112:FF 113:FF 114:FF 115:FF 116:FF 117:FF 118:FF 119:FF
    120:FF 121:FF 122:FF 123:FF 124:FF 125:FF 126:FF 127:FF 128:FF 129:FF
    130:FF 131:FF 132:FF 133:FF 134:FF 135:FF 136:FF 137:FF 138:FF 139:FF
    140:FF 141:FF 142:FF 143:FF 144:FF 145:FF
    Bytes received : 146

body:
I see 2 things, that might give you problems. First the one with a higher chance of being the important point:

You use

    while (EEBlue.available())

in your `GetBMSData()` function. With serial (and especially over a packeted protocol like bluetooth) the sender might introduce pauses in the transmission of the data (for example when it needs to wait for more data, doing other tasks than sending or when a bluetooth packet ends and a new one must be send). You cannot control if and when these pauses happen. They might be big enough so that your `while()` loop can clear the internal buffer of the `SoftwareSerial` library without already having received the full message.

With serial you cannot think of a message as one block of data, which arrives together at the same time. You need to account for it to take its time. For example you could loop inside that function, until you have received the full message. That would fit to your current code structure. Something like this:

    while(i<146){
      if(EEBlue.available()){
        bms[i]= EEBlue.read();
        i++;
      }
    }

Note: If for whatever reason less than the expected number of bytes is send, this code will block forever - or until it received that many bytes.

Or - if you want to do it non-blocking (also rewriting the rest of the code), then you could just allocate a buffer big enough for the whole message and only place the bytes as they arrive inside that buffer. The rest (like sending the data out over `Serial` can then be done, when you have all the data bytes of the message. In this case you don't need a `while` loop, since the `loop()` function already handles the looping. You just test on very loop iteration if data is available and read it. After you read a byte you test for the message being complete. If yes, do the printing and processing.

---

The second problem is not that probable, but I still want to include that here. You are doing quite some printing inside the `while` loop, printing at least 6 bytes for every received byte. Serial can take some time and if it takes to long you can fill up your buffer in the background, effectively loosing data. I would suggest using the `while` loop to just `read()` the bytes and save them in your array. The printing can then be done after the full message was received. For the human reading the Serial printout it will not be different, but you can prevent losing data this way.


message:
Cannot change pointer for port in main loop

I am testing on an Arduino UNO. I want to use timer1 and interrupts to create various LED patterns. The LEDs may span multiple ports i.e PORTB and PORTD. I want to use a "volatile uint8_t*" pointer to store whether to toggle a pin on PORTB or PORTD i.e have the pointer store &PORTB or &POINTD. And then use it as necessary. However, once set, I cannot seem to be able to change the pointer in the loop.

Some more details:
I'm using timer1 in CTC mode (clear on compare match) and making use of both OCR1A and OCR1B interrupts.
When output compare A interrupt matches, the led is turned on and a flag is set for the main loop to change leds.
When output compare B interrupt matches, the led is turned off.
The switch statement works and the led pins can be changed i.e next_led and current_led, however, the next_port and current_port statements are ignored in the main loop.
The led pin change works when changing from case 3 to case 1 (when they are both PORTB), but when changing the next_port variable to PORTD this is completely ignored.

At the very beginning of the code, if I initialize current_port and next_port with &PORTD, then just PORTD led will light up and the main loop will not change the current_port and next_port variable to &PORTB.

I have tried using volatile uint16_t* for the next_port and current_port and that doesn't work, either.

What am I doing wrong?

```
int red_led = 9;    //PORTB 1
int green_led = 10; //PORTB 2

int led3 = 5;       //PORTD 5

volatile uint8_t current_led = 1; //port number of led
volatile uint8_t next_led = 1;

volatile uint8_t *current_port = &PORTB;
volatile uint8_t *next_port = &PORTB;

int counter = 0;
volatile int change_led_flag = 0;
volatile uint8_t led_state = 1;

uint16_t ocr1a_val = 10000-1; //determines period. 16MHz clock, Prescaler=8, 10000-1 ticks = 5ms period (200Hz)
uint16_t ocr1b_val = 9900-1; //determines duty cycle (99% for 10000 ticks)

void setup() {
  pinMode(red_led, OUTPUT);
  pinMode(green_led, OUTPUT);
  pinMode(led3, OUTPUT);

  TCCR1A = 0;
  TCCR1B = 0;

  //set CTC mode
  TCCR1B |= (1<<WGM12);

  //set OCR1A value
  OCR1A = ocr1a_val;
  //set OCR1B value
  OCR1B = ocr1b_val;

  //set pre-scaler to 8
  TCCR1B |= (1 << CS11);

  //enable output compare interrupts
  TIMSK1 |= (1 << OCIE1A);
  TIMSK1 |= (1 << OCIE1B);

  sei();
}

void loop() {
  if(change_led_flag == 1){
  change_led_flag = 0;
  current_led = next_led; //set the current led to what was just turned on
  current_port = next_port; //this statement doesn't do anything.
  switch (led_state) {
    case 1:
      led_state = 2;
      next_led = 2;
      next_port = &PORTB; //this statement doesn't do anything
      break;
    case 2:
      led_state = 3;
      next_led = 5;
      next_port = &PORTD; //this statement doesn't do anything
      break;
    case 3:
      led_state = 1;
      next_led = 1;
      next_port = &PORTB; //this statement doesn't do anything
      break;
    } //end switch statement
  } //end if

} //end loop()

//turn on next_led and set change_led_flag
ISR(TIMER1_COMPA_vect){
  *next_port |= (1 << next_led); //turn on led
  change_led_flag = 1; //set flag to update next led
}

//turn off current_led
ISR(TIMER1_COMPB_vect){
  *current_port &= ~(1 << current_led); //turn off led
}

```

body:
I don't *know* this is your problem, but it is *a* problem in any case.
The pointer itself, not just what it points to, would also need to be volatile qualified. That is:

```c++
volatile uint8_t *volatile current_port = &PORTB;
volatile uint8_t *volatile next_port = &PORTB;
```

The `volatile` after the pointer declarator (the `*`) determines the `volatile` quality of the pointer itself.  The `volatile` that you already had prior to the declarator is just qualifying what is pointed-to, the port in this case, which is needed for similar reasons.

Without the pointer itself being `volatile`, you can't expect to changes to it to be reflected correctly between the ISR contexts and the normal main line of execution that runs `setup`, `loop` and and most everything else.  The compiler/optimizer may assume since it can't see any way to get to code that can change the value that the value is therefore not changing.  ISR dispatches are outside its field of view.

Also in the when you update `next_port` outside of the ISR, you probaly should make sure interrupts are off while you update it:

```c++
noInterrupts();
next_port = &PORTB;
interrupts();
```

Because the pointer value is a two-byte address, if you don't disable the interrupts while assigning it your ISR can be dispatched midway through the assignment when the pointer object isn't yet valid.  I say *should* above, because in your situation the addresses that happen to be used for ports may all have the same upper byte value. It's a good habit to be in regardless.


message:
Failure using references variables in classes

**Theoretical Q**

I'm having some trouble when using a referenced variable in a class.

`Class A` have an `int a=0`. `Class B` has an instance of `Class A`, and referencing `int &a=A.a`, and in the same manner `Class C` has an instance of `Class B` and `int &a=B.a`. Code crashed when trying to update `a` variable when using C instance.

**Relvant Example**

I'm creating a library for TFT+Touch 2.4 screen, to handle buttons more easily.

Libraries `XPT2046_Touchscreen` and `Adafruit_ILI9341` are included here, but initiated in main `.ino` file for easier handling in `loop` and more control in main code.

**1) `MessageTFT`**

A "basic" class was created, called `MessageTFT`. This class creates the graphics, and stores its geometrical properties and color as shown below.

**2) `ButtonTFT`**

`ButtonTFT` based on `MessageTFT` adding touch capabilities to it. Its geometrical and color parameters are referenced to `MessageTFT`. When creating a `button` instance, user defines its properties but, actually it is referenced to `MessageTFT`.

`ButtonTFT` and `MessagesTFT` works as expected. For example a button is defined in `.ino`:

    ButtonTFT butt;

and defined in `void setup()`:

      butt.a = 200;
      butt.b = 60;
      butt.xc = tft.width() / 2;
      butt.yc = tft.height() - butt.b / 2;
      butt.txt_size = 1;
      butt.face_color = ILI9341_CASET;
      butt.txt_color = ILI9341_DARKGREY;
      butt.border_color = ILI9341_MAGENTA;
      butt.roundRect = false;
      butt.createButton("Press!");

and in `void loop()`:

      if (ts.touched())
      {
        TS_Point p = ts.getPoint();
        if (butt.checkPress(p))
          {
            Serial.print("Pressed");
          }
      }

**3) `buttonArrayTFT`**

Evolving to `buttonArrayTFT`, which spreads up to 8 buttons x and y centered on screen. Here again using same way to reference relevant properties (in `buttonArrayTFT` each button's size and position are not defined by user, but calculated to optimize size and position). Now variable are referenced to a `ButtonTFT` instance, for example `&txt_size = _button0.txt_size` as shown below.

Since `txt_size` is common for all button members in that array of buttons, it is referenced for all buttons later in code.

Also `buttonArrayTFT` works as expected, when defining its instance as:

    char *a[] = {"All Windows", "Saloon", "Room", "Specific"};
    buttonArrayTFT mainWindows;

and created:

      mainWindows.create_array(4, 1, a);

as a 4X1 button array with text for each button as in `a`.

**The Problem (code crashes)**

when trying to pass a value for any of referenced parameter ( taking `txt_size` as an example ):

    mainWindows.txt_size = 3;          // <----- This
    mainWindows.create_array(4, 1, a);

While when doing same thing when initiating a button (see up ), I use same way to update button's text size (which is refenced to `MessageTFT` ).

What may be the reason for that ??

Guy

`.h` file:

    #ifndef TFT_GUI_h
    #define TFT_GUI_h

    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_ILI9341.h>
    #include <XPT2046_Touchscreen.h>

    /* Screen calibration */
    #define TS_MIN_X 350
    #define TS_MIN_Y 350
    #define TS_MAX_X 3800
    #define TS_MAX_Y 3800
    /* ~~~~~~~~~~~~~~~~~ */

    /* For Wemos Mini and TFT screen 2.4" */
    #define TFT_CS D0
    #define TFT_DC D8
    #define TFT_RST -1
    #define TS_CS D3
    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

    const uint8_t _pos_corr_factor_x = 3;
    const uint8_t _pos_corr_factor_y = 4;

    extern XPT2046_Touchscreen ts; /* Touch screen */
    extern Adafruit_ILI9341 tft;   /* Graphics */

    class MessageTFT
    {
    public:
      int xc = 0;
      int yc = 0;
      uint8_t a = 0;
      uint8_t b = 0;
      uint8_t txt_size = 3;
      uint8_t border_thickness = 1;
      char txt_buf[20];
      bool roundRect = true;
      uint8_t screen_rotation = 0;
      uint16_t face_color = ILI9341_GREENYELLOW;
      uint16_t txt_color = ILI9341_BLACK;
      uint16_t border_color = ILI9341_RED;
      Adafruit_ILI9341 *TFT[1];

    public:
      MessageTFT(Adafruit_ILI9341 &_tft = tft);
      void createMSG(char *txt);
      void clear_screen(uint8_t c = 0);

    private:
      void _put_text(char *txt);
      void _drawFace();
      void _drawBorder();
    };

    class ButtonTFT
    {
    public:
      /* Following vars belong to MSG class*/
      MessageTFT MSGwindow;
      int &xc = MSGwindow.xc;
      int &yc = MSGwindow.yc;
      uint8_t &a = MSGwindow.a;
      uint8_t &b = MSGwindow.b;
      uint8_t &txt_size = MSGwindow.txt_size;
      uint8_t &screen_rotation = MSGwindow.screen_rotation;
      uint16_t &face_color = MSGwindow.face_color;
      uint16_t &txt_color = MSGwindow.txt_color;
      uint16_t &border_color = MSGwindow.border_color;
      bool &roundRect = MSGwindow.roundRect;
      char *txt_buf = MSGwindow.txt_buf;
      /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

      XPT2046_Touchscreen *TS[1];

    public:
      ButtonTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
      void createButton(char *txt);
      bool wait4press();
      bool checkPress(TS_Point &p);

    private:
      int _tft_x, _tft_y;

    private:
      void _put_text();
      void _press_cb();
      /* fucntions below converts touchscreen values to TFT coordinates */
      void _conv_ts_tft(TS_Point &p);
      bool _check_press_geometry(TS_Point &p);
      int _TS2TFT_x(int px);
      int _TS2TFT_y(int py);
    };

    class buttonArrayTFT
    {
    public:
      buttonArrayTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
      void create_array(uint8_t R, uint8_t C, char *but_txt[]);
      uint8_t checkPress(TS_Point &p);

    public:
      uint8_t &txt_size = _button0.txt_size;
      uint16_t &txt_color = _button0.txt_color;
      uint16_t &border_color = _button0.border_color;
      bool &roundRect = _button0.roundRect;
      int shift_array = 0;

    private:
      ButtonTFT _button0;
      ButtonTFT _button1;
      ButtonTFT _button2;
      ButtonTFT _button3;
      ButtonTFT _button4;
      ButtonTFT _button5;
      ButtonTFT _button6;
      ButtonTFT _button7;
      ButtonTFT *_buttons[8] = {&_button0, &_button1, &_button2, &_button3,
                                &_button4, &_button5, &_button6, &_button7};

    private:
      uint8_t _num_items = 0;
    };

    #endif

**Edit1: How Constructors are defined in `.cpp` file**

    MessageTFT::MessageTFT(Adafruit_ILI9341 &_tft)
    {
      TFT[0] = &_tft; // <--- stored in a pointer
    }

and

    ButtonTFT::ButtonTFT(XPT2046_Touchscreen &_ts, Adafruit_ILI9341 &_tft) : MSGwindow(_tft)
    {
      MSGwindow.TFT[0] = &_tft;
      TS[0] = &_ts;
    }

and

    buttonArrayTFT::buttonArrayTFT(XPT2046_Touchscreen &_ts, Adafruit_ILI9341 &_tft)
        : _button0(_ts, _tft), _button1(_ts, _tft), _button2(_ts, _tft),
          _button3(_ts, _tft), _button4(_ts, _tft), _button5(_ts, _tft),
          _button6(_ts, _tft), _button7(_ts, _tft)
    {
      _button0.MSGwindow.TFT[0] = &_tft;
      _button0.TS[0] = &_ts;
    }

body:
I'm not sure what value this is going to have for Arduino users, but here goes. Your question seem to be an over-complicated form of this the following:

*My code:*
```c++
struct MessageTFT {uint8_t txt_size = 3;};

struct ButtonTFT {
  MessageTFT MSGwindow;
  uint8_t &txt_size = MSGwindow.txt_size;
};

struct buttonArrayTFT {
  uint8_t &txt_size = _button0.txt_size;
  ButtonTFT _button0;
};

buttonArrayTFT bat;

void setup() {
  Serial.begin(9600);
  Serial.println(F("\n\n\nStart."));
}

void loop() {
  Serial.println(bat.txt_size++, DEC);
  delay(1000);
}
```

My question:

*Why does this crash? ...or not print the correct value? or whatever.*

I don't *think* I'm straw-manning (for lack of better term) your question.  But, the question is kind of a mess, so this a best-effort response to it.
If I've clarified the question to the point of being off-topic, so be it. If I do have the correct distillation, if nothing else what people can get out of this is that your questions here can usually be made simpler.

The declared order of members in a class is relevant to the order of initialization; there's more to it than just that. In any case, `_button0` has not been initialized prior to your `uint8_t &txt_size = _button0.txt_size;` The mechanism underlying a member reference in a class is basically that of a pointer.  You are essentially copying an uninitialized pointer out of `_button0` and into the `txt_size` member of `buttonArrayTFT`; that is the `uint8_t &txt_size = MSGwindow.txt_size` has not yet been executed.

You can fix this by doing nothing more than reordering the members like so:

```c++
struct buttonArrayTFT {
  ButtonTFT _button0;
  uint8_t &txt_size = _button0.txt_size;
};
```

Now `uint8_t &txt_size = MSGwindow.txt_size;` in `ButtonTFT` executes prior to `uint8_t &txt_size = _button0.txt_size;` in `buttonArrayTFT`.

This will fix the problem as I've presented. Should you do this? I'm not sure. But then that's not what was asked anyway. Still, you may be better served by getting rid reference members or converting them to inline functions that return a reference type. Or any number of other strategies.

At a minimum this is a problem your code has.


message:
Comments change compiled behavior (sysTickHook weak reference override)

I have a very simple routine that lights up the built-in LED (pin 13) when a system tick timer fires off its interrupt.

I override the weak reference to `int sysTickHook(void)` found in `hooks.c`. I found that in generalfor this to work I need to use `extern "C"` linkage

The part that is bewildering is that this interrupt fires off fine **without** `extern "C"` **if** there are the comments above it as shown below. This is the minimal reproducible example I can find.  Can someone explain this?

I'm using the plain old Arduino IDE 1.8.16.

```c
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {}

// {          -- if you remove this line sysTickHook will not be called
// extern "C" -- if you remove this line sysTickHook will not be called
int sysTickHook()
{
  digitalWrite(13,HIGH);
  return 0;
}
```

body:
The problem is the preprocessor in the IDE. It's not clever enough to work out the `extern "C"` when adding function prototypes.

With your comments you end up with:

```c++
#include <Arduino.h>
#line 1 "/home/matt/t/t.ino"
#line 1 "/home/matt/t/t.ino"
void setup();
#line 6 "/home/matt/t/t.ino"
void loop();
#line 10 "/home/matt/t/t.ino"
 extern "C" int sysTickHook(); // << The extern gets added here from the comment
#line 1 "/home/matt/t/t.ino"
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {}

// {          -- if you remove this line sysTickHook will not be called
// extern "C" -- if you remove this line sysTickHook will not be called
int sysTickHook()
{
  digitalWrite(13,HIGH);
  return 0;
}
```

It finds the `extern` in the comment and thinks it's real code. If you remove the comment markers it ends up with broken code, as you have a stray `{` in there. If you remove the comments entirely you end up with the function in the C++ linkage, which changes the function name internally and doesn't then override the weak function. The same happens if you remove just the first comment.

Basically having those comments breaks the preprocessor in such a way that it works.  The proper way of doing it is:

```c++
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {}

extern "C" {
  int sysTickHook()
  {
    digitalWrite(13,HIGH);
    return 0;
  }
}
```